当前位置:   article > 正文

No7 蓝桥杯单片机实践之定时器的应用

No7 蓝桥杯单片机实践之定时器的应用

1 回顾:

程序编写结构还是中断函数结构的写法,只是由于定时器涉及的寄存器较多,中断初始条件函数中条件也就随之增多。

void  函数名()

{

主要写一些初始化变量。(基本的就是3.1~3.5所涉及的寄存器的初值条件设定)

}

void  函数名() interrupt  中断号

{

就是写时间到后执行什么。(但是为了中断的实时性,有时只写只写中断状态的标志,紧急事件用另一个函数来写,后续实践篇代码有讲)

}

别忘了还要查看对应的中断号

涉及的寄存器要查看手册,通常会涉及到:

高低位寄存器

TMOD寄存器

中断寄存器

TCON寄存器

2 实践

2.1 任务

2.2 思路

涉及的模块:

这里涉及到了LED操作,故HC138接到4通道,才能是控制LED灯的,只有L1和L8两个灯,可以用sbit标出来,可读性比较强。

用到了定时,故定时的结构需要写出来。

在定时结构中,题目要求是Time0,查询资料手册,涉及的寄存器有如下,并写入代码: 

L1灯单位是0.5秒,L8单位是5秒,两者成一个倍数关系,故只需要一个初值即可,以0.5秒为初值,但一个定时器运行完依次最多为65535us,即65.532ms,

                                              需要0.5s即500ms即500000us,

故可以每次计时50000us,定时器运行10次,就到达了0.5s, 定时器运行100次,就到达了5秒。

按照之前所提的公式: TH0 = (65535 - 50000) / 256;
                                     TL0 =  (65535 - 50000) % 256;

  1. void Init_Time0()
  2. {
  3. TMOD = 0x01;
  4. TH0 = (65535 - 50000) / 256;
  5. TL0 = (65535 - 50000) % 256;
  6. TR0 = 1;
  7. EA = 1;
  8. ET0 = 1;
  9. }

然后在中断服务函数上判断是否到达0.5s,到达了进行L1操作

在进一步判断是否到达5s,到达了进行L8操作。

2.3 完整代码:

这里解释以下:

(1)判断定时器运行10次和100次可以用一个变量累加来判断。然后取余操作判断是否达到了每一个10次,当达到100次时,变量清零重计数

(2)在中断中L1和L8的闪烁操作用的是取反:

为什么可以这样呢?中断程序是这样的,刚刚提到定时器运行10次才到达0.5s,默认L1初始为1,即不点亮,当定时器运行了10次才能到达0.5s,注意在这十次中,每一次,都进入了中断服务函数,但是执行到了count++后就不再执行下去,因为没满足if条件,故这段时间L1一直是熄灭的,熄灭时间为(0~9次),刚好10次,0.5秒。当执行第十次时,满足第一个if条件,到达0.5s,那么L1取反为0,点亮。在第11到第19次中,同样,每一次,都进入了中断服务函数,但是执行到了count++后就不再执行下去,因为没满足if条件,故在这段时间内L1一直=0,即L1一直是点亮状态,这段点亮持续了多久呢?(第10次到第19次),刚好10次,故点亮了0.5s。直到第20次,又满足了第一个if条件,L1取反为1,熄灭。

这就是在中断中可以用取反来表示LED闪烁的原因。

  1. #include "stc15f2k60s2.h"
  2. sbit L1 = P0^0;
  3. sbit L8 = P0^7;
  4. void selectHC138(unsigned int n)
  5. {
  6. switch(n)
  7. {
  8. case 0:
  9. P2 = (P2 & 0x1f) | 0x00; break;
  10. case 1:
  11. P2 = (P2 & 0x1f) | 0x20; break;
  12. case 2:
  13. P2 = (P2 & 0x1f) | 0x40; break;
  14. case 3:
  15. P2 = (P2 & 0x1f) | 0x60; break;
  16. case 4:
  17. P2 = (P2 & 0x1f) | 0x80; break;
  18. case 5:
  19. P2 = (P2 & 0x1f) | 0xa0; break;
  20. case 6:
  21. P2 = (P2 & 0x1f) | 0xc0; break;
  22. case 7:
  23. P2 = (P2 & 0x1f) | 0xe0; break;
  24. }
  25. }
  26. void Init_Time0()
  27. {
  28. TMOD = 0x01;
  29. TH0 = (65535 - 50000) / 256;
  30. TL0 = (65535 - 50000) % 256;
  31. TR0 = 1;
  32. EA = 1;
  33. ET0 = 1;
  34. }
  35. unsigned char count = 0;
  36. void Time0() interrupt 1
  37. {
  38. TH0 = (65535 - 50000) / 256;
  39. TL0 = (65535 - 50000) % 256;
  40. count ++;
  41. if (count % 10 == 0)
  42. {
  43. L1 = ~L1;
  44. }
  45. if (count %100 == 0)
  46. {
  47. L8 = ~L8;
  48. count = 0;
  49. }
  50. }
  51. void close() //关闭外设
  52. {
  53. selectHC138(5);
  54. P0 = 0x00;
  55. selectHC138(4);
  56. P0 = 0xff;
  57. }
  58. void main()
  59. {
  60. close();
  61. Init_Time0();
  62. selectHC138(4);
  63. while(1)
  64. {
  65. }
  66. }

3 进阶版实践

3.1 任务

3.2 思路

这里涉及到多种模块:

定时器 :故定时器结构得写下来

数码管计时: 故要数码管得动态变化:数码管内容表(0~F,-) 数码管函数(包括内容和位置),数码管显示函数(显示什么内容),延时函数,HC138选择通道。

独立按键的使用:跳帽接到对应位置。由于只用了两个独立按键,可用sbit表示出来,要写个独立按键函数,判断是否按下。

这里主要的核心是定时器怎么设置:

题目要求设计秒表,分—秒—毫秒。

最小单位为50ms,即数码管最后两位每加1代表每加50ms,即01=50ms,02=100ms。

又1s= 1000ms  ,最小单位为50ms,故数码管最后两位加到20就为1s,秒的两个位置(s位)+1,且数码管最后两位(ms位)清零。

同理,1min=60s,当秒位加到60,清零,min位+1。

数码管显示动态显示对应的位置,由于分—秒—毫秒都是各占两位,如用除和区域可得到各自的十位和个位。

3.3完整代码

注意:     

TR0 = ~TR0;     //表停止计时

  1. #include "stc15f2k60s2.h"
  2. sbit S4 = P3^3;
  3. sbit S5 = P3^2;
  4. void selectHC138(unsigned int n)
  5. {
  6. switch(n)
  7. {
  8. case 0:
  9. P2 = (P2 & 0x1f) | 0x00; break;
  10. case 1:
  11. P2 = (P2 & 0x1f) | 0x20; break;
  12. case 2:
  13. P2 = (P2 & 0x1f) | 0x40; break;
  14. case 3:
  15. P2 = (P2 & 0x1f) | 0x60; break;
  16. case 4:
  17. P2 = (P2 & 0x1f) | 0x80; break;
  18. case 5:
  19. P2 = (P2 & 0x1f) | 0xa0; break;
  20. case 6:
  21. P2 = (P2 & 0x1f) | 0xc0; break;
  22. case 7:
  23. P2 = (P2 & 0x1f) | 0xe0; break;
  24. }
  25. }
  26. void Delay(unsigned char t)
  27. {
  28. while(t--);
  29. }
  30. code unsigned char SMG_Table[] =
  31. {
  32. 0xc0, //0
  33. 0xf9, //1
  34. 0xa4, //2
  35. 0xb0, //3
  36. 0x99, //4
  37. 0x92, //5
  38. 0x82, //6
  39. 0xf8, //7
  40. 0x80, //8
  41. 0x90, //9
  42. 0x88, //A
  43. 0x83, //b
  44. 0xc6, //C
  45. 0xa1, //d
  46. 0x86, //E
  47. 0x8e, //F
  48. 0xbf //-
  49. };
  50. unsigned char t_min = 0;
  51. unsigned char t_s = 0;
  52. unsigned char t_ms = 0;
  53. //==============================Timer============
  54. void InitTime0()
  55. {
  56. TMOD = 0x01;
  57. TH0 = (65535-50000) / 256;
  58. TL0 = (65535-50000) % 256;
  59. TR0 = 1;
  60. ET0 = 1;
  61. EA = 1;
  62. }
  63. void Time0() interrupt 1
  64. {
  65. TH0 = (65535-50000) / 256;
  66. TL0 = (65535-50000) % 256;
  67. t_ms++;
  68. if (t_ms == 20)
  69. {
  70. t_s++;
  71. t_ms = 0;
  72. if (t_s == 60)
  73. {
  74. t_min++;
  75. t_s = 0;
  76. }
  77. }
  78. if (t_min == 99)
  79. {
  80. t_ms = 0;
  81. t_s = 0;
  82. t_min = 0;
  83. }
  84. }
  85. //==============================================
  86. void showSMG(unsigned char position, unsigned char number)
  87. {
  88. selectHC138(6);
  89. P0 = 0x01 << position;
  90. selectHC138(7);
  91. P0 = SMG_Table[number];
  92. }
  93. void SMGDisplay()
  94. {
  95. showSMG(0,t_min/10);
  96. Delay(500);
  97. showSMG(1,t_min%10);
  98. Delay(500);
  99. showSMG(2,16);
  100. Delay(500);
  101. showSMG(3,t_s/10);
  102. Delay(500);
  103. showSMG(4,t_s%10);
  104. Delay(500);
  105. showSMG(5,16);
  106. Delay(500);
  107. showSMG(6,t_ms/10);
  108. Delay(500);
  109. showSMG(7,t_ms%10);
  110. Delay(500);
  111. }
  112. //void SMGDelay(unsigned char t)
  113. //{
  114. // while(t--)
  115. // {
  116. //
  117. // }
  118. //}
  119. void Key()
  120. {
  121. if(S4 == 0) //stop
  122. {
  123. Delay(50);
  124. if(S4 == 0)
  125. {
  126. TR0 = ~TR0; //停止计时
  127. while(S4 == 0)
  128. {
  129. SMGDisplay();
  130. }
  131. }
  132. }
  133. if(S5 == 0) // clear to 0
  134. {
  135. Delay(50);
  136. if(S5 == 0)
  137. {
  138. t_ms = 0;
  139. t_s = 0;
  140. t_min = 0;
  141. while(S5 == 0)
  142. {
  143. SMGDisplay();
  144. }
  145. }
  146. }
  147. }
  148. void close()
  149. {
  150. selectHC138(5);
  151. P0 = 0x00;
  152. selectHC138(4);
  153. P0 = 0xff;
  154. }
  155. void main()
  156. {
  157. close();
  158. InitTime0();
  159. while(1)
  160. {
  161. SMGDisplay();
  162. Key();
  163. }
  164. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/233391
推荐阅读
相关标签
  

闽ICP备14008679号