找回密码
 立即注册
楼主: yuyy1989

冲哥32位8051视频学习日记-已看到27集-实验箱到了

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-7 21:43:06 | 显示全部楼层
本帖最后由 yuyy1989 于 2023-5-7 21:48 编辑

第9集,数码管的静态使用
数码管是用led组成的,通过控制不同位置的led的亮灭来显示图案
  1. //没有数码管调试用,所以不知最终效果如何
  2. #define KEY0 P32
  3. #define KEY1 P33
  4. #define BEEP P54
  5. #define LEDSEG_COM_PIN0 P40 //共阳共阴控制脚
  6. #define LEDSEG_COMON_TYPE 0  //共阳共阴控制脚导通电平 0拉低导通 1拉高导通
  7. #define LEDSEG_LED_PORT P2 //假设bit0-bi7与abcdefg小数点依次相连
  8. #define LEDSEG_LEDON_TYPE 0 //led控制脚导通电平 0拉低导通 1拉高导通
  9. /*
  10.   a
  11.   ----
  12. f| g |b
  13.   ----
  14. e|   |c
  15.   ----   .h
  16.   d
  17. 字符 h  g  f  e  d  c  b  a  16进制数值
  18. 0   0  0  1  1  1  1  1  1   0x3F
  19. 1   0  0  0  0  0  1  1  0   0x06
  20. 2   0  1  0  1  1  0  1  1   0x5B
  21. 3   0  1  0  0  1  1  1  1   0x4F
  22. 4   0  1  1  0  0  1  1  0   0x66
  23. 5   0  1  1  0  1  1  0  1   0x6D
  24. 6   0  1  1  1  1  1  0  1   0x7D
  25. 7   0  0  0  0  0  1  1  1   0x07
  26. 8   0  1  1  1  1  1  1  1   0x7F
  27. 9   0  1  1  0  1  1  1  1   0x6F
  28. -   0  1  0  0  0  0  0  0   0x40
  29. A   0  1  1  1  0  1  1  1   0x77
  30. b   0  1  1  1  1  1  0  0   0x7C
  31. c   0  1  0  1  1  0  0  0   0x58
  32. C   0  0  1  1  1  0  0  1   0x39
  33. d   0  1  0  1  1  1  1  0   0x5E
  34. E   0  1  1  1  1  0  0  1   0x79
  35. F   0  1  1  1  0  0  0  1   0x71
  36. H   0  1  1  1  0  1  1  0   0x76
  37. J   0  0  0  1  1  1  1  0   0x1E
  38. L   0  0  1  1  1  0  0  0   0x38
  39. o   0  1  0  1  1  1  0  0   0x5C
  40. P   0  1  1  1  0  0  1  1   0x73
  41. q   0  1  1  0  0  1  1  1   0x67
  42. U   0  0  1  1  1  1  1  0   0x3E
  43. t   0  1  1  1  1  0  0  0   0x78
  44. r   0  0  1  1  0  0  1  1   0x33
  45. 将对应的数值写入寄存器即可显示相应符号
  46. */
  47. const uint8_t ledsegnumdatas[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
  48. uint8_t currentdat = 0;
  49. uint8_t ledsegcount = 0;//0-9计数
  50. uint8_t ledsegbeepcount = 0;//蜂鸣器鸣叫计数
  51. //控制数码管亮灭
  52. void yuyy_segled_onoff(uint8_t on)
  53. {
  54.     if(on > 1)
  55.     {
  56.         on = 1;
  57.     }
  58.     #if(LEDSEG_COMON_TYPE == 0)
  59.     on = 1- on;
  60.     #endif
  61.     LEDSEG_COM_PIN0 = on;
  62. }
  63. //刷新数码管
  64. void yuyy_segled_showdat(uint8_t dat)
  65. {
  66.     #if(LEDSEG_LEDON_TYPE == 0)
  67.     dat = ~dat;
  68.     #endif
  69.     LEDSEG_LED_PORT = dat;
  70. }
  71. //控制小数点显示
  72. void yuyy_segled_showdot(uint8_t show)
  73. {
  74.     if(show)
  75.     {
  76.         currentdat |= 0x80;
  77.     }
  78.     else
  79.     {
  80.         currentdat &= 0x7F;
  81.     }
  82. }
  83. //显示字符,传入符号对应的数值
  84. void yuyy_segled_shownumchar(uint8_t num)
  85. {
  86.     currentdat &= 0x80;
  87.     currentdat |= num;
  88.     yuyy_segled_showdat(currentdat);
  89. }
  90. //显示0-9数字
  91. void yuyy_segled_show09num(uint8_t num)
  92. {
  93.     if(num < 10)
  94.     {
  95.         yuyy_segled_shownumchar(ledsegnumdatas[num]);
  96.     }
  97. }
  98. //按下一次KEY0,数码管计数+1
  99. void key0down_ledsegcount()
  100. {
  101.     if(KEY0 == 0)
  102.     {
  103.         delay_ms(10);//去抖
  104.         if(KEY0 == 0)
  105.         {
  106.             if((keydown&0x01) == 0)
  107.             {
  108.                 keydown |= 0x01;
  109.                 ledsegcount++;
  110.                 if(ledsegcount > 9)
  111.                 {
  112.                     ledsegcount = 0;
  113.                 }
  114.                 ledsegbeepcount = 0;
  115.                 yuyy_segled_show09num(ledsegcount);
  116.             }
  117.         }
  118.     }
  119.     else
  120.     {
  121.         keydown &= 0xFE;
  122.     }
  123. }   
  124. //按下一次KEY1,蜂鸣器按照数码管显示响
  125. void key1down_ledsegcountbeep()
  126. {
  127.     if(KEY1 == 0)
  128.     {
  129.         delay_ms(10);//去抖
  130.         if(KEY1 == 0)
  131.         {
  132.             if((keydown&0x02) == 0)
  133.             {
  134.                 keydown |= 0x02;
  135.                 ledsegbeepcount = ledsegcount;
  136.             }
  137.         }
  138.     }
  139.     else
  140.     {
  141.         keydown &= 0xFD;
  142.     }
  143.     if (ledsegbeepcount)//由while改为if减少阻塞时间
  144.     {
  145.         BEEP = 1;
  146.         delay_ms(150);
  147.         BEEP = 0;
  148.         delay_ms(150);
  149.         ledsegbeepcount--;
  150.     }
  151.    
  152. }
  153. //在main函数进入while(1)前先点亮LED
  154. yuyy_segled_onoff(1);
  155. yuyy_segled_show09num(ledsegcount);
  156. //在while(1)中调用
  157. key0down_ledsegcount();
  158. key1down_ledsegcountbeep();
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-9 08:57:58 | 显示全部楼层
本帖最后由 yuyy1989 于 2023-5-9 08:59 编辑

第10集,数码管的动态显示
多位数码管的同时显示是一位一位不停切换实现的,和视频的原理一样利用了人眼的视觉残留现象,最好保证整个数码管刷新耗时在20ms以内
没有试验箱也没有数码管,下面的代码没有经过验证
  1. #define LEDSEG_NUM 8 //数码管位数
  2. #define LEDSEG_COM_PORT P4 //共阳共阴控制端口,假设bit0-bi7控制1-8位
  3. #define LEDSEG_COMON_TYPE 0  //共阳共阴控制脚导通电平 0拉低导通 1拉高导通
  4. #define LEDSEG_LED_PORT P2 //假设bit0-bi7与abcdefg小数点依次相连
  5. #define LEDSEG_LEDON_TYPE 0 //led控制脚导通电平 0拉低导通 1拉高导通
  6. #define BEEP P54
  7. /*
  8.   a
  9.   ----
  10. f| g |b
  11.   ----
  12. e|   |c
  13.   ----   .h
  14.   d
  15. 字符 h  g  f  e  d  c  b  a  16进制数值
  16. 0   0  0  1  1  1  1  1  1   0x3F
  17. 1   0  0  0  0  0  1  1  0   0x06
  18. 2   0  1  0  1  1  0  1  1   0x5B
  19. 3   0  1  0  0  1  1  1  1   0x4F
  20. 4   0  1  1  0  0  1  1  0   0x66
  21. 5   0  1  1  0  1  1  0  1   0x6D
  22. 6   0  1  1  1  1  1  0  1   0x7D
  23. 7   0  0  0  0  0  1  1  1   0x07
  24. 8   0  1  1  1  1  1  1  1   0x7F
  25. 9   0  1  1  0  1  1  1  1   0x6F
  26. -   0  1  0  0  0  0  0  0   0x40
  27. A   0  1  1  1  0  1  1  1   0x77
  28. b   0  1  1  1  1  1  0  0   0x7C
  29. c   0  1  0  1  1  0  0  0   0x58
  30. C   0  0  1  1  1  0  0  1   0x39
  31. d   0  1  0  1  1  1  1  0   0x5E
  32. E   0  1  1  1  1  0  0  1   0x79
  33. F   0  1  1  1  0  0  0  1   0x71
  34. H   0  1  1  1  0  1  1  0   0x76
  35. J   0  0  0  1  1  1  1  0   0x1E
  36. L   0  0  1  1  1  0  0  0   0x38
  37. o   0  1  0  1  1  1  0  0   0x5C
  38. P   0  1  1  1  0  0  1  1   0x73
  39. q   0  1  1  0  0  1  1  1   0x67
  40. U   0  0  1  1  1  1  1  0   0x3E
  41. t   0  1  1  1  1  0  0  0   0x78
  42. r   0  0  1  1  0  0  1  1   0x33
  43. 将对应的数值写入寄存器即可显示相应符号
  44. */
  45. const uint8_t ledsegnumdatas[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
  46. uint8_t currentdatas[LEDSEG_NUM] = {0};
  47. uint8_t currentseg = 0;
  48. uint16_t segcunter = 0;//计数0-9999 每10ms+1
  49. uint8_t segtimer = 0;//0-10
  50. uint8_t segkeycount = 0;//0初始状态 1计数 2停止
  51. //选择数码管的一位0-7
  52. void yuyy_segled_select(uint8_t seg)
  53. {
  54.     uint8_t segdat = 0;
  55.     if (seg < 8)
  56.     {
  57.         segdat = 1<<seg;
  58.         
  59.         #if(LEDSEG_COMON_TYPE == 0)
  60.         segdat = ~segdat;
  61.         #endif
  62.         LEDSEG_COM_PORT = segdat;
  63.     }
  64.    
  65. }
  66. //数码管显示字符
  67. void yuyy_segled_showdat(uint8_t dat)
  68. {
  69.     #if(LEDSEG_LEDON_TYPE == 0)
  70.     dat = ~dat;
  71.     #endif
  72.     LEDSEG_LED_PORT = dat;
  73. }
  74. //刷新显示
  75. void yuyy_segled_show()
  76. {
  77.     if(currentseg > 7)
  78.     {
  79.         currentseg = 0;
  80.     }
  81.     yuyy_segled_select(currentseg);
  82.     yuyy_segled_showdat(currentdatas[currentseg]);
  83.     currentseg++;
  84. }
  85. //控制小数点显示,bit0-1每个bit代表一个小数点
  86. void yuyy_segled_showdots(uint8_t dots)
  87. {
  88.     uint8_t i=0;
  89.     while (i<8)
  90.     {
  91.         if(dots&0x01)
  92.         {
  93.             currentdatas[i] |= 0x80;
  94.         }
  95.         else
  96.         {
  97.             currentdatas[i] &= 0x7F;
  98.         }
  99.         dots= dots>>1;
  100.         i++;
  101.     }
  102.    
  103. }
  104. //设置指定位置的字符,传入符号对应的数值
  105. void yuyy_segled_shownumcharat(uint8_t num, uint8_t pos)
  106. {
  107.     if(pos < 8)
  108.     {
  109.         currentdatas[pos] &= 0x80;
  110.         currentdatas[pos] |= num;
  111.     }
  112. }
  113. //设置指定位置的数字
  114. void yuyy_segled_show09numat(uint8_t num, uint8_t pos)
  115. {
  116.     if(num < 10)
  117.     {
  118.         yuyy_segled_shownumcharat(ledsegnumdatas[num],pos);
  119.     }
  120.     if(num == 0xFF)
  121.     {
  122.         yuyy_segled_shownumcharat(0,pos);
  123.     }
  124. }
  125. //显示4位数字 num 0000-9999 count数字位数 pos起始位置
  126. void yuyy_segled_shwownums(uint16_t num,uint8_t count,uint8_t pos)
  127. {
  128.     uint8_t i=0,d=0;
  129.     while (count<5 && i<count)
  130.     {
  131.         d = num % 10;
  132.         yuyy_segled_show09numat(d,pos+i);
  133.         num = num / 10;
  134.         i++;
  135.     }
  136. }
  137. //按下一次KEY0,开始计数,再按停止,再按重置
  138. void key0down_ledsegcounter()
  139. {
  140.     if(KEY0 == 0)
  141.     {
  142.         delay_ms(10);//去抖
  143.         if(KEY0 == 0)
  144.         {
  145.             if((keydown&0x01) == 0)
  146.             {
  147.                 keydown |= 0x01;
  148.                 if(segkeycount == 0)
  149.                 {
  150.                     //开始计数
  151.                     segkeycount = 1;
  152.                 }
  153.                 else if(segkeycount == 1)
  154.                 {
  155.                     //停止计数
  156.                     segkeycount = 2;
  157.                 }
  158.                 else
  159.                 {
  160.                     //重置
  161.                     segkeycount = 0;
  162.                     segcunter = 0;
  163.                     yuyy_segled_shwownums(segcunter,4,0);
  164.                 }
  165.             }
  166.         }
  167.     }
  168.     else
  169.     {
  170.         keydown &= 0xFE;
  171.     }
  172.     if(segkeycount == 1 && segtimer == 10)
  173.     {
  174.         if(segcunter < 9999)
  175.         {
  176.             segcunter++;
  177.             yuyy_segled_shwownums(segcunter,4,0);
  178.         }
  179.         segtimer = 0;
  180.     }
  181.     yuyy_segled_show();
  182.     delay_ms(1);
  183.     segtimer++;
  184. }  
  185. //实战小练main部分
  186. yuyy_segled_shwownums(1000,4,4);
  187. yuyy_segled_shwownums(0,4,0);
  188. yuyy_segled_showdots(0x44);
  189. while(1)
  190. {
  191.         key0down_ledsegcounter();
  192. }
  193. //课后练习简易时钟
  194. uint16_t clockms = 0; //毫秒
  195. uint8_t clocksec = 0; //秒
  196. uint8_t clockmin = 0; //分
  197. uint8_t clockhour = 0; //时
  198. void clocktest()
  199. {
  200.     if(clockms == 1000)
  201.     {
  202.         clocksec++;
  203.         clockms = 0;
  204.         yuyy_segled_shwownums(clocksec,2,0);
  205.     }
  206.     if(clocksec == 60)
  207.     {
  208.         clockmin++;
  209.         clocksec = 0;
  210.         yuyy_segled_shwownums(clocksec,2,0);
  211.         yuyy_segled_shwownums(clockmin,2,3);
  212.     }
  213.     if(clockmin == 60)
  214.     {
  215.         clockhour++;
  216.         clockmin = 0;
  217.         yuyy_segled_shwownums(clockmin,2,3);
  218.         yuyy_segled_shwownums(clockhour,2,6);
  219.     }
  220.     if(clockhour == 24)
  221.     {
  222.         clockhour = 0;
  223.         yuyy_segled_shwownums(clockhour,2,6);
  224.     }
  225.     if(clockhour == 0 && clockmin == 0 && clocksec == 30) // 00-00-30闹钟开始响
  226.     {
  227.         BEEP = 1;
  228.     }
  229.     if(clockhour == 0 && clockmin == 0 && clocksec == 33) // 00-00-33闹钟结束
  230.     {
  231.         BEEP = 0;
  232.     }
  233.     yuyy_segled_show();
  234.     delay_ms(1);
  235.     clockms++;
  236. }
  237. //课后练习的main部分
  238. yuyy_segled_showdots(0x00);
  239. yuyy_segled_shownumcharat(0x40,2);
  240. yuyy_segled_shownumcharat(0x40,5);
  241. yuyy_segled_shwownums(0,2,0);
  242. yuyy_segled_shwownums(0,2,3);
  243. yuyy_segled_shwownums(0,2,6);
  244. while(1)
  245. {
  246.         clocktest();
  247. }
复制代码

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-9 16:56:13 | 显示全部楼层
第11集,定时器的使用
介绍了中断的概念,主程序收到中断请求后暂停当前程序进入中断响应函数,中断响应函数处理完成后返回主程序继续执行,中断频率越低越好。
定时一定时间之后产生的中断是定时器中断。
定时器是定时器和计数器的统称。
1.设置为定时器时,可实现硬件计时,或者使程序每隔一固定时间完成一项操作。
2.设置为计数器时能够对脉冲进行计数。
3.替代长时间的delay,提高CPU的运行效率和处理速度,能及时响应某个事件
STC32G定时器相关寄存器
QQ截图20230509150435.png

QQ截图20230509150500.png

使用STC-ISP软件可以方便地生成定时器代码
QQ截图20230509161247.png

关于中断函数后面的中断号,也可以在手册中查到
QQ截图20230509165347.png

QQ截图20230509150937.png

以下代码因为没有实验箱和数码管所以没有验证过
  1. void Timer0_Init(void)
  2. {
  3.     // Timer0初始化
  4.     TMOD = 0x00; //16位重载
  5.     TH0 = 0xF8; //[TH0,TL0] = 65536 - (MAIN_Fosc*time)/T/(TM0PS+1) 其中T=1或12 TM0PS为定时器0时钟预分频寄存器默认0
  6.     TL0 = 0x30; //当前数据为24M下1ms的定时器配置
  7.     ET0 = 1;    //开启中断
  8.     TR0 = 1;    //运行
  9. }
  10. //针对按键开始停止计数的程序修改
  11. //修改这个函数
  12. void key0down_ledsegcounter()
  13. {
  14.     if(KEY0 == 0)
  15.     {
  16.         delay_ms(10);//去抖
  17.         if(KEY0 == 0)
  18.         {
  19.             if((keydown&0x01) == 0)
  20.             {
  21.                 keydown |= 0x01;
  22.                 if(segkeycount == 0)
  23.                 {
  24.                     //开始计数
  25.                     segkeycount = 1;
  26.                 }
  27.                 else if(segkeycount == 1)
  28.                 {
  29.                     //停止计数
  30.                     segkeycount = 2;
  31.                 }
  32.                 else
  33.                 {
  34.                     //重置
  35.                     segkeycount = 0;
  36.                     segcunter = 0;
  37.                     yuyy_segled_shwownums(segcunter,4,0);
  38.                 }
  39.             }
  40.         }
  41.     }
  42.     else
  43.     {
  44.         keydown &= 0xFE;
  45.     }
  46. }
  47. void timer0_int(void) interrupt 1  //1ms 中断函数
  48. {
  49.     if(segkeycount == 1 && segtimer == 10)
  50.     {
  51.         if(segcunter < 9999)
  52.         {
  53.             segcunter++;
  54.             yuyy_segled_shwownums(segcunter,4,0);
  55.         }
  56.         segtimer = 0;
  57.     }
  58.     segtimer++;
  59.     yuyy_segled_show();
  60. }
  61. //main函数内
  62. Timer0_Init();
  63. EA = 1;
  64. while(1)
  65. {
  66.         key0down_ledsegcounter();
  67. }
  68. //针对简易时钟的修改
  69. //修改这个函数
  70. uint16_t clockms = 0; //毫秒
  71. uint8_t clocksec = 0; //秒
  72. uint8_t clockmin = 0; //分
  73. uint8_t clockhour = 0; //时
  74. uint8_t clockrun = 0; //1运行 0暂停
  75. uint16_t beeptime = 0;
  76. void clocktest()
  77. {
  78.     if(clockms == 1000)
  79.     {
  80.         clocksec++;
  81.         clockms = 0;
  82.         yuyy_segled_shwownums(clocksec,2,0);
  83.     }
  84.     if(clocksec == 60)
  85.     {
  86.         clockmin++;
  87.         clocksec = 0;
  88.         yuyy_segled_shwownums(clocksec,2,0);
  89.         yuyy_segled_shwownums(clockmin,2,3);
  90.     }
  91.     if(clockmin == 60)
  92.     {
  93.         clockhour++;
  94.         clockmin = 0;
  95.         yuyy_segled_shwownums(clockmin,2,3);
  96.         yuyy_segled_shwownums(clockhour,2,6);
  97.     }
  98.     if(clockhour == 24)
  99.     {
  100.         clockhour = 0;
  101.         yuyy_segled_shwownums(clockhour,2,6);
  102.     }
  103.     if(clockhour == 0 && clockmin == 0 && clocksec == 30) // 00-00-30闹钟开始响
  104.     {
  105.         BEEP = 1;
  106.         beeptime = 3001;
  107.     }
  108.     if(beeptime > 0) // 00-00-33闹钟结束
  109.     {
  110.         beeptime--;
  111.         if(beeptime == 0)
  112.         {
  113.             BEEP = 0;
  114.         }
  115.     }
  116.     if(clockrun)
  117.     {
  118.         clockms++;
  119.     }
  120.     yuyy_segled_show();
  121. }
  122. //按下一次KEY0,时钟停止再按继续
  123. void key0down_clockrunstop()
  124. {
  125.     if(KEY0 == 0)
  126.     {
  127.         delay_ms(10);//去抖
  128.         if(KEY0 == 0)
  129.         {
  130.             if((keydown&0x01) == 0)
  131.             {
  132.                 keydown |= 0x01;
  133.                 if(clockrun)
  134.                 {
  135.                     clockrun = 0;
  136.                 }
  137.                 else
  138.                 {
  139.                     clockrun = 1;;
  140.                 }
  141.             }
  142.         }
  143.     }
  144.     else
  145.     {
  146.         keydown &= 0xFE;
  147.     }
  148. }  
  149. void timer0_int(void) interrupt 1  //1ms 中断函数
  150. {
  151.     clocktest();
  152. }
  153. //main函数内
  154. Timer0_Init();
  155. EA = 1;
  156. while(1)
  157. {
  158.         key0down_clockrunstop();
  159. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-10 21:42:38 | 显示全部楼层
第12集,计数器的使用
对于输出信号带有电平变化的,想要计算个数就可以用到计数器
各定时器计数器模式外部中断IO
T0--P3.4
T1--P3.5
T2--P1.2
T3--P0.4/P0.0
T4--P0.6/P0.2
一个转速测量的例程,使用P2.0 P2.1 P2.2 P2.3分别输出500Hz 250Hz 100Hz 50Hz的脉冲,分别连接P3.5模拟不同转速,通过USB-HID打印转速
  1. #define KEY0 P32
  2. #define COUNTPERLOOP 10 //一圈10个计数
  3. #define CHECKINTERVAL 2000 //检测周期
  4. uint8_t speedunint = 0; //速度单位 0转每秒 1转每分钟
  5. uint32_t motorspeed = 0;
  6. uint32_t motorcounter = 0;
  7. uint32_t time0counter = 0;
  8. void Timer0_Init(void)                //1毫秒@24.000MHz
  9. {
  10.         TMOD &= 0xF0;                        //设置定时器模式
  11.         TL0 = 0x30;                                //设置定时初始值
  12.         TH0 = 0xF8;                                //设置定时初始值
  13.         TF0 = 0;                                //清除TF0标志
  14.     ET0 = 1;                //开启中断
  15.         TR0 = 1;                                //定时器0开始计时
  16. }
  17. void timer0_int(void) interrupt 1  //1ms 中断函数
  18. {
  19.     P20 = !P20; //模拟500Hz的脉冲
  20.     if(time0counter % 2 == 0)
  21.     {
  22.         P21 = !P21; //模拟250Hz的脉冲
  23.     }
  24.     if(time0counter % 5 == 0)
  25.     {
  26.         P22 = !P22; //模拟100Hz的脉冲
  27.     }
  28.     if(time0counter % 10 == 0)
  29.     {
  30.         P23 = !P23; //模拟50Hz的脉冲
  31.     }
  32.     //上面4个IO与P3.5连接模拟编码器输入
  33.     if(time0counter < CHECKINTERVAL)
  34.     {
  35.         time0counter++;
  36.     }
  37.     else
  38.     {
  39.         time0counter = 0;
  40.         motorcounter |= ((TH1 << 8)&0xFF00) | TL1;
  41.         motorspeed = motorcounter/(CHECKINTERVAL/1000)/COUNTPERLOOP; //结果是转每秒
  42.         if(speedunint == 1)
  43.         {
  44.             motorspeed *= 60;
  45.             printf_hid("转速:%ld 转每分\r\n",motorspeed);
  46.         }
  47.         else
  48.         {
  49.             printf_hid("转速:%ld 转每秒\r\n",motorspeed);
  50.         }
  51.         motorspeed = 0;
  52.         motorcounter = 0;
  53.         TR1 = 0;
  54.         TH1 = 0x00;
  55.         TL1 = 0x00;
  56.         TR1 = 1; //测试时不先停一下不能重置T1计数
  57.     }
  58. }
  59. void Timer1counter_init(void)
  60. {
  61.     // Timer1计数器初始化
  62.     TMOD |= 0x40; //计数器模式
  63.     TH1 = 0x00; //计数器初始值
  64.     TL1 = 0x00; //计数器初始值
  65.     TF1 = 0;    //清除TF1标志
  66.     ET1 = 1;    //开启中断
  67.     TR1 = 1;    //运行
  68. }
  69. void timer1_int(void) interrupt 3
  70. {
  71.     uint16_t h;
  72.     h = motorcounter>>16;
  73.     h += 1;
  74.     motorcounter &= 0x0000FFFF;
  75.     motorcounter |= ((h << 16)&0xFFFF0000);
  76. }
  77. //按键0按下切换转速单位
  78. void key0down_changespeedunit()
  79. {
  80.     if(KEY0 == 0)
  81.     {
  82.         delay_ms(10);//去抖
  83.         if(KEY0 == 0)
  84.         {
  85.             if((keydown&0x01) == 0)
  86.             {
  87.                 keydown |= 0x01;
  88.                 speedunint = 1-speedunint;
  89.             }
  90.         }
  91.     }
  92.     else
  93.     {
  94.         keydown &= 0xFE;
  95.     }
  96. }
  97. //main函数部分
  98. Timer1counter_init();
  99. Timer0_Init();
  100. EA = 1;     //打开总中断
  101. P3PU = 0x20; //P3.5内部上拉
  102. while(1)
  103. {
  104.         key0down_changespeedunit();
  105. }
复制代码
测试结果如下
P3.5连接P2.0
微信截图_20230510212517.png

P3.5连接P2.1
微信截图_20230510212551.png

P3.5连接P2.2
微信截图_20230510214004.png
P3.5连接P2.3
微信截图_20230510214039.png


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-11 09:21:29 | 显示全部楼层
第13集,简易多任务处理上


理清程序的逻辑思路,规范程序
修饰符extern用在变量或者函数的声明前,用来说明“此变量或函数是在别处定义的,要在此处引用”
注意extern修饰的变量不能赋初始值
模块化的编程,按照功能归类将相同的功能放到一组.h和.c文件中
重要的函数添加说明,使用keil的模板可以方便快捷的添加
QQ截图20230511085600.png

keil默认的模板中可能没有我们需要的,我们可以自己添加,右键点击模板的空白处,选择配置模板
QQ截图20230511085652.png

在弹出的窗口中点击新建
QQ截图20230511085321.png

输入模板名称和内容后点击OK
QQ截图20230511085521.png

如果新建的模板名称没出现在列表中关闭keil再重新打开
QQ截图20230511085732.png

在右面的编辑区域将光标定位到要插入模板的地方,再双击模板名称即可插入模板中的内容
QQ截图20230511085752.png

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-11 14:03:10 | 显示全部楼层
第13集,简易多任务处理中
善用Keil的搜索和替换功能,可以方便的修改变量或函数名称
使用分时复用的方法让LED和数码管显示不互相干扰
使用#define定义状态常量
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-11 19:20:24 | 显示全部楼层
第13集,简易多任务处理下
把按键功能封装起来,仿照写了个按键处理文件
yuyy_key.h
  1. #ifndef __YUYY_KEY_H_
  2. #define __YUYY_KEY_H_
  3. #include "config.h"
  4. #define KEYNUMS 4 //按键总数
  5. #define KEYSCANINTERVAL 10//按键扫描间隔
  6. #define DEBOUNCETIME 30 //去抖时间
  7. #define LONGPRESSTIME 2000 //长按识别时间
  8. #define KEYPORT P3 //按键io端口号
  9. #define KEYIOSTART 2 //按键io起始值 屠龙刀的按键从P3.2开始
  10. enum YUYY_KEYSTATE
  11. {
  12.     KEY_UP = 0,      //按键未按下
  13.     KEY_DOWN,        //按键按下
  14.     KEY_SINGLECLICK, //单击按键 按下按键后在LONGPRESSTIME之前松开
  15.     KEY_LONGPRESS,   //长按按键 按下按键的时间超过LONGPRESSTIME
  16.     KEY_LONGPRESSUP  //长按后松开
  17. };
  18. //定义回调
  19. typedef void (*yuyy_key_cb)(uint8_t keynum,enum YUYY_KEYSTATE state);
  20. /**
  21. * 10ms一次检查按键状态
  22. */
  23. void yuyy_keyloop(void);
  24. /**
  25. * 设置回调函数
  26. * 外部文件通过回调函数监控按键状态
  27. */
  28. void yuyy_setkeycb(yuyy_key_cb cb);
  29. #endif
复制代码
yuyy_key.c
  1. #include "yuyy_key.h"
  2. uint16_t keydowncount[KEYNUMS] = {0};
  3. yuyy_key_cb keycb;
  4. void sendkeystate(uint8_t keynum,enum YUYY_KEYSTATE state)
  5. {
  6.     if(keycb)
  7.     {
  8.         keycb(keynum,state);
  9.     }
  10. }
  11. void yuyy_keyloop(void)
  12. {
  13.     uint8_t i = 0;
  14.     while (i<KEYNUMS)
  15.     {
  16.         if((~KEYPORT) & (1<<(i+KEYIOSTART)))
  17.         {
  18.             if(keydowncount[i] < 0xFFFF)
  19.             {
  20.                 keydowncount[i]++;
  21.             }
  22.             if(keydowncount[i]*KEYSCANINTERVAL == DEBOUNCETIME)
  23.             {
  24.                 sendkeystate(i,KEY_DOWN);
  25.             }
  26.             if(keydowncount[i]*KEYSCANINTERVAL == LONGPRESSTIME)
  27.             {
  28.                 sendkeystate(i,KEY_LONGPRESS);
  29.             }
  30.         }
  31.         else
  32.         {
  33.             if(keydowncount[i]*KEYSCANINTERVAL > DEBOUNCETIME)
  34.             {
  35.                 if(keydowncount[i]*KEYSCANINTERVAL < LONGPRESSTIME)
  36.                 {
  37.                     sendkeystate(i,KEY_SINGLECLICK);
  38.                 }
  39.                 else
  40.                 {
  41.                     sendkeystate(i,KEY_LONGPRESSUP);
  42.                 }
  43.             }
  44.             keydowncount[i] = 0;
  45.         }
  46.         i++;
  47.     }
  48.    
  49. }
  50. void yuyy_setkeycb(yuyy_key_cb cb)
  51. {
  52.     keycb = cb;
  53. }
复制代码
main.c
  1. #include "yuyy_key.h"
  2. uint16_t time0counter = 0;
  3. //使用USB-HID打印按键状态变化
  4. void test_keystate_changed(uint8_t keynum,enum YUYY_KEYSTATE state)
  5. {
  6.     switch (state)
  7.     {
  8.     case KEY_DOWN:
  9.         printf_hid("按键%d 按下\r\n",keynum);
  10.         break;
  11.     case KEY_SINGLECLICK:
  12.         printf_hid("按键%d 单击\r\n",keynum);
  13.         break;
  14.         
  15.     case KEY_LONGPRESS:
  16.         printf_hid("按键%d 长按\r\n",keynum);
  17.         break;
  18.     case KEY_LONGPRESSUP:
  19.         printf_hid("按键%d 长按松开\r\n",keynum);
  20.         break;
  21.    
  22.     default:
  23.         break;
  24.     }   
  25. }
  26. void Timer0_Init(void)                //1毫秒@24.000MHz
  27. {
  28.         TMOD &= 0xF0;                        //设置定时器模式
  29.         TL0 = 0x30;                                //设置定时初始值
  30.         TH0 = 0xF8;                                //设置定时初始值
  31.         TF0 = 0;                                //清除TF0标志
  32.     ET0 = 1;                //开启中断
  33.         TR0 = 1;                                //定时器0开始计时
  34. }
  35. void timer0_int(void) interrupt 1  //1ms 中断函数
  36. {
  37.     if(time0counter < 10)
  38.     {
  39.         time0counter++;
  40.     }
  41.     else
  42.     {
  43.         time0counter = 0;
  44.         yuyy_keyloop();
  45.     }
  46. }
  47. //main函数中(省略了其它初始化代码)
  48. Timer0_Init();
  49. yuyy_setkeycb(test_keystate_changed);
  50. while(1)
  51. {
  52. }
复制代码
QQ截图20230511190659.png

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-12 09:05:31 | 显示全部楼层
第13集,简易多任务处理终
仿照视频封装了一下蜂鸣器和定时器功能
yuyy_beep.h

  1. #ifndef __YUYY_BEEP_H_
  2. #define __YUYY_BEEP_H_
  3. #include "config.h"
  4. #define BEEPPIN P54 //蜂鸣器控制io
  5. #define BEEPON 0 //控制蜂鸣器开启的IO电平
  6. /**
  7. * 蜂鸣器开启指定时间
  8. * ms10:0关闭 1-0xFFFE开启对应时间x10 0xFFFF一直开启
  9. */
  10. void yuyy_beep(uint16_t ms10);
  11. /**
  12. * 10ms调用一次
  13. */
  14. void yuyy_beep_loop();
  15. #endif
复制代码
yuyy_beep.c

  1. #include "yuyy_beep.h"
  2. uint16_t beepontime = 0;
  3. void yuyy_beep(uint16_t ms10)
  4. {
  5.     beepontime = ms10;
  6.     if(ms10 == 0) //传入的是0立即关闭
  7.     {
  8.         BEEPPIN = !BEEPON;
  9.     }
  10. }
  11. void yuyy_beep_loop()
  12. {
  13.     if(beepontime>0)
  14.     {
  15.         BEEPPIN = BEEPON;
  16.         if(beepontime < 0xFFFF)
  17.         {
  18.             beepontime--;
  19.         }
  20.     }
  21.     else
  22.     {
  23.         BEEPPIN = !BEEPON;
  24.     }
  25. }
复制代码
yuyy_timer.h

  1. #ifndef __YUYY_TIMER_H_
  2. #define __YUYY_TIMER_H_
  3. #include "config.h"
  4. //定义回调
  5. typedef void (*yuyy_timer0_cb)(void);
  6. /**
  7. * 初始化timer0,
  8. * us:定时时间 1-32768 24M主频时
  9. * cb:定时回调
  10. * return:0成功 1失败
  11. */
  12. uint8_t yuyy_timer0init(uint16_t us,yuyy_timer0_cb cb);
  13. #endif
复制代码
yuyytimer.c

  1. #include "yuyy_timer.h"
  2. yuyy_timer0_cb t0cb;
  3. uint8_t yuyy_timer0init(uint16_t us,yuyy_timer0_cb cb)
  4. {
  5.     uint32_t thl = (MAIN_Fosc/1000000*us)/12/(TM0PS+1);
  6.     if(thl > 65535)
  7.     {
  8.         return 1;
  9.     }
  10.     t0cb = cb;
  11.     thl = 65536 - thl;
  12.     TMOD &= 0xF0;                        //设置定时器模式
  13.     T0x12 = 0;              //12T模式
  14.         TL0 = thl&0xFF;                    //设置定时初始值
  15.         TH0 = (thl>>8)&0xFF;        //设置定时初始值
  16.         TF0 = 0;                                //清除TF0标志
  17.     ET0 = 1;                //开启中断
  18.         TR0 = 1;                                //定时器0开始计时
  19.     return 0;
  20. }
  21. void timer0_int(void) interrupt 1  //timer0中断函数
  22. {
  23.     if(t0cb)
  24.     {
  25.         t0cb();
  26.     }
  27. }
复制代码
测试
main.c
  1. void test_timer0_cb(void)
  2. {
  3.     static uint32_t timer0counter = 0;
  4.     if(timer0counter < 100)
  5.     {
  6.         timer0counter++;
  7.     }
  8.     else
  9.     {
  10.         P20 = !P20;
  11.         yuyy_beep(10);
  12.         timer0counter = 0;
  13.     }
  14.     yuyy_beep_loop();
  15. }
  16. //main函数(省略了其它初始化代码)
  17. yuyy_timer0init(10000,test_timer0_cb); //10ms定时
  18. EA = 1;     //打开总中断
  19. while(1)
  20. {
  21. }
复制代码
编译烧录后P20上的led每1秒切换一次状态,蜂鸣器每1秒响100ms


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-14 12:41:11 | 显示全部楼层
本帖最后由 yuyy1989 于 2023-5-14 14:17 编辑

第14集,矩阵按键
在按键数量较多时,为了减少IO口的占用,将按键排列成矩阵排列的形式的按键阵列我们称位矩阵按键。使用扫描法识别按键。
按键识别原理:端口默认为高电平,实时读取到引脚为低电平是表示按下。
第一步:现将 P0.0-P0.3 输出低电平,P0.6-P0.7 输出高电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
第二步:现将 P0.0-P0.3 输出高电平,P0.6-P0.7 输出低电平,如果有按键按下,按不的那一行的IO就会变成低电平,就可以判断出哪一行按下了。
第三步:行列组合就能判断哪个按键被按下了
不确定计算优先级最好加上括号
矩阵按键功能实现,和上节课的按键功能整合到一起了
yuyy_key.h
  1. #ifndef __YUYY_KEY_H_
  2. #define __YUYY_KEY_H_
  3. #include "config.h"
  4. //普通按键
  5. #define KEYNUMS 4 //按键总数
  6. #define KEYSCANINTERVAL 10//按键扫描间隔
  7. #define DEBOUNCETIME 30 //去抖时间
  8. #define LONGPRESSTIME 2000 //长按识别时间
  9. #define KEYPORT P3 //按键io端口号
  10. #define KEYIOSTART 2 //按键io起始值 屠龙刀的按键从P3.2开始
  11. #define KEYDOWNLEV 0 //按键按下的io电平
  12. //矩阵按键
  13. #define MATRIXKEYCOLS 4 //按键列数
  14. #define MATRIXKEYROWS 2 //按键行数
  15. #define MATRIXKEYNUMS MATRIXKEYCOLS*MATRIXKEYROWS //矩阵按键总数
  16. /**
  17. *按键分布示例
  18. *     P00 P01 P02 P03
  19. * P06  0   1   2   3
  20. * P07  4   5   6   7   
  21. */
  22. #define MATRIXKEYROW0PIN P06 //第0行IO
  23. #define MATRIXKEYROW1PIN P07 //第1行IO
  24. #define MATRIXKEYCOL0PIN P00 //第0列IO
  25. #define MATRIXKEYCOL1PIN P01 //第1列IO
  26. #define MATRIXKEYCOL2PIN P02 //第2列IO
  27. #define MATRIXKEYCOL3PIN P03 //第3列IO
  28. enum YUYY_KEYSTATE
  29. {
  30.     KEY_UP = 0,      //按键未按下
  31.     KEY_DOWN,        //按键按下
  32.     KEY_SINGLECLICK, //单击按键 按下按键后在LONGPRESSTIME之前松开
  33.     KEY_LONGPRESS,   //长按按键 按下按键的时间超过LONGPRESSTIME
  34.     KEY_LONGPRESSUP  //长按后松开
  35. };
  36. //定义回调
  37. typedef void (*yuyy_key_cb)(uint8_t keynum,enum YUYY_KEYSTATE state);
  38. /**
  39. * 10ms一次检查按键状态
  40. */
  41. void yuyy_keyloop(void);
  42. /**
  43. * 设置回调函数
  44. * 外部文件通过回调函数监控按键状态
  45. */
  46. void yuyy_setkeycb(yuyy_key_cb cb);
  47. #endif
复制代码
yuyy_key.c

  1. #include "yuyy_key.h"
  2. #if(KEYNUMS|MATRIXKEYNUMS)
  3. uint16_t keydowncount[KEYNUMS+MATRIXKEYNUMS] = {0};
  4. #else
  5. uint16_t keydowncount[1] = {0};
  6. #endif
  7. yuyy_key_cb keycb;
  8. void sendkeystate(uint8_t keynum,enum YUYY_KEYSTATE state)
  9. {
  10.     if(keycb)
  11.     {
  12.         keycb(keynum,state);
  13.     }
  14. }
  15. void yuyy_refreshkey(uint8_t key,uint8_t down)
  16. {
  17.     if(down)
  18.     {
  19.         if(keydowncount[key] < 0xFFFF)
  20.         {
  21.             keydowncount[key]++;
  22.         }
  23.         if(keydowncount[key]*KEYSCANINTERVAL == DEBOUNCETIME)
  24.         {
  25.             sendkeystate(key,KEY_DOWN);
  26.         }
  27.         if(keydowncount[key]*KEYSCANINTERVAL == LONGPRESSTIME)
  28.         {
  29.             sendkeystate(key,KEY_LONGPRESS);
  30.         }
  31.     }
  32.     else
  33.     {
  34.         if(keydowncount[key]*KEYSCANINTERVAL > DEBOUNCETIME)
  35.         {
  36.             if(keydowncount[key]*KEYSCANINTERVAL < LONGPRESSTIME)
  37.             {
  38.                 sendkeystate(key,KEY_SINGLECLICK);
  39.             }
  40.             else
  41.             {
  42.                 sendkeystate(key,KEY_LONGPRESSUP);
  43.             }
  44.         }
  45.         keydowncount[key] = 0;
  46.     }
  47. }
  48. void matrixkeydelay(void) //根据之前的毫秒延时函数计算,在24M主频时延时大约10us
  49. {
  50.     uint8_t i = 60;
  51.     while (--i);
  52. }
  53. void yuyy_keyloop(void)
  54. {
  55.     uint8_t key = 0;
  56.     #if(MATRIXKEYNUMS)
  57.     uint8_t i,j,col = 0,row = 0;
  58.     #endif
  59.     while (key<KEYNUMS)
  60.     {
  61.         if(((KEYPORT >> (key+KEYIOSTART)) & 0x01) == KEYDOWNLEV)
  62.         {
  63.             yuyy_refreshkey(key,1);
  64.         }
  65.         else
  66.         {
  67.             yuyy_refreshkey(key,0);
  68.         }
  69.         key++;
  70.     }
  71.     #if(MATRIXKEYNUMS)
  72.     MATRIXKEYROW0PIN = 1;
  73.     MATRIXKEYROW1PIN = 1;
  74.     MATRIXKEYCOL0PIN = 0;
  75.     MATRIXKEYCOL1PIN = 0;
  76.     MATRIXKEYCOL2PIN = 0;
  77.     MATRIXKEYCOL3PIN = 0;
  78.     matrixkeydelay();
  79.     if (MATRIXKEYROW0PIN == 0)
  80.     {
  81.         row |= 0x01;
  82.     }
  83.     if (MATRIXKEYROW1PIN == 0)
  84.     {
  85.         row |= 0x02;
  86.     }
  87.     MATRIXKEYROW0PIN = 0;
  88.     MATRIXKEYROW1PIN = 0;
  89.     MATRIXKEYCOL0PIN = 1;
  90.     MATRIXKEYCOL1PIN = 1;
  91.     MATRIXKEYCOL2PIN = 1;
  92.     MATRIXKEYCOL3PIN = 1;
  93.     matrixkeydelay();
  94.     if (MATRIXKEYCOL0PIN == 0)
  95.     {
  96.         col |= 0x01;
  97.     }
  98.     if (MATRIXKEYCOL1PIN == 0)
  99.     {
  100.         col |= 0x02;
  101.     }
  102.     if (MATRIXKEYCOL2PIN == 0)
  103.     {
  104.         col |= 0x04;
  105.     }
  106.     if (MATRIXKEYCOL3PIN == 0)
  107.     {
  108.         col |= 0x08;
  109.     }
  110.    
  111.     MATRIXKEYROW0PIN = 1;
  112.     MATRIXKEYROW1PIN = 1;
  113.     MATRIXKEYCOL0PIN = 1;
  114.     MATRIXKEYCOL1PIN = 1;
  115.     MATRIXKEYCOL2PIN = 1;
  116.     MATRIXKEYCOL3PIN = 1;
  117.    
  118.     for(i=0;i<MATRIXKEYROWS;i++)
  119.     {
  120.         for (j = 0; j < MATRIXKEYCOLS; j++)
  121.         {
  122.             if((row&(1<<i)) && (col&(1<<j)))
  123.             {
  124.                 yuyy_refreshkey(key,1);
  125.             }
  126.             else
  127.             {
  128.                 yuyy_refreshkey(key,0);
  129.             }
  130.             key++;
  131.         }
  132.         
  133.     }
  134.     #endif
  135.    
  136. }
  137. void yuyy_setkeycb(yuyy_key_cb cb)
  138. {
  139.     keycb = cb;
  140. }
复制代码
main.c

  1. void test_keystate_changed(uint8_t keynum,enum YUYY_KEYSTATE state)
  2. {
  3.     switch (state)
  4.     {
  5.     case KEY_DOWN:
  6.         printf_hid("按键%d 按下\r\n",keynum);
  7.         break;
  8.     case KEY_SINGLECLICK:
  9.         printf_hid("按键%d 单击\r\n",keynum);
  10.         yuyy_beep(5);
  11.         break;
  12.         
  13.     case KEY_LONGPRESS:
  14.         printf_hid("按键%d 长按\r\n",keynum);
  15.         break;
  16.     case KEY_LONGPRESSUP:
  17.         printf_hid("按键%d 长按松开\r\n",keynum);
  18.         break;
  19.    
  20.     default:
  21.         break;
  22.     }
  23.    
  24. }
  25. void test_timer0_cb(void)
  26. {
  27.     yuyy_keyloop();
  28. }
  29. //main函数中(省略了其它初始化)
  30. yuyy_timer0init(10000,test_timer0_cb); //10ms定时
  31. EA = 1;     //打开总中断
  32. yuyy_setkeycb(test_keystate_changed);
  33. while(1)
  34. {
  35. }
复制代码
QQ截图20230514123024.png


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:141
  • 最近打卡:2024-05-24 21:11:31

3

主题

64

回帖

1196

积分

金牌会员

积分
1196
发表于 2023-5-14 14:46:16 | 显示全部楼层
第14集,矩阵按键
密码锁示例,增加了退格和清空已输入密码的功能
  1. #include "config.h"
  2. #include "string.h"
  3. //已经写过的直接调用
  4. #include "yuyy_key.h"
  5. #include "yuyy_beep.h"
  6. #include "yuyy_timer.h"
  7. #define LED0 P35
  8. //USB调试及复位所需定义
  9. char *USER_DEVICEDESC = NULL;
  10. char *USER_PRODUCTDESC = NULL;
  11. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
  12. const uint8_t ledsegcodes[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};
  13. const uint8_t password[] = {1,2,3,4,5,6,7,8}; //开锁密码
  14. uint8_t currentpw[8]; //当前密码
  15. uint8_t currentpwindex = 0;
  16. uint16_t timetoclose = 0;
  17. uint16_t timetoledsegoff = 0;
  18. void test_show(void)//显示,没有数码管使用虚拟数码管代替
  19. {
  20.     uint8_t segdatas[8]={0};
  21.     uint8_t i;
  22.     for ( i = 0; i < 8; i++)
  23.     {
  24.         segdatas[i] = ledsegcodes[currentpw[i]];
  25.     }
  26.     SEG7_ShowCode(segdatas);
  27. }
  28. void test_keystate_changed(uint8_t keynum,enum YUYY_KEYSTATE state)
  29. {
  30.     switch (state)
  31.     {
  32.     case KEY_DOWN:
  33.         printf_hid("按键%d 按下\r\n",keynum);
  34.         break;
  35.     case KEY_SINGLECLICK:
  36.         printf_hid("按键%d 单击\r\n",keynum);
  37.         yuyy_beep(2);
  38.         if(keynum == 0) //内部开锁
  39.         {
  40.             LED0 = 0;
  41.             timetoclose = 500;
  42.         }
  43.         else if(keynum == 1) //后退一位
  44.         {
  45.             if(currentpwindex>0)
  46.             {
  47.                 currentpwindex--;
  48.             }
  49.             currentpw[currentpwindex] = 10;
  50.         }
  51.         else if(keynum == 2) //清空已输入密码
  52.         {
  53.             memset(currentpw,10,8);
  54.             currentpwindex = 0;
  55.         }
  56.         else if(keynum > 3)
  57.         {
  58.             currentpw[currentpwindex] = keynum - 3;
  59.             currentpwindex++;
  60.             if(currentpwindex == 8)
  61.             {
  62.                 if(memcmp(currentpw,password,8) == 0) //密码正确
  63.                 {
  64.                     LED0 = 0;
  65.                     timetoclose = 500;
  66.                 }
  67.                 else
  68.                 {
  69.                     LED0 = 1;
  70.                     yuyy_beep(200);
  71.                 }
  72.                 memset(currentpw,10,8);
  73.                 currentpwindex = 0;
  74.             }
  75.         }
  76.         test_show();
  77.         timetoledsegoff = 1000;
  78.         break;
  79.         
  80.     case KEY_LONGPRESS:
  81.         printf_hid("按键%d 长按\r\n",keynum);
  82.         break;
  83.     case KEY_LONGPRESSUP:
  84.         printf_hid("按键%d 长按松开\r\n",keynum);
  85.         break;
  86.    
  87.     default:
  88.         break;
  89.     }
  90.    
  91. }
  92. void test_timer0_cb(void)
  93. {
  94.     yuyy_beep_loop();
  95.     yuyy_keyloop();
  96.     if(timetoclose > 0)
  97.     {
  98.         timetoclose--;
  99.         if(timetoclose == 0)
  100.         {
  101.             LED0 = 1;
  102.         }
  103.     }
  104.     if(timetoledsegoff > 0)
  105.     {
  106.         timetoledsegoff--;
  107.         if(timetoledsegoff == 0)
  108.         {
  109.             uint8_t segdatas[8]={0};
  110.             memset(currentpw,10,8);
  111.             currentpwindex = 0;
  112.             SEG7_ShowCode(segdatas);
  113.         }
  114.     }
  115. }
  116. /******************** 主函数 **************************/
  117. void main(void)
  118. {
  119.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  120.     EAXFR = 1; //扩展寄存器(XFR)访问使能
  121.     CKCON = 0; //提高访问XRAM速度
  122.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
  123.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
  124.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
  125.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
  126.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
  127.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
  128.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
  129.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
  130.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  131.     //USB调试及复位所需代码-----
  132.     P3M0 &= ~0x03;
  133.     P3M1 |= 0x03;
  134.     IRC48MCR = 0x80;
  135.     while (!(IRC48MCR & 0x01));
  136.     usb_init();
  137.     //-------------------------
  138.     yuyy_setkeycb(test_keystate_changed);
  139.     yuyy_timer0init(10000,test_timer0_cb); //10ms定时
  140.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
  141.     EA = 1;     //打开总中断
  142.     LED0 = 1;
  143.    
  144.     printf_hid("STC32G 测试程序\r\n");
  145.     memset(currentpw,10,8);
  146.     test_show();
  147.     while(1)
  148.     {
  149.     }
  150. }
复制代码


回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-7 05:54 , Processed in 0.146557 second(s), 96 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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