fhl2397 发表于 2010-1-11 21:49:47

(原创)数字时钟_基于NEC9234与合泰1621

刚刚接触NEC不久,希望和大家共同学习,共同提高,我的QQ:386132185,希望能和更多的网友认识,加我的朋友请标明是学习单片机的。谢谢







#include<io78f9234.h>
#include<intrinsics.h>
//#include<migration.h>
#pragma location = 0X0080
__root const unsigned char XUAN=0X98;//选项字节,设置实用外部高速时钟电路
#define _NOP __no_operation()
#define ucharunsigned char
#define uint   unsigned int
#define clrwdt()WDTM=0x77//屏蔽看门狗
#define BIAS 0X52//LCD1/2偏压,4个COM端_在改程序中命令标志为3为:100,命令代码末尾任意
#define SYSDIS 0X00//关闭系统振荡器和LCD偏压发生器
#define SYSEN 0X02//打开系统振荡器
#define LCDOFF 0X04//关闭LCD偏压发生器
#define LCDON 0X06//开启LCD偏压发生器
#define XTAL 0X28//外部时钟源
#define RC256 0X30//片内RC振荡器0
#define TONEON 0X12//打开声音输出
#define TONEOFF 0X10//关闭声音输出
#define WDTDIS 0X0a//看门狗溢出标志输出失效
#define WDTEN 0X0c//看门狗溢出标志有效
#define NORMAL 0Xc6//普通模式
#define dat P12_bit.no0//数据引脚
#define cs P13_bit.no0//片选引脚
#define wr P4_bit.no5//写信号引脚
#define rd P4_bit.no2//读信号引脚
__saddr char cont,cnt11,cnt12,cnt3=1,cnt13,cnt4,cnt14;
__saddr uchar readdata=0x00,rdata;//用于读数据用
__saddr uchar disbuff1={0xFA,0x60,0xD6,0xF4,0x6C,0xBC,0xBE,0xE0,0xFE,0xFC};//显示缓存,数据,每个地址发两次,从高到低,每次发送4位,用于显示个位数字
__saddr uchar disbuff2={0xFA,0x60,0xD6,0xF4,0x6C,0xBC,0xfa};//显示缓存,数据,每个地址发两次,从高到低,每次发送4位,用于显示分钟十位
__saddr uchar disbuff3={0xFA,0x60,0xD6};//显示缓存,数据,每个地址发两次,从高到低,每次发送4位,用于显示小时十位
__saddr uchar col1={0xab,0x01,0x67,0x45,0xcd,0xcd,0xab};
__saddr uchar cont1;
__saddr uchar pan=1;
__saddr uint cnt1,cnt2;
__saddr uint fen,shi,yanshi1=500,yanshi2=500;
//延时,毫秒级
void delayms(uint ms)//准确延时1ms,当ms=1时
{
uint i,j;
for(i=0;i<ms;i++)
    for(j=0;j<460;j++);
}
//延时,毫秒级
void delaytms(uint ms)//准确延时1ms,当ms=1时
{
TMIF000=1;
uint i,j;
for(i=0;i<ms;i++)
    for(j=0;j<460;j++);
TMIF000=0;
}
//发送数据函数,高位在前发送,用于传送格式代码和地址
void wrhdata(uchar data,uchar cnt)
{
cs=0;
uchar i;
for(i=0;i<cnt;i++)
{
    if((data&0x80)==0)
      dat=0;
    else dat=1;
    __no_operation();
    wr=0;
    __no_operation();
    __no_operation();
    wr=1;
    data<<=1;
}
//cs=1;
}
//发送数据函数,低位在前发送,用于发送数据
void wrldata(uchar data,uchar cnt)
{
cs=0;
uchar i;
for(i=0;i<cnt;i++)
{
    if((data&0x01)==0)
      dat=0;
    else dat=1;
    wr=0;
    __no_operation();
    wr=1;
    data>>=1;
}
//cs=1;
}
//发送命令代码函数
void sendcmd(uchar cmd)
{
cs=0;
__no_operation();
wrhdata(0x80,4);
wrhdata(cmd,8);
__no_operation();
cs=1;
}
//发送普通命令代码函数
void sendcmdNORMAL(uchar cmd)
{
cs=0;
__no_operation();
wrhdata(0x90,4);
wrhdata(cmd,8);
__no_operation();
cs=1;
}
//写入数据函数
void senddata(uchar addr,uchar data)
{
cs=0;
__no_operation();
wrhdata(0xa0,3);
wrhdata(addr<<2,6);
wrldata(data,4);
cs=1;
__no_operation();
}
//16位定时器TM000初始化函数
void init_TM000(void)
{
TMC00=0x00;//禁止定时器
CRC00=0X00;//设定CR000作为比较寄存器使用
CR000=0x007d;//设置计时次数,计时为0.5S/25
PRM00=0XA2;//设定预分频为31.25KHz
TMC00=0X0C;//设定定时器计时完成后自动清零
TMMK000=0;//允许定时器中断
}
//定时器TM000中断服务函数
#pragma vector=INTTM000_vect
__interrupt void INTTM000_Server(void)
{
TMIF000=0;
TMMK80=0;
pan++;
cont++;
cnt1++;
if(cont>125)
{
    cont=0;
    col1= (col1>>4)|(col1<<4);
    senddata(0x04,col1);
}
/*时钟显示程序*/
   
   if(cnt1>15000)//分钟的个位十位显示
   {
    cnt1=0;
    cnt2++;
    cnt4++;
    cnt11=cnt4%10,//计算分钟个位
    cnt12=cnt4/10;//计算分钟十位
    senddata(0x07,disbuff1>>4);
    senddata(0x06,disbuff1);
    senddata(0x05,disbuff2>>4);
    senddata(0x04,disbuff2);
    if(cnt2>59)//小时的个位十位显示
   {
      cnt4=0;
      cnt2=0;
      cnt3++;
      if(cnt3>23) cnt3=0;
      cnt13=cnt3%10;//计算小时个位
      cnt14=cnt3/10;//计算小时十位
      senddata(0x03,disbuff1>>4);
      senddata(0x02,disbuff1>>0);
      senddata(0x01,disbuff3>>4);
      senddata(0x00,disbuff3>>0);
      /*if(cnt3>23)
       {
      cnt3=0;
       }
      else __no_operation();*/
   }
    else __no_operation();
    }
else __no_operation();
}
//定时器TM80初始化函数
void init_TM80(void)
{
TMC80=0x00;//禁止定时器
CR80=50;//设置计时次数
TMC80=0x82;//允许定时器,设置计时频率为31.25KHZ
TMMK80=0;//允许定时器中断
}
//定时器TM80中断服务函数
#pragma vector=INTTM80_vect
__interrupt void INTTM80_Server(void)
{
TMIF80=0;
//TMMK000=0;
}
void main()
{
cs=1;
PCC=0X00;//以下两行为设置cpu时钟为8M
PPCC=0X00;//
WDTM=0X77;//屏蔽看门狗
PM4=0X02;//设置P4口位输入、输出状态
//P4=0x00;//设置P4口初值
MK1=0X85;//屏蔽外部中断3
INTM1=0X01;//设定外部中断3上升沿有效
PMK3=0; //允许外部中断3
PM12_bit.no0=0;//设定数据位输出口状态
P4_bit.no0=1;//点亮背光板
P0=0X07;//设定p0口状态
PM0=0X07;//设定p00,p01,p02为输入端口
PU0=0X07;//p00,p01,p02使用内部上拉电阻
//P0_bit.no3=0;
sendcmd(RC256);
sendcmd(BIAS);
sendcmd(SYSEN);
sendcmd(LCDON);
sendcmdNORMAL(NORMAL);
senddata(0x00,0xfa);
senddata(0x01,0xfa>>4);
senddata(0x02,0xfa);
senddata(0x03,0xfa>>4);
senddata(0x04,0xfb);
senddata(0x05,0xfa>>4);
senddata(0x06,0xfa);
senddata(0x07,0xfa>>4);
init_TM80();
init_TM000();
__enable_interrupt();//开中断
    while(pan)
    {
      //yanshi1=500;
      //yanshi2=500;
      /*按键程序*/
      if(P0<7)//判断设置键是否按下
      {
      yanshi1=0;
      yanshi2=10;
      delayms(10);//消除抖动
      if(P0<7)//判断设置键是否按下
      {
          TMMK000=1;
          switch (P0)
          {
            case 0x00:__no_operation();break;//三键同时按下
            case 0x01:__no_operation();break;//P01\P02同时按下
            case 0x02:__no_operation();break;//P00、P02同时按下
            case 0x03://P02键按下,确定设定的状态,退出设置模式
            {
            pan=0;
            cont1=0;
            TMMK000=0;
            }
            break;
            case 0x04:__no_operation();break;//P01\P00同时按下
            case 0x05://P01键按下,对应按键次数设定数字时钟相应的位,每按键一下,对应的位数字自加1
            {
            __no_operation();
            switch(cont1)
            {
                case 0:__no_operation();break;//确定当前值,退出设定模式,所有数据正常显示
                case 1://修改小时数据,小时数据闪烁
                {
                  yanshi1=0;
                  yanshi2=150;
                  if(cnt3>23) cnt3=0;
                  cnt13=cnt3%10;//计算小时个位
                  cnt14=cnt3/10;//计算小时十位
                  cnt3++;
               }
                   break;
               case 2://修改分钟数据,分钟数据闪烁
               {
                   yanshi1=0;
                   yanshi2=150;
                   if(cnt4>59) cnt4=0,cnt2=0;
                   else cnt2++,cnt4++;
                   cnt11=cnt4%10,//计算分钟个位
                   cnt12=cnt4/10;//计算分钟十位
               }
                  break;
               case 3:__no_operation();break;
            }
            }
            break;
          case 0x06://P00键按下,进入设置时间状态,对应按键的次数,依次设定不同的位
          {
         cont1++;
         if(cont1>3) cont1=0;
         else __no_operation();//yanshi1=500,yanshi2=500;
          }
            break;
          }
      }
      else __no_operation();
      
      }
      else
      {
      yanshi1=500;
      yanshi2=500;
      }
// 相应的修改位闪烁
      if(cont1>0)
      {
      switch(cont1)
{
case 0:__no_operation();break;
case 1:
    {
      senddata(0x03,0);
      senddata(0x02,0);
      senddata(0x01,0);
      senddata(0x00,0);
      delayms(yanshi1);
      senddata(0x03,disbuff1>>4);
      senddata(0x02,disbuff1);
      senddata(0x01,disbuff3>>4);
      senddata(0x00,disbuff3);
      delayms(yanshi2);
    }
    break;
case 2:
    {
      senddata(0x07,0);
      senddata(0x06,0);
      senddata(0x05,0);
      senddata(0x04,0);
      delayms(yanshi1);
      senddata(0x07,disbuff1>>4);
      senddata(0x06,disbuff1);
      senddata(0x05,disbuff2>>4);
      senddata(0x04,disbuff2);
      delayms(yanshi2);
    }
    break;
case 3:__no_operation();break;
}
      }
else __no_operation();
    }
}

yqldt 发表于 2010-1-27 18:17:59

这个好难懂

eleczj 发表于 2012-4-9 11:59:49

{:lol:}{:lol:}{:lol:}
多谢LZ。

lxa0 发表于 2012-4-10 00:02:18

光有代码?
没有硬件图?

powermeter 发表于 2012-8-11 13:51:38

看看了{:smile:}

tangxixiaowu99 发表于 2012-9-29 12:07:10

这个网上好多例子,好长,先看看有没有亮点!

tc34437335 发表于 2012-11-20 23:36:40

没有用多个文件分开来,看起来好累还好NEC9234 只有8K ROM
页: [1]
查看完整版本: (原创)数字时钟_基于NEC9234与合泰1621