• (51单片机)习题:TM1640驱动数码管并用任意矩阵键盘调节显示参数


    一、天威TM1640介绍

          TM1640 是一种LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字接口、数据锁存器、LED 驱动等电路。主要应用于电子产品LED显示屏驱动。采用SOP28、SSOP28的封装形式。

    •  采用CMOS 工艺 
    •  显示模式(8 段×16 位)
    •  辉度调节电路(占空比8 级可调) 
    •  两线串行接口(SCLK,DIN) 
    •  振荡方式:内置RC 振荡 
    •  内置上电复位电路 
    •  封装形式:SSOP28、SOP28

    (1).管脚定义:

    (2).管脚功能定义:

    (3).电气参数

    (4).微处理器的数据通过两线总线接口和TM1640 通信,在输入数据时当 CLK 是高电平时,DIN 上的信号必须保持不变;只有 CLK 上的时钟信号为低电平时 DIN 上的信号才能改变。 数据的输入总是低位在前, 高位在后传输。 数据输入的开始条件是 CLK 为高电平时, DIN 由高变低;结束条件是 CLK 为高时, DIN 由低电平变为高电平。
    指令数据传输过程如下图:

    根据上面时序图,可以写出如下写一字节驱动代码:

    1. void TM1640_Write_Byte(uint8 TM1640_Dat)
    2. {
    3. uint8 i;
    4. for(i=0;i<8;i++)
    5. {
    6. CLK = 0;
    7. if((TM1640_Dat & 0X01)==0X01)
    8. DIN = 1;
    9. else
    10. DIN = 0;
    11. TM1640_Dat = TM1640_Dat >>1;
    12. //_nop_(); //延时 500ns
    13. CLK = 1;
    14. //_nop_(); //延时 500ns
    15. }
    16. //*********************************
    17. //写完一字节数据,必须要把DIN,SLK拉低,否则会导致固定地址模式不能显示“.”
    18. DIN = 0;
    19. CLK = 0;
    20. //*********************************
    21. }

    (5).两种模式

             写 SRAM 数据地址自动加 1 模式:

            写 SRAM 数据固定地址模式:

    1. /两种写数据模式(固定地址模式、地址自动+1模式)
    2. typedef enum
    3. {
    4. Addr_Fix_Mode = 0X44, //固定地址模式
    5. Addr_Auto_Mod = 0X40, //地址自动增+1模式
    6. } Addr_Mode_t;

    (6)显示控制命令

    1. //亮度调节
    2. typedef enum
    3. {
    4. Brightness_level_0 = 0X80, //亮度 0 熄灭
    5. Brightness_level_1 = 0X88, //亮度 1
    6. Brightness_level_2 = 0X89, //亮度 2
    7. Brightness_level_3 = 0X8A, //亮度 3
    8. Brightness_level_4 = 0X8B, //亮度 4
    9. Brightness_level_5 = 0X8C, //亮度 5
    10. Brightness_level_6 = 0X8D, //亮度 6
    11. Brightness_level_7 = 0X8E, //亮度 7
    12. Brightness_level_8 = 0X8F, //亮度 8
    13. } Brightness_level_t;

    (7)地址命令设置

    1. //显示寄存器地址
    2. typedef enum
    3. {
    4. All_Place_Addr = 16, //TM1640 最大支持16位数码管
    5. Place_Addr_01 = 0XC0,
    6. Place_Addr_02 = 0XC1,
    7. Place_Addr_03 = 0XC2,
    8. Place_Addr_04 = 0XC3,
    9. Place_Addr_05 = 0XC4,
    10. Place_Addr_06 = 0XC5,
    11. Place_Addr_07 = 0XC6,
    12. Place_Addr_08 = 0XC7,
    13. Place_Addr_09 = 0XC8,
    14. Place_Addr_10 = 0XC9,
    15. Place_Addr_11 = 0XCA,
    16. Place_Addr_12 = 0XCB,
    17. Place_Addr_13 = 0XCC,
    18. Place_Addr_14 = 0XCD,
    19. Place_Addr_15 = 0XCE,
    20. Place_Addr_16 = 0XCF,
    21. } Place_Addr_t;

    上电时,地址默认设为C0H。显示数据与芯片管脚以及显示地址之间的对应关系如下表所示:

    注意:芯片显示寄存器在上电瞬间其内部保存的值可能是随机不确定的,此时客户直接发送开屏命令, 将有可能出现显示乱码。所以我司建议客户对显示寄存器进行一次上电清零操作,即上电后向16位显存地址 (C0H-CDH)中全部写入数据0x00。

    TM1640初始化代码如下 :

    1. void TM1640_Init()
    2. {
    3. uint8 i =0;
    4. //地址自动增加 1 模式
    5. TM1640_Star();
    6. TM1640_Write_Byte(Addr_Auto_Mod);
    7. TM1640_End();
    8. //清除显示寄存器
    9. TM1640_Star();
    10. TM1640_Write_Byte(Place_Addr_01); //设置首地址
    11. for(i=0;i<All_Place_Addr;i++) //All_Place_Addr = 16, //TM1640 最大支持16位数码管
    12. TM1640_Write_Byte(0X00); //TM1640 初始化,数据清零 0x00
    13. TM1640_End();
    14. //显示亮度
    15. TM1640_Star();
    16. TM1640_Write_Byte(Brightness_level_5);
    17. TM1640_End();
    18. }
    19. void TM1640_Star()
    20. {
    21. //TM1640起始信号 ,SCL 高电平期间,DIN 由高变低
    22. CLK = 1; //时钟 高电平
    23. DIN = 1; //数据 IO
    24. _nop_();
    25. DIN = 0; //数据 IO
    26. _nop_();
    27. }
    28. void TM1640_End()
    29. {
    30. //TM1640起始信号 ,SCL 高电平期间,DIN 由低变高
    31. CLK = 1; //时钟 高电平
    32. DIN = 0; //数据 IO
    33. DIN = 1; //数据 IO
    34. }

    二、 习题:TM1640驱动数码管并用任意矩阵键盘调节显示参数

    习题要求:使用TM1640驱动数码管时钟(带设置、加、减、确认按键功能)

    • VCC:电源正,推荐3.3V或5V  ---------5V供电
    • CLK:同步串行通信时钟信号输入引脚  --------CLK=P2^1
    • DIN:同步串行通信数据输入引脚   --------- DIN=P2^0
    • GND:地

    简易电路搭建如下图所示:

    完整代码如下 :

    1. /*********************************************************************
    2. 程序名称:TM1640驱动数码管时钟(带设置、加、减、确认按键功能)
    3. 程序版本:V1.0
    4. 作 者: Attack BUG
    5. 编写时间:2023.09.01
    6. 硬件支持: TM1640、STC89C52RC、 16位矩阵键盘
    7. 接口说明:
    8. 修改日志:
    9. *********************************************************************/
    10. /*********************************************************************
    11. 头文件包含/SFR定义
    12. *********************************************************************/
    13. #include <reg52.h>
    14. #include <intrins.h>
    15. /*********************************************************************
    16. 宏定义
    17. *********************************************************************/
    18. typedef unsigned char uint8; //8位有符号字符型
    19. typedef unsigned int uint16; //16位有符号整型
    20. typedef unsigned long uint32; //32位有符号长整型
    21. #define SET 1 //设置键
    22. #define ADD 2 //
    23. #define SUB 3 //
    24. #define OK 4 //确认键
    25. /*********************************************************************
    26. 单片机IO口位定义
    27. *********************************************************************/
    28. sbit DIN=P2^0; //定义端口 3个位声明
    29. sbit CLK=P2^1;
    30. /*********************************************************************
    31. 函数原形声明
    32. *********************************************************************/
    33. uint8 code SMG[19]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x76,0x80,0x40}; //共阴数码管段码表
    34. uint8 key_scan();
    35. uint8 shi=12,fen=30,miao=0;
    36. void delay(uint16 x_ms);
    37. void TM1640_Init();
    38. void TM1640_Star();
    39. void TM1640_End();
    40. void TM1640_Write_Byte(uint8 TM1640_Dat);
    41. void TM1640_Display_time(uint8 address, uint8 shi, uint8 fen, uint8 miao);
    42. void TM1640_address_moshi(uint8 address_mode);
    43. void TM1640_liangdu(uint8 liangdu);
    44. void TM1640_Display_dian(uint8 address,uint8 set_mode);
    45. void TM1640_Display_liushui();
    46. //两种写数据模式(固定地址模式、地址自动+1模式)
    47. typedef enum
    48. {
    49. Addr_Fix_Mode = 0X44, //固定地址模式
    50. Addr_Auto_Mod = 0X40, //地址自动增+1模式
    51. } Addr_Mode_t;
    52. //亮度调节
    53. typedef enum
    54. {
    55. Brightness_level_0 = 0X80, //亮度 0 熄灭
    56. Brightness_level_1 = 0X88, //亮度 1
    57. Brightness_level_2 = 0X89, //亮度 2
    58. Brightness_level_3 = 0X8A, //亮度 3
    59. Brightness_level_4 = 0X8B, //亮度 4
    60. Brightness_level_5 = 0X8C, //亮度 5
    61. Brightness_level_6 = 0X8D, //亮度 6
    62. Brightness_level_7 = 0X8E, //亮度 7
    63. Brightness_level_8 = 0X8F, //亮度 8
    64. } Brightness_level_t;
    65. //显示寄存器地址
    66. typedef enum
    67. {
    68. All_Place_Addr = 16, //TM1640 最大支持16位数码管
    69. Place_Addr_01 = 0XC0,
    70. Place_Addr_02 = 0XC1,
    71. Place_Addr_03 = 0XC2,
    72. Place_Addr_04 = 0XC3,
    73. Place_Addr_05 = 0XC4,
    74. Place_Addr_06 = 0XC5,
    75. Place_Addr_07 = 0XC6,
    76. Place_Addr_08 = 0XC7,
    77. Place_Addr_09 = 0XC8,
    78. Place_Addr_10 = 0XC9,
    79. Place_Addr_11 = 0XCA,
    80. Place_Addr_12 = 0XCB,
    81. Place_Addr_13 = 0XCC,
    82. Place_Addr_14 = 0XCD,
    83. Place_Addr_15 = 0XCE,
    84. Place_Addr_16 = 0XCF,
    85. } Place_Addr_t;
    86. /*********************************************************************
    87. *函数名称:main
    88. *函数功能:主函数
    89. *函数调用:
    90. *参数列表:无
    91. *返 回 值:无
    92. *结 果:
    93. *备 注:
    94. *********************************************************************/
    95. void main()
    96. {
    97. bit smg_mode = 0; //数码管模式 0:时钟模式 1:设置模式
    98. uint8 set_mode = 0; //设置模式的3种情况,1:秒 2:分 3:时
    99. uint8 temp = 0; //缓存矩阵键盘键值
    100. uint16 count = 0; //秒精度调节参数
    101. TM1640_Init(); //初始化TM1640,必需进行初始化
    102. while(1)
    103. {
    104. if(smg_mode==0) // smg_mode = 0 默认上电时钟模式
    105. {
    106. count++; //秒精度调节参数
    107. TM1640_address_moshi(Addr_Auto_Mod); //选择地址模式 Addr_Auto_Mode:地址自动加1模式
    108. TM1640_Display_time(Place_Addr_01, shi, fen, miao); //在第一个数码管位置显示:时、分、秒
    109. //TM1640_Display_liushui(); //从第9位数码管(Place_Addr_09)开始显示 8个横杠“-“
    110. TM1640_liangdu(Brightness_level_5); //亮度选择:5级亮度
    111. if(count==800)
    112. {
    113. count=0;
    114. miao++;
    115. if(miao==60)
    116. {
    117. miao=0;
    118. fen++;
    119. if(fen==60)
    120. {
    121. fen=0;
    122. shi++;
    123. if(shi==24)
    124. {
    125. shi=0;
    126. }
    127. }
    128. }
    129. }
    130. }
    131. else //smg_mode = 1 设置模式
    132. {
    133. //TM1640_Display_liushui(); //从第9位数码管(Place_Addr_09)开始显示 8个横杠“-“
    134. TM1640_Display_time(Place_Addr_01, shi, fen, miao); //在第一个数码管位置显示:时、分、秒
    135. }
    136. //****************************************************************************
    137. temp = key_scan(); //缓存矩阵键盘键值,key_scan()有四种结果:SETADD、SUB、OK
    138. switch(temp)
    139. {
    140. case SET: //识别到设置键时(每按一次set_mode进行一次自加计数)
    141. {
    142. smg_mode = 1; //识别到设置键按下,进入设置模式
    143. set_mode++; //按一次设置键,切换一次设置模式
    144. if(set_mode >= 4)
    145. set_mode = 1;
    146. }
    147. break;
    148. case OK: //识别确认键时,退出,进入正常走时
    149. {
    150. smg_mode = 0; //返回时钟模式
    151. set_mode = 0; //退出模式设置
    152. }
    153. break;
    154. default:
    155. switch(set_mode) //基于设置模式下的三种情况(时、分、秒调节)
    156. {
    157. case 1: //模式一:设置秒钟 set_mode = 1
    158. {
    159. TM1640_Display_dian(Place_Addr_01,set_mode); //set_mode=1,秒钟个位显示"."
    160. if(temp==ADD) //识别 '加'
    161. {
    162. miao++; //+
    163. if(miao==60)
    164. miao = 0;
    165. }
    166. if(temp==SUB) //识别 '减'
    167. {
    168. miao--; //秒-
    169. if(miao==255)
    170. miao = 59;
    171. }
    172. }
    173. break;
    174. case 2: //模式二:设置分钟 set_mode = 2
    175. {
    176. TM1640_Display_dian(Place_Addr_01,set_mode); //set_mode=2,分钟个位显示"."
    177. if(temp==ADD) //识别 '加'
    178. {
    179. fen++; //+
    180. if(fen==60)
    181. fen = 0;
    182. }
    183. if(temp==SUB) //识别 '减'
    184. {
    185. fen--; //分-
    186. if(fen==255)
    187. fen = 59;
    188. }
    189. }
    190. break;
    191. case 3: //模式三:设置时 set_mode = 3
    192. {
    193. TM1640_Display_dian(Place_Addr_01,set_mode); //set_mode=3,时个位显示"."
    194. if(temp==ADD) //识别 '加'
    195. {
    196. shi++; //+
    197. if(shi==24)
    198. shi = 0;
    199. }
    200. if(temp==SUB) //识别 '减'
    201. {
    202. shi--; //时-
    203. if(shi==255)
    204. shi = 23;
    205. }
    206. }
    207. break;
    208. }
    209. break;
    210. }
    211. }
    212. }
    213. void TM1640_Init()
    214. {
    215. uint8 i =0;
    216. //地址自动增加 1 模式
    217. TM1640_Star();
    218. TM1640_Write_Byte(Addr_Auto_Mod);
    219. TM1640_End();
    220. //清除显示寄存器
    221. TM1640_Star();
    222. TM1640_Write_Byte(Place_Addr_01); //设置首地址
    223. for(i=0;i<All_Place_Addr;i++) //All_Place_Addr = 16, //TM1640 最大支持16位数码管
    224. TM1640_Write_Byte(0X00); //TM1640 初始化,数据清零 0x00
    225. TM1640_End();
    226. //显示亮度
    227. TM1640_Star();
    228. TM1640_Write_Byte(Brightness_level_5);
    229. TM1640_End();
    230. }
    231. void TM1640_Star()
    232. {
    233. //TM1640起始信号 ,SCL 高电平期间,DIN 由高变低
    234. CLK = 1; //时钟 高电平
    235. DIN = 1; //数据 IO
    236. _nop_();
    237. DIN = 0; //数据 IO
    238. _nop_();
    239. }
    240. void TM1640_End()
    241. {
    242. //TM1640起始信号 ,SCL 高电平期间,DIN 由低变高
    243. CLK = 1; //时钟 高电平
    244. DIN = 0; //数据 IO
    245. DIN = 1; //数据 IO
    246. }
    247. void TM1640_Write_Byte(uint8 TM1640_Dat)
    248. {
    249. uint8 i;
    250. for(i=0;i<8;i++)
    251. {
    252. CLK = 0;
    253. if((TM1640_Dat & 0X01)==0X01)
    254. DIN = 1;
    255. else
    256. DIN = 0;
    257. TM1640_Dat = TM1640_Dat >>1;
    258. //_nop_(); //延时 500ns
    259. CLK = 1;
    260. //_nop_(); //延时 500ns
    261. }
    262. //*********************************
    263. //写完一字节数据,必须要把DIN,SLK拉低,否则会导致固定地址模式不能显示“.”
    264. DIN = 0;
    265. CLK = 0;
    266. //*********************************
    267. }
    268. void TM1640_Display_liushui()
    269. {
    270. uint8 j;
    271. TM1640_Star(); //开始条件
    272. TM1640_Write_Byte(Place_Addr_09); //在第9个数码管位置写入地址
    273. for(j=0;j<8;j++)
    274. TM1640_Write_Byte(SMG_liushui[j]); //显示"-"
    275. TM1640_End(); //结束条件
    276. }
    277. void TM1640_Display_time(uint8 address, uint8 shi, uint8 fen, uint8 miao)
    278. {
    279. TM1640_Star(); //开始条件
    280. TM1640_Write_Byte(address); //写入地址
    281. TM1640_Write_Byte(SMG[shi%100/10]); //显示时的十位
    282. TM1640_Write_Byte(SMG[shi%10]); //显示时的个位
    283. TM1640_Write_Byte(SMG[18]); //显示"-"
    284. TM1640_Write_Byte(SMG[fen%100/10]); //显示分的十位
    285. TM1640_Write_Byte(SMG[fen%10]); //显示分的个位
    286. TM1640_Write_Byte(SMG[18]); //显示"-"
    287. TM1640_Write_Byte(SMG[miao%100/10]); //显示秒的十位
    288. TM1640_Write_Byte(SMG[miao%10]); //显示秒的个位
    289. TM1640_End(); //结束条件
    290. }
    291. void TM1640_Display_dian(uint8 address,uint8 set_mode) //小数点显示函数
    292. {
    293. TM1640_Star(); //开始条件
    294. TM1640_Write_Byte(address); //写入首地址
    295. //传输显示数据
    296. if(set_mode==3) //若为时钟,时钟个位显示“.”
    297. {
    298. TM1640_Write_Byte(SMG[shi%100/10]); //显示时 十位
    299. TM1640_Write_Byte(SMG[shi%10]|0X80); //显示时 个位,同时显示"."
    300. TM1640_Write_Byte(SMG[18]); //显示"-"
    301. TM1640_Write_Byte(SMG[fen%100/10]); //显示分 十位
    302. TM1640_Write_Byte(SMG[fen%10]); //显示分 个位
    303. TM1640_Write_Byte(SMG[18]); //显示"-"
    304. TM1640_Write_Byte(SMG[miao%100/10]); //显示秒 十位
    305. TM1640_Write_Byte(SMG[miao%10]); //显示秒 个位
    306. TM1640_End(); //结束条件
    307. }
    308. else if(set_mode==2) //若为分钟,分钟个位显示“.”
    309. {
    310. TM1640_Write_Byte(SMG[shi%100/10]); //显示时 十位
    311. TM1640_Write_Byte(SMG[shi%10]); //显示时 个位
    312. TM1640_Write_Byte(SMG[18]); //显示"-"
    313. TM1640_Write_Byte(SMG[fen%100/10]); //显示分 十位
    314. TM1640_Write_Byte(SMG[fen%10]|0X80); //显示分 个位,同时显示"."
    315. TM1640_Write_Byte(SMG[18]); //显示"-"
    316. TM1640_Write_Byte(SMG[miao%100/10]); //显示秒 十位
    317. TM1640_Write_Byte(SMG[miao%10]); //显示秒 个位
    318. TM1640_End(); //结束条件
    319. }
    320. else if(set_mode==1) //若为秒钟,秒钟个位显示“.”
    321. {
    322. TM1640_Write_Byte(SMG[shi%100/10]); //显示时 十位
    323. TM1640_Write_Byte(SMG[shi%10]); //显示时 个位
    324. TM1640_Write_Byte(SMG[18]); //显示"-"
    325. TM1640_Write_Byte(SMG[fen%100/10]); //显示分 十位
    326. TM1640_Write_Byte(SMG[fen%10]); //显示分 个位
    327. TM1640_Write_Byte(SMG[18]); //显示"-"
    328. TM1640_Write_Byte(SMG[miao%100/10]); //显示秒 十位
    329. TM1640_Write_Byte(SMG[miao%10]|0X80); //显示秒 个位,同时显示"."
    330. TM1640_End(); //结束条件
    331. }
    332. else //默认显示 shi-fen-miao
    333. {
    334. TM1640_Write_Byte(SMG[shi%100/10]); //显示时 十位
    335. TM1640_Write_Byte(SMG[shi%10]); //显示时 个位
    336. TM1640_Write_Byte(SMG[18]); //显示"-"
    337. TM1640_Write_Byte(SMG[fen%100/10]); //显示分 十位
    338. TM1640_Write_Byte(SMG[fen%10]); //显示分 个位
    339. TM1640_Write_Byte(SMG[18]); //显示"-"
    340. TM1640_Write_Byte(SMG[miao%100/10]); //显示秒 十位
    341. TM1640_Write_Byte(SMG[miao%10]); //显示秒 个位
    342. TM1640_End(); //结束条件
    343. }
    344. }
    345. void TM1640_address_moshi(uint8 address_mode) //模式选择函数
    346. {
    347. TM1640_Star(); //开始条件
    348. TM1640_Write_Byte(address_mode); //写数据模式 地址自动加1模式 or 固定地址模式
    349. TM1640_End(); //结束条件
    350. }
    351. void TM1640_liangdu(uint8 liangdu) //亮度调节
    352. {
    353. TM1640_Star(); //开始条件
    354. TM1640_Write_Byte(liangdu); //设置亮度级别
    355. TM1640_End(); //结束条件
    356. }
    357. uint8 key_scan()
    358. {
    359. uint8 keynum = 0; //矩阵键盘键值 1~16
    360. uint8 temp = 0; //按键按下时的P3数据缓存
    361. /**************************************************************************/
    362. // 扫描矩阵键盘第一行 0XFE 1111 1110
    363. P3 = 0XFE;
    364. if(P3 != 0XFE)
    365. {
    366. delay(10); //按键消抖 5~10ms
    367. if(P3 != 0XFE)
    368. {
    369. temp = P3; //缓存P3总线的数据状态
    370. while(P3 != 0XFE)
    371. {
    372. TM1640_Display_time(Place_Addr_01,shi,fen,miao); //在第1位数码管(Place_Addr_09)显示时间 xx-xx-xx
    373. }
    374. switch(temp)
    375. {
    376. case 0X7E: keynum = 1; break;
    377. case 0XBE: keynum = 2; break;
    378. case 0XDE: keynum = 3; break;
    379. case 0XEE: keynum = 4; break;
    380. default: keynum = 0; break;
    381. }
    382. }
    383. }
    384. /**************************************************************************/
    385. // 扫描矩阵键盘第二行 0XFD 1111 1101
    386. P3 = 0XFD;
    387. if(P3 != 0XFD)
    388. {
    389. delay(10); //按键消抖 5~10ms
    390. if(P3 != 0XFD)
    391. {
    392. temp = P3; //缓存P3总线的数据状态
    393. while(P3 != 0XFD)
    394. {
    395. TM1640_Display_time(Place_Addr_01,shi,fen,miao); //在第1位数码管(Place_Addr_09)显示时间 xx-xx-xx
    396. }
    397. switch(temp)
    398. {
    399. case 0X7D: keynum = 5; break;
    400. case 0XBD: keynum = 6; break;
    401. case 0XDD: keynum = 7; break;
    402. case 0XED: keynum = 8; break;
    403. default: keynum = 0; break;
    404. }
    405. }
    406. }
    407. /**************************************************************************/
    408. // 扫描矩阵键盘第三行 0XFB 1111 1011
    409. P3 = 0XFB;
    410. if(P3 != 0XFB)
    411. {
    412. delay(10); //按键消抖 5~10ms
    413. if(P3 != 0XFB)
    414. {
    415. temp = P3; //缓存P3总线的数据状态
    416. while(P3 != 0XFB)
    417. {
    418. TM1640_Display_time(Place_Addr_01,shi,fen,miao); //在第1位数码管(Place_Addr_09)显示时间 xx-xx-xx
    419. }
    420. switch(temp)
    421. {
    422. case 0X7B: keynum = 9; break;
    423. case 0XBB: keynum = 10; break;
    424. case 0XDB: keynum = 11; break;
    425. case 0XEB: keynum = 12; break;
    426. default: keynum = 0; break;
    427. }
    428. }
    429. }
    430. /**************************************************************************/
    431. // 扫描矩阵键盘第四行 0XF7 1111 0111
    432. P3 = 0XF7;
    433. if(P3 != 0XF7)
    434. {
    435. delay(10); //按键消抖 5~10ms
    436. if(P3 != 0XF7)
    437. {
    438. temp = P3; //缓存P3总线的数据状态
    439. while(P3 != 0XF7)
    440. {
    441. TM1640_Display_time(Place_Addr_01,shi,fen,miao); //在第1位数码管(Place_Addr_09)显示时间 xx-xx-xx
    442. }
    443. switch(temp)
    444. {
    445. case 0X77: keynum = 13; break;
    446. case 0XB7: keynum = 14; break;
    447. case 0XD7: keynum = 15; break;
    448. case 0XE7: keynum = 16; break;
    449. default: keynum = 0; break;
    450. }
    451. }
    452. }
    453. /**************************************************************************/
    454. return keynum;
    455. }
    456. /********************************延时函数***********************************/
    457. void delay(uint16 x_ms) //延迟 x_ms*1 毫秒
    458. {
    459. uint16 i,j;
    460. for(i=0;i<x_ms;i++)
    461. for(j=0;j<114;j++);
    462. }

    最终视觉效果如下 :

    TM1640驱动数码管+任务矩阵按键调节

  • 相关阅读:
    规则引擎深度对比,LiteFlow vs Drools!
    prometheus 告警
    python:关于函数内 * 和 / 是什么意思?
    Django框架基本语法(一)
    static应用知识:单例设计模式
    js事件流
    Anaconda安装使用以及Pycharm教程
    域名限制注册有哪些原因?
    一个依赖解决 Spring Boot 反爬虫,防止接口盗刷
    Obsidian+SyncTrayzor打造个人文档云同步平台
  • 原文地址:https://blog.csdn.net/qq283875409/article/details/132629605