找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1414|回复: 9
收起左侧

51单片机定时器C语言宏定义为什么设置这样?

[复制链接]
ID:1055345 发表于 2022-12-11 17:55 | 显示全部楼层 |阅读模式
一个51单片机的定时器C语言程序,想问一下,为什么时间和闹钟的时分秒是这样定义的,还有这个99没看懂
#define SHISHE shi,99,99
#define FENSHE 99,fen,99
#define MIAOSHE 99,99,miao
#define NAO_S nao_s,99,99         
#define NAO_F 99,nao_f,99
#define NAO_M 99,99,nao_m

图像 001.png
回复

使用道具 举报

ID:883242 发表于 2022-12-12 12:59 | 显示全部楼层
这里面什么都也看不出来,要看引用这些宏定义的代码。
回复

使用道具 举报

ID:1055345 发表于 2022-12-12 21:11 | 显示全部楼层
Hephaestus 发表于 2022-12-12 12:59
这里面什么都也看不出来,要看引用这些宏定义的代码。

代码是这些,麻烦看一下
  1. #include"reg52.h"
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. #define ulong unsigned long
  5. #define XIANSHI shi,fen,miao  
  6. #define SHISHE shi,99,99         //99是任意一个数,用于后面条件检测
  7. #define FENSHE 99,fen,99
  8. #define MIAOSHE 99,99,miao
  9. #define NAO_S nao_s,99,99           //闹钟的宏
  10. #define NAO_F 99,nao_f,99
  11. #define NAO_M 99,99,nao_m     //宏定义结束

  12. sbit key1=P3^0;                                   //定义按键所连51单片机的引脚
  13. sbit key2=P3^1;
  14. sbit key3=P3^2;

  15. sbit duan_1 =P2^0;                   //虽然声明是duan但是其实是用来位选的
  16. sbit duan_2 =P2^1;
  17. sbit duan_3 =P2^2;
  18. sbit duan_4 =P2^3;
  19. sbit duan_5 =P2^4;
  20. sbit duan_6 =P2^5;
  21. sbit huxiled=P2^6;                  //呼吸灯
  22. sbit nzled=P3^3;                  //D2灯用来指示设置的闹钟时间到

  23. sbit BEEP=P1^5;

  24. uchar shijian[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};         

  25. uchar shi,fen,miao,nao_s=0,nao_f=0,nao_m=15,num_1=0,num_2=0,b=1,c=0;
  26. uchar a=0,n=0;

  27.                                           
  28.                        
  29. void delayms(uint x)                        
  30. {
  31.         uint a,b;
  32.         for(a=x;a>0;a--)
  33.                 for(b=110;b>0;b--);            //延时1ms   
  34. }

  35. void xianshi(uchar S,F,M)                   //时间和闹钟显示函数
  36. {
  37.         uchar shi_1,shi_2,fen_1,fen_2,miao_1,miao_2;

  38.         shi_1=S/10;shi_2=S%10;
  39.         fen_1=F/10;fen_2=F%10;
  40.         miao_1=M/10;miao_2=M%10;
  41.        
  42.         if(S==99) {shi_1=10;shi_2=10;}//和设置按键有关,为了单独显示某一时或者分、秒。
  43.         if(F==99) {fen_1=10;fen_2=10;}
  44.         if(M==99) {miao_1=10;miao_2=10;}

  45.         duan_1=1;P0=shijian[shi_1];delayms(5);duan_1=0;          //位选
  46.         duan_2=1;P0=shijian[shi_2];delayms(5);duan_2=0;
  47.         duan_3=1;P0=shijian[fen_1];delayms(5);duan_3=0;
  48.         duan_4=1;P0=shijian[fen_2];delayms(5);duan_4=0;
  49.         duan_5=1;P0=shijian[miao_1];delayms(5);duan_5=0;
  50.         duan_6=1;P0=shijian[miao_2];delayms(5);duan_6=0;


  51. }

  52. void keyscan()
  53. {
  54.         uint time=0;
  55.         if(key1==0)
  56.         {
  57.                 while(!key1)
  58.                 {
  59.                         time++;
  60.                         if(time>40000){a=5;break;} //这是一个长按进入闹钟模式设置键
  61.                 }
  62.                 if(time<39999)       
  63.                 a++;
  64.         }
  65.         if(key2==0)                                                   //key2控制时间加
  66.         {

  67.                 delayms(90);

  68.                 if(key2==0)
  69.                 {
  70.                         if(a==1) {delayms(90);shi++;if(shi==24) shi=0;}       
  71.                         if(a==2) {delayms(90);fen++;if(fen==60) fen=0;}
  72.                         if(a==3) {delayms(90);miao++;if(miao==60) miao=0;}

  73.                         if(a==6) {delayms(90);nao_s++;if(nao_s==24) nao_s=0;}
  74.                         if(a==7) {delayms(90);nao_f++;if(nao_f==60) nao_f=0;}
  75.                         if(a==8) {delayms(90);nao_m++;if(nao_m==60) nao_m=0;}
  76.                 }while(!key2);
  77.         }
  78.         if(key3==0)                                                  //key3控制时间减
  79.         {
  80.                 delayms(90);
  81.                 if(key3==0)
  82.                 {
  83.                         if(a==1) {delayms(90);shi--;if(shi>=0&&shi<24);else shi=23;}
  84.                         if(a==2) {delayms(90);fen--;if(fen>=0&&fen<60);else fen=59;}
  85.                         if(a==3) {delayms(90);miao--;if(miao>=0&&miao<60);else miao=59;}

  86.                         if(a==6) {delayms(90);nao_s--;if(nao_s>=0&&nao_s<24);else nao_s=23;}
  87.                         if(a==7) {delayms(90);nao_f--;if(nao_f>=0&&nao_f<60);else nao_f=59;}
  88.                         if(a==8) {delayms(90);nao_m--;if(nao_m>=0&&nao_m<60);else nao_m=59;}       
  89.                 }while(!key3);
  90.         }
  91.         if(a==4||a==9){a=0;}                         //归零
  92. }

  93. void init()
  94. {
  95.         nzled=0;   //给D2灯一个预设熄灭
  96.         TMOD=0x01; //工作方式1

  97.         TH0=0x4C;  //定时器T0  定时19ms
  98.         TL0=0x00;
  99.         ET0=1;
  100.         ET1=1;

  101.         TH1=0xc0; //定时器T1   定时56ms
  102.         TL1=0x00;
  103.         ET0=1;
  104.         ET1=1;
  105.         TR1=1;

  106.         EA=1;         //总中断
  107. }

  108. void nzhongled()                          //闹钟和时间一致时让数码管和D2一起在将近10秒内频闪不断
  109. {
  110.         uint g;
  111.         for(g=0;g<23;g++)
  112.         {
  113.                 nzled=1;                                  //闹钟显示灯开始闪烁
  114.                 delayms(200);
  115.                 xianshi(XIANSHI);
  116.             nzled=0;
  117.                 delayms(200);
  118.                 xianshi(XIANSHI);
  119.                 BEEP=~BEEP;              //取反输出到喇叭的信号
  120.                        
  121.                
  122.         }       
  123. }

  124. void main()
  125. {
  126.        
  127.         init();
  128.         while(1)
  129.         {       
  130.                 switch(a)
  131.                 {       
  132.                         case 0:TR0=1;keyscan();xianshi(XIANSHI);break;
  133.                         case 1:TR0=0;keyscan();xianshi(SHISHE);break;//中断关闭,时间停止
  134.                         case 2:keyscan();xianshi(FENSHE);break;
  135.                         case 3:keyscan();xianshi(MIAOSHE);break;
  136.                         case 5:;
  137.                         case 6:keyscan();xianshi(NAO_S);break;
  138.                         case 7:keyscan();xianshi(NAO_F);break;
  139.                         case 8:keyscan();xianshi(NAO_M);break;
  140.                 }
  141.                 if(a==0&&(nao_s==shi&&nao_f==fen&&nao_m==miao))
  142.                 {
  143.                         nzhongled();         //闹钟与时间一致进入nzhongled函数
  144.                        
  145.                 }

  146.         }
  147. }

  148. void zhongduan1() interrupt 1                //精确计时           定时器中断T0
  149. {
  150.         TH0=0x4C;
  151.         TL0=0x00;
  152.         num_1++;
  153.         if(num_1==20)
  154.         {
  155.                 num_1=0;
  156.                 miao++;
  157.                 if(miao==60)
  158.                 {
  159.                         miao=0;
  160.                         fen++;
  161.                         if(fen==60)
  162.                         {
  163.                                 fen=0;
  164.                                 shi++;
  165.                                 if(shi==24) shi=0;       
  166.                         }
  167.                 }
  168.         }
  169. }

  170. void zhongduan2() interrupt 3       
  171. //呼吸灯程序,具体体现为D1灯,
  172. //在proteus中无呼吸效果猜测是因为proteus模拟时每次刷新每帧是0.05秒太久

  173. {
  174.         TH1=0xc0;
  175.         TL1=0x00;
  176.         num_2++;
  177.         if(b<=6)
  178.         {
  179.                 if(num_2<b) huxiled=1;
  180.                 else huxiled=0;
  181.         }
  182.         else
  183.         {
  184.                 if((num_2+6)<b) huxiled=0;
  185.                 else huxiled=1;       
  186.         }
  187.         if(num_2==6)
  188.         {
  189.                 num_2=0;c++;
  190.                 if(c==4)
  191.                 {
  192.                         b++;c=0;
  193.                         if(b==13) b=0;
  194.                 }
  195.         }
  196. }
复制代码
回复

使用道具 举报

ID:77589 发表于 2022-12-13 10:53 | 显示全部楼层
首先,要明白宏是在编译之前,编译器按照宏定义作替换。既然是这样,去替换一下就明白了啊!
把xianshi(XIANSHI);替换下就成了xianshi(shi,fen,miao); 其中shi,fen,miao不是程序中定义的全局变量吗?这就是正常显示时间啊。
把xianshi(SHISHE);替换下就成了xianshi(shi,99,99); 一下就明白是正常显示小时,把分钟和秒钟显示成99。
剩下的自己分析..........
回复

使用道具 举报

ID:332130 发表于 2022-12-13 12:27 | 显示全部楼层
说实话,写了好几年的单片机了,这种宏定义头一次见,NB,学到了!之前都是用结构体写的
回复

使用道具 举报

ID:1055345 发表于 2022-12-13 13:06 | 显示全部楼层
Longan.Wang 发表于 2022-12-13 10:53
首先,要明白宏是在编译之前,编译器按照宏定义作替换。既然是这样,去替换一下就明白了啊!
把xianshi(XI ...
  1. if(S==99) {shi_1=10;shi_2=10;}//和设置按键有关,为了单独显示某一时或者分、秒。
  2.         if(F==99) {fen_1=10;fen_2=10;}
  3.         if(M==99) {miao_1=10;miao_2=10;}
复制代码

你好,我还想问一下,这段代码是如何让数码管单独显示某一时,或者分,或者秒的
回复

使用道具 举报

ID:161164 发表于 2022-12-13 13:35 | 显示全部楼层
muchenxi 发表于 2022-12-13 13:06
你好,我还想问一下,这段代码是如何让数码管单独显示某一时,或者分,或者秒的

2022-12-13_133403.png
回复

使用道具 举报

ID:1055345 发表于 2022-12-13 19:35 | 显示全部楼层

我网上查了,这个P0的调用是对数码管进行消影用的,我还是没搞清楚他如何使时,分,秒单独显示
回复

使用道具 举报

ID:1055345 发表于 2022-12-14 14:43 | 显示全部楼层
Longan.Wang 发表于 2022-12-13 10:53
首先,要明白宏是在编译之前,编译器按照宏定义作替换。既然是这样,去替换一下就明白了啊!
把xianshi(XI ...

感谢回复讲解
回复

使用道具 举报

ID:1055345 发表于 2022-12-14 14:45 | 显示全部楼层

谢谢回复,刚看懂
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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