找回密码
 立即注册
搜索
热搜: 中医 针灸 咳嗽
查看: 123|回复: 0

2个定时器计时并驱动扫描数码管(无软件延时)

[复制链接]

3706

主题

1

回帖

1万

积分

管理员

积分
11870
发表于 2023-2-6 21:30:39 | 显示全部楼层 |阅读模式
  1. /*
  2. 定时器驱动扫描数码管
  3. T1扫描数码管
  4. T0 负责计时
  5. 全程未使用延时函数
  6. */
  7. #include <reg52.h>

  8. #define Ulong unsigned long
  9. #define Uint  unsigned int
  10. #define Uchar unsigned char

  11. sbit DU = P2 ^ 6; // 数码管段选
  12. sbit WE = P2 ^ 7; // 位选

  13. double code Crystal     = 11.0592; // 晶振频率 设定
  14. double code Clock_Cycle = 12;      // 时钟周期
  15. double Machine_Cycle;              // 机器周期
  16. Ulong Need_time_US;                // 微秒总数量

  17. Ulong Need_time_MS; // 计算溢出的毫秒
  18. Ulong Need_time_S;  // 计算溢出的微秒
  19. Ulong Need_time;    // 定时器0溢出的总数量计算
  20. Ulong Need_time2;   // 定时器1溢出的总数量计算
  21. Ulong display_count = 0, display_count1 = 0;
  22. int val[8]; ///*存储每个位的数字数组变量*/

  23. Uchar code DUtabel[] = {
  24.     0x3F,
  25.     0x06,
  26.     0x5B,
  27.     0x4F,
  28.     0x66,
  29.     0x6D,
  30.     0x7D,
  31.     0x07,
  32.     0x7F,
  33.     0x6F,
  34.     0x77,
  35.     0x7C,
  36.     0x39,
  37.     0x5E,
  38.     0x79,
  39.     0x71,
  40.     0x76,
  41.     0x38,
  42.     0x40,
  43.     0x00,
  44. };

  45. Uchar code WEtabel[] = {
  46.     0x00, // 全亮,补位选空位
  47.     0xFE,
  48.     0xFD,
  49.     0xfb,
  50.     0xf7,
  51.     0xef,
  52.     0xdf,
  53.     0xbf,
  54.     0x7f,
  55. };

  56. void Sys_init();
  57. void showval(Uchar val, Uchar WEval);
  58. void display(int Z);
  59. void T0_Timer_Init(Ulong U_time, int mod, int type);
  60. void T1_Timer_Init(Ulong U_time, int mod, int type);

  61. void delay(Uchar z, int mod);

  62. ///////////////main/////////////////////

  63. void main()
  64. {

  65.     Sys_init();             // 系统初始化
  66.     T1_Timer_Init(5, 2, 0); // T1扫描数码管
  67.     T0_Timer_Init(1, 3, 0); // T0 负责计时
  68.     while (1) {
  69.         // display(display_count);
  70.     }
  71. }

  72. ////////////函数区域//////////////////

  73. /*初始化参数*/
  74. void Sys_init()
  75. {
  76.     Machine_Cycle = 1 / Crystal * Clock_Cycle; // 初始化 机器周期
  77. }

  78. void showval(Uchar val, Uchar WEval)
  79. {

  80.     WE = 1;              // 打开位选锁存
  81.     P0 = WEtabel[WEval]; // 选择位选
  82.     WE = 0;              // 位锁存

  83.     DU = 1;            // 打开段选锁存器
  84.     P0 = DUtabel[val]; // 送数据
  85.     DU = 0;            // 段锁存
  86. }

  87. void display(int Z)
  88. {

  89.     static int i;
  90.     if (i == Z) {
  91.         i = 0;
  92.         return;
  93.     }

  94.     P0 = 0XFF; // 清除段码
  95.     showval(val[i], 8 - i);
  96.     i++;
  97. }

  98. /*
  99. 设置定时器
  100. 参数1数量:   时间数量
  101. 参数2单位: 1.微秒 2.毫秒 3.秒
  102. 参数3模式: 0.定时器 1.计数器
  103. #说明:引脚 计数器0引脚P3*4
  104. */
  105. void T0_Timer_Init(Ulong U_time, int mod, int type)
  106. {

  107.     if (type == 1) // 如果选择计数模式
  108.     {
  109.         TR0 = 1;
  110.         TMOD |= 0X05;
  111.         TH0 = 0;
  112.         TL0 = 0;
  113.     } else { // 如果为定时器模式

  114.         /*时间转换*/
  115.         if (mod == 3) {

  116.             Need_time_US = U_time * 1000 * 1000;

  117.         } else if (mod == 2) {

  118.             Need_time_US = U_time * 1000;

  119.         } else if (mod == 1) {

  120.             Need_time_US = U_time;
  121.         }
  122.         /*设置定时器*/

  123.         Need_time = (Ulong)(Need_time_US / Machine_Cycle) / 65535; // 获得溢出总量

  124.         // 设置中断
  125.         EA   = 1;    // 打开总中断
  126.         ET0  = 1;    // 打开定时器0中断
  127.         TR0  = 1;    // 启动定时器0
  128.         TMOD = 0X01; // 定时器工作模式1,16位定时模式

  129.         TH0 = (Ulong)(65535 - (Ulong)(Need_time_US / Machine_Cycle) % 65535) / 256; //(Need_time_US/Machine_Cycle)%65535 排除溢出位
  130.         TL0 = (Ulong)(65535 - (Ulong)(Need_time_US / Machine_Cycle) % 65535) % 256;
  131.     }
  132. }

  133. void T0_Time() interrupt 1
  134. {
  135.     static Ulong use_count;     // 已经执行的数量
  136.     if (Need_time == use_count) // 判断Need_time总耗微秒数 是不是消耗完  如果消耗完 进入重置阶段
  137.     {
  138.         TH0 = (Ulong)(65535 - (Ulong)(Need_time_US / Machine_Cycle) % 65535) / 256; //(Need_time_US/Machine_Cycle)%65535 排除溢出位
  139.         TL0 = (Ulong)(65535 - (Ulong)(Need_time_US / Machine_Cycle) % 65535) % 256;

  140.         use_count = 0;   // 重置已消耗的数量
  141.         display_count++; // 记录消耗完毕的次数
  142.     } else {             // 如果没消耗完 继续进入下一轮定时中断触发消耗
  143.         use_count++;     // 已消耗的数量加1
  144.         TH0 = 0;         // 清0
  145.         TL0 = 0;         // 清0
  146.     }
  147. }

  148. /*
  149. 设置定时器
  150. 参数1数量:   时间数量
  151. 参数2单位: 1.微秒 2.毫秒 3.秒
  152. 参数3模式: 0.定时器 1.计数器
  153. #说明:引脚 计数器1引脚P3*5
  154. */
  155. void T1_Timer_Init(Ulong U_time, int mod, int type)
  156. {

  157.     if (type == 1) // 如果选择计数模式
  158.     {
  159.         TR1 = 1;
  160.         TMOD |= 0X50;
  161.         TH1 = 0;
  162.         TL1 = 0;
  163.     } else { // 如果为定时器模式

  164.         /*时间转换*/
  165.         if (mod == 3) {

  166.             Need_time_US = U_time * 1000 * 1000;

  167.         } else if (mod == 2) {

  168.             Need_time_US = U_time * 1000;

  169.         } else if (mod == 1) {

  170.             Need_time_US = U_time;
  171.         }
  172.         /*设置定时器*/

  173.         Need_time2 = (Ulong)(Need_time_US / Machine_Cycle) / 65535; // 获得溢出总量

  174.         // 设置中断
  175.         EA   = 1;    // 打开总中断
  176.         ET1  = 1;    // 打开定时器0中断
  177.         TR1  = 1;    // 启动定时器0
  178.         TMOD = 0X10; // 定时器工作模式1,16位定时模式

  179.         TH1 = (Ulong)(65535 - (Ulong)(Need_time_US / Machine_Cycle) % 65535) / 256; //(Need_time_US/Machine_Cycle)%65535 排除溢出位
  180.         TL1 = (Ulong)(65535 - (Ulong)(Need_time_US / Machine_Cycle) % 65535) % 256;
  181.     }
  182. }

  183. void T1_Time() interrupt 3
  184. {
  185.     Ulong use_count1; // 已经执行的数量
  186.     int Zlen = 0;

  187.     if (Need_time2 == use_count1) // 判断Need_time总耗微秒数 是不是消耗完  如果消耗完 进入重置阶段
  188.     {
  189.         TH1        = (Ulong)(65535 - (Ulong)(Need_time_US / Machine_Cycle) % 65535) / 256; //(Need_time_US/Machine_Cycle)%65535 排除溢出位
  190.         TL1        = (Ulong)(65535 - (Ulong)(Need_time_US / Machine_Cycle) % 65535) % 256;
  191.         use_count1 = 0; // 重置已消耗的数量

  192.         display_count1 = display_count;

  193.         while (display_count1 != 0) {
  194.             // 提取n的各个数位上的数
  195.             val[Zlen++] = display_count1 % 10;
  196.             display_count1 /= 10;
  197.         }

  198.         display(Zlen);

  199.         //  display_count1++; // 记录消耗完毕的次数
  200.     } else {          // 如果没消耗完 继续进入下一轮定时中断触发消耗
  201.         use_count1++; // 已消耗的数量加1
  202.         TH1 = 0;      // 清0
  203.         TL1 = 0;      // 清0
  204.     }
  205. }

  206. /*
  207. 延迟函数.
  208. 参数1:z为数量
  209. 参数2:mod为模式
  210. 1:毫秒
  211. 2:秒
  212. */
  213. void delay(Uchar z, int mod)
  214. {
  215.     Ulong i;
  216.     if (mod == 1) {
  217.         for (i = 0; i < z; i++) {

  218.             unsigned char a, b;
  219.             for (b = 102; b > 0; b--)
  220.                 for (a = 3; a > 0; a--)
  221.                     ;
  222.         }
  223.     }

  224.     else if (mod == 2) {
  225.         for (i = 0; i < z * 1000; i++) {
  226.             // 10000us //误差 -0.000000000002us
  227.             unsigned char a, b;
  228.             for (b = 102; b > 0; b--)
  229.                 for (a = 3; a > 0; a--)
  230.                     ;
  231.         }
  232.     }
  233. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|私人站点 ( 冀ICP备2023028127号-2 )

GMT+8, 2025-4-20 01:55 , Processed in 0.082451 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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