找回密码
 立即注册
楼主: yuyy***

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

[复制链接]
  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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();
    复制代码


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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. }
    复制代码

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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. }
    复制代码


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

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

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 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, 2024-5-12 08:54 , Processed in 0.088514 second(s), 65 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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