拓冰建站拓冰建站
首页 / 资讯中心 / 正文

一个串口一个芯片搞定48键带灯键盘,每个灯可控制单独闪烁,还支持组合和长按键,代码很短

这里分享一个使用BC7595的带灯矩阵键盘设计每个灯可独立控制有闪烁功能且电路非常简洁只需要1只芯片和几个电阻。亮点每个按键指示灯可单独控制且可闪烁接口为UART串口直接输出键值可以支持任意组合键或检测长按键整个键盘电路图如下为了看得更清楚这里是一个局部放大图最简应用使用起来超级简单电路图中的按键编号即对应其键值按键按下时会在串口直接输出其键值另外芯片还可检测按键释放输出的键值为按下的键值128最高位置1).比如1号键按下串口即输出 0x01而1号键释放时则输出0x81。LED的控制也很简单这个编号同时也是LED的地址点亮指令为0XC1, 熄灭指令为0XC0串口发送(0XC1, 0X01)就将1号键的灯点亮发送(0XC0, 0x01)则将其熄灭。闪烁功能稍微麻烦一点闪烁由0x3n和0x2n指令控制n的取值范围为0-5,对应控制DIG0到DIG5线上的LED指令由2个字节组成第二个字节的每位对应一个LEDbit0对应连接A线的LEDbit1对应连接B线的LED, 以此类推。比如让S9闪烁S9在DIG1和B线的交叉点上则串口发送(0x31, 0x02)就能让S9的LED开始闪烁。关闭闪烁则发送(0x21, 0x02)。需要说明的是要想看到闪烁必须先将该LED点亮才行。如果该LED只有闪烁和熄灭两种状态不需要常亮则设置闪烁属性后只需控制ON/OFF就行了闪烁属性即便LED关了也会保留再此点亮时就会自动开始闪烁。这里是一个最简单应用的例子串口设置等部分代码省略该程序完成以下功能S1键按下时该键的LED点亮执行该键任务按键释放则LED熄灭任务停止S16键按一下则该键LED点亮执行该键任务再按一下则LED熄灭任务停止S47键按一下该键LED开始闪烁执行该键任务再按一下则LED熄灭任务停止void send_bc7595_cmd(uint8_t cmd, uint8_t data) { uart_send_byte(cmd); uart_send_byte(data); } void main(void) { config_uart(); send_bc7595_cmd(0x35, 0x80); // 设置S47键LED的闪烁属性为开DIG5线与bit7) while (1) { // 主循环 if (UART_RX_DATA_AVAILABLE) { // 查询串口缓冲区是否接收到数据 switch (UART_RX_DATA) { // 根据串口接收数据执行不同操作 case 1: // 如果是S1按下 send_bc7595_cmd(0xC1, 1); // 点亮S1的LED s1_task_on(); // 执行S1键任务 break; case 0x81: // 如果是S1释放 send_bc7595_cmd(0xC0, 1); // 关闭S1的LED s1_task_off(); // 停止S1键任务 break; case 16: // 如果是S16按下 if (s16_task_is_on()) { // 检查S16任务是否已经开启如果已经开启则停止 s16_task_off(); send_bc7595_cmd(0xC0, 16); // 关闭S16的LED } else { // 如果S16任务状态是关 s16_task_on(); // 开始S16的任务 send_bc7595_cmd(0xC1, 16); // 点亮S16的LED } break; case 47: // 如果是S47按下 if (s47_task_is_on()) { // 检查S47任务是否已经开启如果已经开启则停止 s47_task_off(); send_bc7595_cmd(0xC0, 47); // 关闭S47的LED } else { // 如果S47任务状态是关 s47_task_on(); // 开始S47的任务 send_bc7595_cmd(0xC1, 47); // 点亮S47的LED即S47的LED开始闪烁 } break; default: break; } } delay_ms(50); // 查询间隔50ms,也可执行其他功能 } // 主循环 }进阶应用长按键和组合键长按键和组合键的使用稍微复杂一点需要使用与之配套的串口键盘驱动库(开源库GitCode上可下载 单线UART矩阵键盘驱动:基于 C 语言的 UART 单线矩阵键盘驱动库 - AtomGit)。这个库的功能就是允许你给需要的长按键和组合键自己定义一个键值然后其他的使用和基础的S0到S47一样也是按下时收到普通键值释放时收到128的键值。就是说使用长按键和组合键只需要在程序开始时定义一下在主程序中处理逻辑和普通按键是完全一样的。下面这个程序完成这个功能S3键只有在和S0键同时按下时才起作用组合键按一次任务开S3的LED点亮再按一次关闭单独按S3不做任何操作。S4键短按一下LED亮再短按一下LED灭如果长按3s则LED闪烁再长按3s则退出闪烁LED熄灭#include “key_scan.h” // 包含头文件以使用键盘驱动库 const unsigned char lp1[] {4, 120}; // 将S4键配置为长按键lp1赋予自定义键值120 const unsigned char* LPDef[] {lp1}; // 汇总长按键定义如果有多个长按键一起放在这里 const unsigned char cb1[] {2, 121, 0, 3}; // 将S0、S3 2个键配置为组合键cb1赋予自定义键值121 const unsigned char* CBDef[] {cb1}; // 汇总组合键定义如果有多个组合键一起放在这里 unsigned char CBMap[1]; // 定义用于检测组合键的映射数组其空间应不小于定义的组合键总数 void uart_rx_isr(void) { // UART 接收中断处理函数 update_key_status(RX_DATA); // 使用驱动库要求在UART接收中断中用收到的数据呼叫 update_key_status() 函数 } void send_bc7595_cmd(uint8_t cmd, uint8_t data) { // 发送BC7595指令函数 uart_send_byte(cmd); uart_send_byte(data); } int main(void) { config_uart(); set_longpress_count(60); // 设置长按键时间为 3 秒(50ms*60) def_longpress_key(LPDef, 1); // 定义 1 个长按键 def_combined_key(CBDef, CBMap, 1); // 定义1个组合键 while (1) { // 主循环 if (is_key_changed()) { // 使用驱动库时用此函数查询是否有按键变化 switch (get_key_value()) { // 使用此函数读取键值根据键值执行不同操作 case 121: // 如果是S0-S3组合键 if (s3_task_is_on()) { // 检查S3任务是否已经开启如果已经开启则停止 s3_task_off(); send_bc7595_cmd(0xC0, 3); // 关闭S3的LED } else { // 如果S3任务状态是关 s3_task_on(); // 开始S3的任务 send_bc7595_cmd(0xC1, 3); // 点亮S3的LED } break; case 120: // 如果是S4长按3s if (s4_blink_on()) { // 检查S4是否已经闪烁如果已经闪烁则停止 send_bc7595_cmd(0xC0, 4); // 关闭S4的LED send_bc7595_cmd(0x20, 0x10); // 关闭S4的闪烁 DIG0线bit4 } else { // 如果S47任务状态是关 send_bc7595_cmd(0xC1, 4); // 点亮S4的LED send_bc7595_cmd(0x30, 0x10); // 开启S4的闪烁 DIG0线bit4 } break; case 4: // 如果是S4短按 if (!s4_blink_on()) { // 如果S4没有在闪烁状态 if (s4_LED_is_on()) { // 检查S4 LED是否已经点亮如果已经点亮则关闭 send_bc7595_cmd(0xC0, 4); // 关闭S4的LED } else { // 如果S4 LED状态是关 send_bc7595_cmd(0xC1, 4); // 点亮S4的LED } } break; default: break; } } delay_ms(50); // 查询间隔50ms,也可执行其他功能 long_press_tick(); // 使用长按键功能时需要定期呼叫此函数 } // 主循环 }
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门