找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2925|回复: 0
收起左侧

单片机IO行列扫描键盘数码管显示键值和调整时间

[复制链接]
ID:350005 发表于 2018-7-17 15:49 | 显示全部楼层 |阅读模式
  1. #define         MAIN_Fosc                22118400L        //定义主时钟

  2. #include        "STC15Fxxxx.H"


  3. #define        Timer0_Reload        (65536UL -(MAIN_Fosc / 1000))                //Timer 0 中断频率, 1000次/秒

  4. #define DIS_DOT                0x20
  5. #define DIS_BLACK        0x10
  6. #define DIS_                0x11




  7. u8 code t_display[]={                                                //标准字库
  8. //         0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  9.         0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
  10. //black         -     H    J         K          L           N        o   P         U     t    G    Q    r   M    y
  11.         0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
  12.         0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};        //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

  13. u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};                //位码


  14. sbit        P_HC595_SER   = P4^0;        //pin 14        SER                data input
  15. sbit        P_HC595_RCLK  = P5^4;        //pin 12        RCLk        store (latch) clock
  16. sbit        P_HC595_SRCLK = P4^3;        //pin 11        SRCLK        Shift data clock


  17. u8         LED8[8];                //显示缓冲
  18. u8        display_index;        //显示位索引
  19. bit        B_1ms;                        //1ms标志

  20. u8        KeyCode;        //给用户使用的键码, 1~16有效
  21. u8        cnt10ms;

  22. u8 IO_KeyState, IO_KeyState1, IO_KeyHoldCnt;        //行列键盘变量
  23. u8        cnt50ms;

  24. u8        hour,minute,second;        //RTC变量
  25. u16        msecond;

  26. void        IO_KeyScan(void);        //50ms call




  27. /********************** 显示时钟函数 ************************/
  28. void        DisplayRTC(void)
  29. {
  30.         if(hour >= 10)        LED8[0] = hour / 10;
  31.         else                        LED8[0] = DIS_BLACK;
  32.         LED8[1] = hour % 10;
  33.         LED8[2] = minute / 10;
  34.         LED8[3] = minute % 10;
  35.         if(msecond >= 500)                LED8[1] |= DIS_DOT;        //小时后的小数点做秒闪
  36. }

  37. /********************** RTC演示函数 ************************/
  38. void        RTC(void)
  39. {
  40.         if(++second >= 60)
  41.         {
  42.                 second = 0;
  43.                 if(++minute >= 60)
  44.                 {
  45.                         minute = 0;
  46.                         if(++hour >= 24)        hour = 0;
  47.                 }
  48.         }
  49. }

  50. /**********************************************/
  51. void main(void)
  52. {
  53.         u8        i;
  54.         
  55.         P0M1 = 0;        P0M0 = 0;        //设置为准双向口
  56.         P1M1 = 0;        P1M0 = 0;        //设置为准双向口
  57.         P2M1 = 0;        P2M0 = 0;        //设置为准双向口
  58.         P3M1 = 0;        P3M0 = 0;        //设置为准双向口
  59.         P4M1 = 0;        P4M0 = 0;        //设置为准双向口
  60.         P5M1 = 0;        P5M0 = 0;        //设置为准双向口
  61.         P6M1 = 0;        P6M0 = 0;        //设置为准双向口
  62.         P7M1 = 0;        P7M0 = 0;        //设置为准双向口


  63.         display_index = 0;
  64.         
  65.         AUXR = 0x80;        //Timer0 set as 1T, 16 bits timer auto-reload,
  66.         TH0 = (u8)(Timer0_Reload / 256);
  67.         TL0 = (u8)(Timer0_Reload % 256);
  68.         ET0 = 1;        //Timer0 interrupt enable
  69.         TR0 = 1;        //Tiner0 run
  70.         EA = 1;                //打开总中断
  71.         
  72.         for(i=0; i<8; i++)        LED8[i] = 0x10;        //上电消隐

  73.         hour   = 12;        //初始化时间值
  74.         minute = 0;
  75.         second = 0;
  76.         DisplayRTC();

  77.         KeyCode = 0;        //给用户使用的键码, 1~16有效
  78.         cnt10ms = 0;

  79.         IO_KeyState = 0;
  80.         IO_KeyState1 = 0;
  81.         IO_KeyHoldCnt = 0;
  82.         cnt50ms = 0;
  83.         
  84.         while(1)
  85.         {
  86.                 if(B_1ms)        //1ms到
  87.                 {
  88.                         B_1ms = 0;
  89.                         if(++msecond >= 1000)        //1秒到
  90.                         {
  91.                                 msecond = 0;
  92.                                 RTC();
  93.                                 DisplayRTC();
  94.                         }
  95.                         if(msecond == 500)        DisplayRTC();        //小时后的小数点做秒闪


  96.                         if(++cnt50ms >= 50)                //50ms扫描一次行列键盘
  97.                         {
  98.                                 cnt50ms = 0;
  99.                                 IO_KeyScan();
  100.                         }
  101.                         
  102.                         if(KeyCode > 0)                //有键按下
  103.                         {
  104.                                 LED8[6] = KeyCode / 10;        //显示键码
  105.                                 LED8[7] = KeyCode % 10;        //显示键码

  106.                                 if(KeyCode == 17)        //hour +1
  107.                                 {
  108.                                         if(++hour >= 24)        hour = 0;
  109.                                         DisplayRTC();
  110.                                 }
  111.                                 if(KeyCode == 18)        //hour -1
  112.                                 {
  113.                                         if(--hour >= 24)        hour = 23;
  114.                                         DisplayRTC();
  115.                                 }
  116.                                 if(KeyCode == 19)        //minute +1
  117.                                 {
  118.                                         second = 0;
  119.                                         if(++minute >= 60)        minute = 0;
  120.                                         DisplayRTC();
  121.                                 }
  122.                                 if(KeyCode == 20)        //minute -1
  123.                                 {
  124.                                         second = 0;
  125.                                         if(--minute >= 60)        minute = 59;
  126.                                         DisplayRTC();
  127.                                 }

  128.                                 KeyCode = 0;
  129.                         }

  130.                 }
  131.         }
  132. }
  133. /**********************************************/

  134.         

  135. /*****************************************************
  136.         行列键扫描程序
  137.         使用XY查找4x4键的方法,只能单键,速度快

  138.    Y     P04      P05      P06      P07
  139.           |        |        |        |
  140. X         |        |        |        |
  141. P00 ---- K00 ---- K01 ---- K02 ---- K03 ----
  142.           |        |        |        |
  143. P01 ---- K04 ---- K05 ---- K06 ---- K07 ----
  144.           |        |        |        |
  145. P02 ---- K08 ---- K09 ---- K10 ---- K11 ----
  146.           |        |        |        |
  147. P03 ---- K12 ---- K13 ---- K14 ---- K15 ----
  148.           |        |        |        |
  149. ******************************************************/


  150. u8 code T_KeyTable[16] = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};

  151. void IO_KeyDelay(void)
  152. {
  153.         u8 i;
  154.         i = 60;
  155.         while(--i)        ;
  156. }

  157. void        IO_KeyScan(void)        //50ms call
  158. {
  159.         u8        j;

  160.         j = IO_KeyState1;        //保存上一次状态

  161.         P0 = 0xf0;        //X低,读Y
  162.         IO_KeyDelay();
  163.         IO_KeyState1 = P0 & 0xf0;

  164.         P0 = 0x0f;        //Y低,读X
  165.         IO_KeyDelay();
  166.         IO_KeyState1 |= (P0 & 0x0f);
  167.         IO_KeyState1 ^= 0xff;        //取反
  168.         
  169.         if(j == IO_KeyState1)        //连续两次读相等
  170.         {
  171.                 j = IO_KeyState;
  172.                 IO_KeyState = IO_KeyState1;
  173.                 if(IO_KeyState != 0)        //有键按下
  174.                 {
  175.                         F0 = 0;
  176.                         if(j == 0)        F0 = 1;        //第一次按下
  177.                         else if(j == IO_KeyState)
  178.                         {
  179.                                 if(++IO_KeyHoldCnt >= 20)        //1秒后重键
  180.                                 {
  181.                                         IO_KeyHoldCnt = 18;
  182.                                         F0 = 1;
  183.                                 }
  184.                         }
  185.                         if(F0)
  186.                         {
  187.                                 j = T_KeyTable[IO_KeyState >> 4];
  188.                                 if((j != 0) && (T_KeyTable[IO_KeyState& 0x0f] != 0))
  189.                                         KeyCode = (j - 1) * 4 + T_KeyTable[IO_KeyState & 0x0f] + 16;        //计算键码,17~32
  190.                         }
  191.                 }
  192.                 else        IO_KeyHoldCnt = 0;
  193.         }
  194.         P0 = 0xff;
  195. }




  196. /**************** 向HC595发送一个字节函数 ******************/
  197. void Send_595(u8 dat)
  198. {               
  199.         u8        i;
  200.         for(i=0; i<8; i++)
  201.         {
  202.                 dat <<= 1;
  203.                 P_HC595_SER   = CY;
  204.                 P_HC595_SRCLK = 1;
  205.                 P_HC595_SRCLK = 0;
  206.         }
  207. }

  208. /********************** 显示扫描函数 ************************/
  209. void DisplayScan(void)
  210. {        
  211.         Send_595(~T_COM[display_index]);                                //输出位码
  212.         Send_595(t_display[LED8[display_index]]);        //输出段码

  213.         P_HC595_RCLK = 1;
  214.         P_HC595_RCLK = 0;                                                        //锁存输出数据
  215.         if(++display_index >= 8)        display_index = 0;        //8位结束回0
  216. }


  217. /********************** Timer0 1ms中断函数 ************************/
  218. void timer0 (void) interrupt TIMER0_VECTOR
  219. {
  220.         DisplayScan();        //1ms扫描显示一位
  221.         B_1ms = 1;                //1ms标志
  222. }
复制代码

评分

参与人数 1黑币 +15 收起 理由
564654654 + 15 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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