找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 919|回复: 0
打印 上一主题 下一主题
收起左侧

单片机定时器0+MXA7219数码管显示+AT24C02时钟断电累计工作计时 源程序

[复制链接]
跳转到指定楼层
楼主
ID:370682 发表于 2022-5-12 08:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include<STC15.h>                   // 引用标准库的头文件
  2. #include <intrins.h>      //包含_nop_()函数定义的头文件
  3. sbit SCL=P4^3;
  4. sbit SDA=P4^4;


  5. typedef unsigned char BYTE;
  6. typedef unsigned int WORD;

  7. #define uchar unsigned char // 定义一下方便使用
  8. #define uint unsigned int


  9. unsigned char  cntb=0,n=0,m=0,k=0,ns=0,ks=0,n1=0,k1=0,k2=0;

  10. sbit EC16_KEY=P1^3;        //EC16编码器按键信号输入定义
  11. sbit DIN = P2^7;                    // 串行数据输入
  12. sbit CLK = P2^5;                    // 串行时钟
  13. sbit LOAD = P2^6;                   // 显示数据锁存控制
  14. sbit led=P2^4;

  15. /****************************
  16. MAX7219特殊功能寄存器定义
  17. ************************/        

  18. #define DECODE_MODE   0x09            // 译码模式寄存器
  19. #define INTENSITY     0x0a                 // 亮度寄存器
  20. #define SCAN_LIMIT    0x0b              // 扫描位数寄存器
  21. #define SHUT_DOWN     0x0c               // 低功耗模式寄存器
  22. #define DISPLAY_TEST  0x0f            // 显示测试寄存器       

  23. void Write_Max7219_byte(unsigned char temp);
  24. void Write_Max7219(unsigned char address,unsigned char dat);
  25. void Init_Max7219(void);
  26. void delay_msIIC(unsigned int time);
  27. void Init_interrupt();
  28. void show();
  29. void SGM_showLJ()        ;


  30. void I2cStart();
  31. void I2cStop();
  32. unsigned char I2cSendByte(unsigned char dat);
  33. unsigned char I2cReadByte();
  34. void At24c02Write(unsigned char addr,unsigned char dat);
  35. unsigned char At24c02Read(unsigned char addr);


  36. /****************************
  37.    共阴二位十脚数码管段码数组
  38. ******************************/
  39. uchar code LEDcode[]=
  40. {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b         /*0,1,2,3,4,5,6,7,8,9*/
  41.        
  42. /* 0x77,0x1f,0x4e,0x3d,0x4f,0x47,0x67,0x3e,0xff, */ };     /*A,B,C,D,E,F,P,U,全亮*/


  43. /*******************************************************************************
  44. * 函数名         : Delay10us()
  45. * 函数功能                   : 延时10us
  46. * 输入           : 无
  47. * 输出                  : 无
  48. *******************************************************************************/

  49. void Delay10us_IIC()
  50. {
  51.         unsigned char a,b;
  52.         for(b=1;b>0;b--)
  53.                 for(a=2;a>0;a--);

  54. }
  55. /*******************************************************************************
  56. * 函数名         : I2cStart()
  57. * 函数功能                 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
  58. * 输入           : 无
  59. * 输出                  : 无
  60. * 备注           : 起始之后SDA和SCL都为0
  61. *******************************************************************************/

  62. void I2cStart()
  63. {
  64.         SDA=1;
  65.         Delay10us_IIC();
  66.         SCL=1;
  67.         Delay10us_IIC();//建立时间是SDA保持时间>4.7us
  68.         SDA=0;
  69.         Delay10us_IIC();//保持时间是>4us
  70.         SCL=0;                       
  71.         Delay10us_IIC();               
  72. }
  73. /*******************************************************************************
  74. * 函数名         : I2cStop()
  75. * 函数功能                 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿
  76. * 输入           : 无
  77. * 输出                  : 无
  78. * 备注           : 结束之后保持SDA和SCL都为1;表示总线空闲
  79. *******************************************************************************/

  80. void I2cStop()
  81. {
  82.         SDA=0;
  83.         Delay10us_IIC();
  84.         SCL=1;
  85.         Delay10us_IIC();//建立时间大于4.7us
  86.         SDA=1;
  87.         Delay10us_IIC();               
  88. }
  89. /*******************************************************************************
  90. * 函数名         : I2cSendByte(unsigned char dat)
  91. * 函数功能                 : 通过I2C发送一个字节。在SCL时钟信号高电平期间,保持发送信号SDA保持稳定
  92. * 输入           : num
  93. * 输出                  : 0或1。发送成功返回1,发送失败返回0
  94. * 备注           : 发送完一个字节SCL=0,SDA=1
  95. *******************************************************************************/

  96. unsigned char I2cSendByte(unsigned char dat)
  97. {
  98.         unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。               
  99.         for(a=0;a<8;a++)//要发送8位,从最高位开始
  100.         {
  101.                 SDA=dat>>7;         //起始信号之后SCL=0,所以可以直接改变SDA信号
  102.                 dat=dat<<1;
  103.                 Delay10us_IIC();
  104.                 SCL=1;
  105.                 Delay10us_IIC();//建立时间>4.7us
  106.                 SCL=0;
  107.                 Delay10us_IIC();//时间大于4us               
  108.         }
  109.         SDA=1;
  110.         Delay10us_IIC();
  111.         SCL=1;
  112.         while(SDA)//等待应答,也就是等待从设备把SDA拉低
  113.         {
  114.                 b++;
  115.                 if(b>200)         //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
  116.                 {
  117.                         SCL=0;
  118.                         Delay10us_IIC();
  119.                         return 0;
  120.                 }
  121.         }
  122.         SCL=0;
  123.         Delay10us_IIC();
  124.         return 1;               
  125. }
  126. /*******************************************************************************
  127. * 函数名         : I2cReadByte()
  128. * 函数功能                   : 使用I2c读取一个字节
  129. * 输入           : 无
  130. * 输出                  : dat
  131. * 备注           : 接收完一个字节SCL=0,SDA=1.
  132. *******************************************************************************/

  133. unsigned char I2cReadByte()
  134. {
  135.         unsigned char a=0,dat=0;
  136.         SDA=1;                        //起始和发送一个字节之后SCL都是0
  137.         Delay10us_IIC();
  138.         for(a=0;a<8;a++)//接收8个字节
  139.         {
  140.                 SCL=1;
  141.                 Delay10us_IIC();
  142.                 dat<<=1;
  143.                 dat|=SDA;
  144.                 Delay10us_IIC();
  145.                 SCL=0;
  146.                 Delay10us_IIC();
  147.         }
  148.         return dat;               
  149. }


  150. /*******************************************************************************
  151. * 函数名         : void At24c02Write(unsigned char addr,unsigned char dat)
  152. * 函数功能                   : 往24c02的一个地址写入一个数据
  153. * 输入           : 无
  154. * 输出                  : 无
  155. *******************************************************************************/

  156. void At24c02Write(unsigned char addr,unsigned char dat)
  157. {
  158.         I2cStart();
  159.         I2cSendByte(0xa0);//发送写器件地址
  160.         I2cSendByte(addr);//发送要写入内存地址
  161.         I2cSendByte(dat);        //发送数据
  162.         I2cStop();
  163. }
  164. /*******************************************************************************
  165. * 函数名         : unsigned char At24c02Read(unsigned char addr)
  166. * 函数功能                   : 读取24c02的一个地址的一个数据
  167. * 输入           : 无
  168. * 输出                  : 无
  169. *******************************************************************************/

  170. unsigned char At24c02Read(unsigned char addr)
  171. {
  172.         unsigned char num;
  173.         I2cStart();
  174.         I2cSendByte(0xa0); //发送写器件地址
  175.         I2cSendByte(addr); //发送要读取的地址
  176.         I2cStart();
  177.         I2cSendByte(0xa1); //发送读器件地址
  178.         num=I2cReadByte(); //读取数据
  179.         I2cStop();
  180.         return num;       
  181. }




  182. /******************
  183. MAX7219读数据子程序
  184. *********************/

  185. void Write_Max7219_byte(unsigned char temp)
  186. {
  187.    unsigned char i;
  188.    for(i=0;i<8;i++)                        //移位循环8次
  189.         {
  190.         CLK=0;                                        //清零时钟总线
  191.         DIN=(bit)(temp&0x80);        //每次取高字节亮
  192.         temp=temp<<1;                   //左移移位
  193.         CLK=1;                                   //时钟上升沿,发送高字节位
  194.         }
  195. }

  196.   /*****************************
  197.   MAX7219写数据子程序
  198.   *************************/
  199. void Write_Max7219(unsigned char address,unsigned char dat)
  200. {
  201. LOAD=0;                             //拉低片选线,选中器件
  202. Write_Max7219_byte(address);        //读取高字节地址位
  203. Write_Max7219_byte(dat);                //读取高字节数据位
  204. LOAD=1;                          //读取结束,上升沿锁存数据
  205. }

  206. /*****************************
  207.   MAX7219初始化子程序
  208.   *************************/
  209. void Init_Max7219(void)
  210. {
  211.     Write_Max7219(SHUT_DOWN,0x01);                   //开启正常工作模式
  212.     Write_Max7219(DISPLAY_TEST,0x00);                //选中工作模式
  213.         Write_Max7219(DECODE_MODE,0x00);                //选用全译码模式
  214.         Write_Max7219(SCAN_LIMIT,0x07);                        //8只LED全用
  215.         Write_Max7219(INTENSITY,0x0a);                        //设置初始亮度

  216. }

  217. /*******************************
  218. MAX7219显示子程序
  219. *******************************/

  220. /********************************
  221. ms级延时子程序
  222. ******************************/
  223. void delay_msIIC(unsigned int time)       
  224. {
  225. unsigned int i,j;
  226. for(i=time;i>0;i--)
  227. for(j=125;j>0;j--);
  228. }


  229. void show()                         
  230. {            
  231.                                 At24c02Write(1,n);   //在地址1内写入分钟数据n
  232.                                                                 delay_msIIC(30);  
  233.         Write_Max7219(4,LEDcode[n%10]);                //数码管分钟个位数值分离
  234.                            delay_msIIC(1);   
  235.                     Write_Max7219(3,LEDcode[n%100/10]);        //数码管分钟十位数值分离
  236.                                                                 delay_msIIC(1);  
  237.                                                         At24c02Write(3,k);   //在地址3内写入小时数据k
  238.                                                                 delay_msIIC(30);  
  239.                                 Write_Max7219(2,LEDcode[k%10]);           //数码管小时个位数值分离
  240.                                                                 delay_msIIC(1);                                            
  241.                                 Write_Max7219(1,LEDcode[k%100/10]);        //数码管小时十位数值分离
  242.                                                                 delay_msIIC(1);   


  243. }


  244. /********************************************************
  245.   MAX7219数码管开机累计计时显示分,小时数值分离子程序
  246. ********************************************************/

  247. void SGM_showLJ()                         
  248. {
  249.              
  250.                                
  251.                                             led=0;              //中间小数点信号为低电平
  252.                                         Write_Max7219(4,LEDcode[ns%10]);                  //数码管编码器脉冲计数值个位数值分离
  253.                                                 delay_msIIC(1);
  254.                                         Write_Max7219(3,LEDcode[ns%100/10]);        //数码管编码器脉冲计数值十位数值分离
  255.                          delay_msIIC(1);
  256.                                         Write_Max7219(2,LEDcode[ks%10]);            //数码管编码器脉冲计数值百位数值分离
  257.                                delay_msIIC(1);                                            
  258.                                         Write_Max7219(1,LEDcode[ks%100/10]);        //数码管编码器脉冲计数值千位数值分离
  259.                                           delay_msIIC(1);   
  260. }


  261. /**************************
  262. 定时器0初始化子程序
  263. *****************************/
  264. void Init_interrupt()               
  265. {
  266. TMOD=0X01;
  267. TH0=(65536-46080)/256;         //定时器赋初值11.0592MHZ晶振,赋初值TH0=(65536- 1000*50*(11.0592/12)/256)      50ms
  268. TL0=(65536-46080)/256;

  269. ET0=1;
  270. IT0=1;
  271. IT1=1;
  272. EX0=1;
  273. EX1=1;
  274. EA=1;
  275. }

  276. void t0(void) interrupt 1 using 0
  277. {
  278. TH0=(65536-46080)/256;
  279. TL0=(65536-46080)/256;
  280.   cntb ++;       
  281.    m++;
  282.     if(m==30)         ////m执行30次,led灯1s交替闪烁
  283.     {
  284.          led=~led;
  285.          m=0;
  286.     }
  287.                                   
  288.     if(cntb==1200)         //cntb执行1200次,一分钟时间到
  289.     {
  290.                        
  291.            n=n+1;                          //分钟变量加1操作
  292.            cntb=0;                     //定时器计数变量清零
  293.     }

  294.             if(n>59)                        //分钟 显示大于59秒
  295.           {          
  296.           k=k+1;                           //小时变量加1操作
  297.             n=0;                         //分钟变量清零       
  298.            }
  299.           
  300.               if(k>99)         //时间显示大于99小时
  301.           {          
  302.           k=99;        
  303.            }
  304.    
  305. }

  306. /***************************************************
  307. 函数功能主函数
  308. ***************************************************/
  309. void main(void)
  310. { /**************************
  311.                                                         定义特殊端口功能寄存器
  312.                                                 **************************/
  313.                                                                         P0M0 = 0x00;
  314.                                                                                 P0M1 = 0x00;
  315.                                                                         P2M0 = 0x00;
  316.                                                                                 P2M1 = 0x00;
  317.                                                                         P3M0 = 0x00;
  318.                                                                                 P3M1 = 0x00;       
  319.                                                                         P4M0 = 0x00;
  320.                                                                                 P4M1 = 0x00;       
  321.                                                                         P5M0 = 0x00;
  322.                                                                                 P5M1 = 0x00;       
  323.                                                                         P6M0 = 0x00;
  324.                                                                                 P6M1 = 0x00;       
  325.                                                                
  326.                                                                 Init_interrupt();        //定时器初始化
  327.                        Init_Max7219();                //7219初始化
  328.         /*****************此段程序为开机读取累计工作分钟数据程序************/
  329.                        n1=At24c02Read(1);          //读取EEPROM地址1内的数据保存在n1中
  330.                                                                 delay_msIIC(30);
  331.                       ns=At24c02Read(2);          //读取EEPROM地址2内的数据保存在ns中
  332.                                                           delay_msIIC(30);
  333.                       ns=ns+n1;
  334.                                                                 if(ns>=60)
  335.                                                                 {
  336.                                                                         ns=ns-60;    //累计计时60分钟,累计变量分钟-60,
  337.                                                                         k2=k2+1;      //累计小时数加1
  338.                                                                 }

  339. /*****************此段程序为开机读取累计工作小时数据程序************/
  340.                                                                
  341.                        k1=At24c02Read(3);          //读取EEPROM地址3内的数据保存在k1中
  342.                                                                 delay_msIIC(30);
  343.                       ks=At24c02Read(4);          //读取EEPROM地址4内的数据保存在ks中
  344.                                                           delay_msIIC(30);
  345.                       ks=ks+k1+k2;
  346.                                                                 if(ks>=99)
  347.                                                                         ks=99;    //累计计时99小时
  348.                                                                
  349.                                                                 SGM_showLJ();   //调用累计计时函数
  350.         /******************下列此程序为累计存储分钟变量程序**************/                                                       
  351.                                                                 At24c02Write(2,0);   //在地址2内写入数据0,清除2地址
  352.                       delay_msIIC(30);
  353.                        At24c02Write(2,ns);   //在地址2内写入数据ns
  354.                                                                 delay_msIIC(30);  
  355.                        At24c02Write(1,0);   //在地址1内写入数据0,清除1地址
  356.                                                                 delay_msIIC(30);
  357.                                                                  n=0;             //清零分钟
  358.                                                                
  359.   /******************下列此程序为累计存储分钟变量程序**************/                       
  360.                                                                 At24c02Write(4,0);   //在地址4内写入数据0,清除4地址
  361.                       delay_msIIC(30);
  362.                        At24c02Write(4,ks);   //在地址4内写入数据ks
  363.                                                                 delay_msIIC(30);  
  364.                        At24c02Write(3,0);   //在地址3内写入数据0,清除3地址
  365.                                                                 delay_msIIC(30);         
  366.                                                                  k=0;               //清零小时
  367.                                                                
  368.    while(1)
  369. {
  370.          
  371.                                                 if(EC16_KEY==0)         //检测开机信号
  372.                                          {
  373.                                                                  
  374.                                                 TR0=1;
  375.                   show();                        //调用数码管显示       
  376.                                                                         
  377.                                          }
  378.                                    TR0=0;
  379. }
  380. }

复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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