查看: 1544|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
沙发
发表于 2016-5-28 21:53:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚刚接触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 uchar  unsigned 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[10]={0xFA,0x60,0xD6,0xF4,0x6C,0xBC,0xBE,0xE0,0xFE,0xFC};//显示缓存,数据,每个地址发两次,从高到低,每次发送4位,用于显示个位数字
__saddr uchar disbuff2[7]={0xFA,0x60,0xD6,0xF4,0x6C,0xBC,0xfa};//显示缓存,数据,每个地址发两次,从高到低,每次发送4位,用于显示分钟十位
__saddr uchar disbuff3[3]={0xFA,0x60,0xD6};//显示缓存,数据,每个地址发两次,从高到低,每次发送4位,用于显示小时十位
__saddr uchar col1[7]={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[cnt12]= (col1[cnt12]>>4)|(col1[cnt12]<<4);
    senddata(0x04,col1[cnt12]);
  }
  /*时钟显示程序*/
   
   if(cnt1>15000)//分钟的个位十位显示
   {
    cnt1=0;
    cnt2++;
    cnt4++;
    cnt11=cnt4%10,//计算分钟个位
    cnt12=cnt4/10;//计算分钟十位
    senddata(0x07,disbuff1[cnt11]>>4);
    senddata(0x06,disbuff1[cnt11]);
    senddata(0x05,disbuff2[cnt12]>>4);
    senddata(0x04,disbuff2[cnt12]);
    if(cnt2>59)//小时的个位十位显示
     {
      cnt4=0;
      cnt2=0;
      cnt3++;
      if(cnt3>23) cnt3=0;
      cnt13=cnt3%10;//计算小时个位
      cnt14=cnt3/10;//计算小时十位
      senddata(0x03,disbuff1[cnt13]>>4);
      senddata(0x02,disbuff1[cnt13]>>0);
      senddata(0x01,disbuff3[cnt14]>>4);
      senddata(0x00,disbuff3[cnt14]>>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[cnt13]>>4);
      senddata(0x02,disbuff1[cnt13]);
      senddata(0x01,disbuff3[cnt14]>>4);
      senddata(0x00,disbuff3[cnt14]);
      delayms(yanshi2);
    }
    break;
  case 2:
    {
      senddata(0x07,0);
      senddata(0x06,0);
      senddata(0x05,0);
      senddata(0x04,0);
      delayms(yanshi1);
      senddata(0x07,disbuff1[cnt11]>>4);
      senddata(0x06,disbuff1[cnt11]);
      senddata(0x05,disbuff2[cnt12]>>4);
      senddata(0x04,disbuff2[cnt12]);
      delayms(yanshi2);
    }
    break;
  case 3:__no_operation();break;
  }
      }
  else __no_operation();
    }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表