找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1786|回复: 1
打印 上一主题 下一主题
收起左侧

单片机任意IO组合实现矩阵按键的程序

[复制链接]
跳转到指定楼层
楼主
单片机源程序如下:
  1. #include "STC32G.h"
  2. sbit C4 = P2^7;
  3. sbit C3 = P2^6;
  4. sbit C2 = P2^5;
  5. sbit C1 = P2^4;
  6. sbit R1 = P2^3;
  7. sbit R2 = P2^2;
  8. sbit R3 = P2^1;
  9. sbit R4 = P4^1;
  10. //理论可以使用任意io,不仅限P0、P1 ……
  11. unsigned char S16 = 0;
  12. bit        _1msPast = 0;
  13. bit busy;//串口忙
  14. bit keypressed = 0;//有键按下位
  15. //仅支持单按键,键在松开后执行操作。

  16. void KeyScan()
  17. {        //每个毫秒扫描一次,
  18.         unsigned char keys;//检测到按下的键值
  19.         static unsigned char pressMscount,looseMscount,pressednum;//按下毫秒计数,松开毫秒计数,按下的键值
  20.         C1 = C2 = C3 = C4 = 1;
  21.         R1 = R2 = R3 = R4 = 0;
  22.         keys = !C1 * 1 + !C2 * 2 + !C3 * 3 + !C4 * 4;
  23.         C1 = C2 = C3 = C4 = 0;
  24.         R1 = R2 = R3 = R4 = 1;
  25.         keys += !R1 * 0 + !R2 * 4 + !R3 * 8 + !R4 * 12;
  26.         C1 = C2 = C3 = C4 = R1 = R2 = R3 = R4 = 0;
  27.         if(keys != 0)
  28.         {
  29.                 //当有键按下时,
  30.                 if(keypressed == 0)
  31.                 //如果键按下标志位为0,则说明突然有键按下,开始按下消抖计时
  32.                 {
  33.                         pressMscount += 1;
  34.                         while(pressMscount == 25)
  35.                         {
  36.                                 //计数达到25时确定有键按下,置keypressed位为1
  37.                                 keypressed = 1;
  38.                                 pressMscount = 0;
  39.                                 pressednum = keys;
  40.                         }
  41.                 }
  42.         }
  43.         else
  44.         {//如果无键按下,或者处于抖动状态,则清除计数
  45.                 //如果刚刚处于有键按下状态,则说明到达按键松开阶段,键按下标志取消
  46.                 if(keypressed == 1)
  47.                 {
  48.                         looseMscount +=1;
  49.                         while(looseMscount == 25)
  50.                         {
  51.                                 //计数达到25时确定按键已松开,置keypressed位为0,发送刚刚按下的按键
  52.                                 keypressed = 0;
  53.                                 looseMscount = 0;
  54.                                 S16 = pressednum;
  55.                                 //松开抖动
  56.                         }
  57.                 }else if(keypressed == 0){
  58.                         //如果按下标志位为0,可能是处于无键按下状态,或者处于按下抖动状态
  59.                         pressMscount = 0;
  60.                 }
  61.         }
  62. }

  63. //定时器0设置
  64. void T0Set()
  65. {        
  66.         AUXR &= 0x7F;                //定时器时钟12T模式
  67.         TMOD &= 0xF0;                //设置定时器模式
  68.         TL0 = 0x33;                //设置定时初始值
  69.         TH0 = 0xF5;                //设置定时初始值        //1毫秒@33.1776MHz
  70.         TF0 = 0;                //清除TF0标志
  71.         TR0 = 1;                        //启动定时器
  72. }
  73. //在定时器0里进行毫秒累加
  74. void T0Action() interrupt 1
  75. {
  76.         _1msPast = 1;
  77. }
  78. //在main里监测到毫秒累加为1时执行动作,并归零毫秒累加。
  79. void DealTimeInMain()
  80. {
  81.         while(_1msPast == 1)
  82.         {
  83.                 KeyScan();
  84.         _1msPast = 0;
  85.         }
  86. }
  87. //================================
  88. //发送字节
  89. void SendData(char dat)
  90. {
  91.     while (busy);           //Wait for the completion of the previous data is sent
  92.     ACC = dat;
  93.           if (P)                  //Set the parity bit according to P
  94.     {
  95.         TB8 = 1;            //Set parity bit to 1
  96.     }
  97.     else
  98.     {
  99.         TB8 = 0;            //Set parity bit to 0
  100.     }
  101.     busy = 1;
  102.     SBUF = ACC;             //Send data to UART buffer
  103. }

  104. char putchar(char c)
  105. {
  106.         SendData(c);
  107.         return c;
  108. }
  109. //串口1配置
  110. void UartInit()
  111. {
  112.         SCON = 0x50;        //8位数据,可变波特率
  113.         AUXR &= 0xBF;        //定时器时钟12T模式
  114.         AUXR &= 0xFE;        //串口1选择定时器1为波特率发生器
  115.         TMOD &= 0x0F;        //设置定时器模式
  116.         TL1 = 0xFA;                //设置定时初始值
  117.         TH1 = 0xFF;                //设置定时初始值
  118.         ET1 = 0;                //禁止定时器%d中断
  119.         TR1 = 1;                //定时器1开始计时
  120.     busy = 0;
  121. }
  122. //串口通信
  123. void UartIsr() interrupt 4
  124. {
  125.         if (RI)
  126.         {
  127.                 RI = 0;             //Clear receive interrupt flag
  128.         }
  129.         if (TI)
  130.         {
  131.                 TI = 0;             //Clear transmit interrupt flag
  132.                 busy = 0;           //Clear transmit busy flag
  133.         }
  134. }
  135. void main()
  136. {
  137.         
  138.         EAXFR = 1;
  139.     P0M0 = 0x00;
  140.     P0M1 = 0x00;
  141.     P1M0 = 0x00;
  142.         P1M1 = 0x00;
  143.     P2M0 = 0x00;
  144.     P2M1 = 0x00;
  145.     P3M0 = 0x00;
  146.     P3M1 = 0x00;
  147.     P4M0 = 0x00;
  148.     P4M1 = 0x00;
  149.     P5M0 = 0x00;
  150.     P5M1 = 0x00;
  151.     P6M0 = 0x00;
  152.     P6M1 = 0x00;
  153.     P7M0 = 0x00;
  154.     P7M1 = 0x00;

  155.     UartInit();

  156.         T0Set();
  157. //        IT0 = 1;
  158.         ET0 = 1;                           //使能定时器0中断
  159.     ES = 1;                                //使能串口1中断
  160.     EA = 1;                                //使能总中断
  161.         
  162.     while (1)
  163.     {
  164.                 DealTimeInMain();
  165.                 while(S16!=0)
  166.                 {//检测到按键,执行动作
  167.                         printf("S%d被按下\r\n",S16);
  168.                         S16=0;
  169.                 }
  170.         }
  171. }
复制代码



此代码可以直接用于STC32G屠龙刀系列,波特率33.1776,C1234 R4321分别接:
C4 → P2^7;
C3 → P2^6;
C2 → P2^5;
C1 → P2^4;
R1 → P2^3;
R2 → P2^2;
R3 → P2^1;
R4 → P4^1;

按下S1-S16,然后松开会向串口返回按下的值,仅支持单键按下,多键会返回错误的值。不支持长按。

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1042619 发表于 2022-11-14 11:42 | 只看该作者
            感谢楼主精彩分享!另外从 STC-ISP V6.90T 以上版本的 ISP烧录/辅助开发工具包一体化软件的增加了I/O口配置小工具、增加将程序最小化到系统托盘区,提升幸福感小工具越来越多了.

JPG.3.png (104.14 KB, 下载次数: 92)

JPG.3.png

jpg.4.jpg (7.46 KB, 下载次数: 96)

jpg.4.jpg

JPG.1.png (79.42 KB, 下载次数: 99)

JPG.1.png
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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