前言
在电赛控制类项目中,功能切换通常需要借助按键指令实现。传统方案多采用外接实体按键,通过检测按键高电平状态来发送指令。针对这一需求,我提出了一种更为高效的按键实现方案。
答案就是触摸屏按键
触摸屏按键不需要额外接线,同时能快速添加多种需要向串口发送的指令以实现不同的功能
硬件准备
正点原子STM32F407ZGT6核心板,2.8寸TFT触摸屏
代码实现
需要做的就是写好显示和触摸的驱动,然后打开串口,实现把触摸的数据发送到串口的功能
lcd和触摸屏的驱动官方例程会提供,这里不赘述,评论区会提供工程文件
绘制按键代码,可根据需求增加或减少
static void init_keypad(void)
{
uint16_t w = lcddev.width / 3;
uint16_t h = lcddev.height;
uint16_t xs, ys = 0, xe, ye = h - 1;
uint8_t i, num = 1;
for (i = 0; i < 3; i++)
{
xs = i * w;
xe = xs + w - 1;
keytab[i].x0 = xs;
keytab[i].y0 = ys;
keytab[i].x1 = xe;
keytab[i].y1 = ye;
keytab[i].cmd = num;
// 白底
LCD_Fill(xs, ys, xe, ye, WHITE);
// 黑色边框
LCD_Fill(xs, ys, xe, ys, BLACK);
LCD_Fill(xs, ye, xe, ye, BLACK);
LCD_Fill(xs, ys, xs, ye, BLACK);
LCD_Fill(xe, ys, xe, ye, BLACK);
// 居中数字
POINT_COLOR = BLACK;
LCD_ShowChar(xs + w/2 - 8, (h/2) - 8, '0' + num, 16, 0);
num++;
}
}
绘制按键反馈代码(可以判断有无触摸)
static void draw_key(uint8_t idx, uint8_t pressed)
{
uint16_t bg = pressed ? GREEN : WHITE;
uint16_t xs = keytab[idx].x0;
uint16_t ys = keytab[idx].y0;
uint16_t xe = keytab[idx].x1;
uint16_t ye = keytab[idx].y1;
uint16_t w = xe - xs + 1;
uint16_t h = ye - ys + 1;
// 背景
LCD_Fill(xs, ys, xe, ye, bg);
// 边框
LCD_Fill(xs, ys, xe, ys, BLACK);
LCD_Fill(xs, ye, xe, ye, BLACK);
LCD_Fill(xs, ys, xs, ye, BLACK);
LCD_Fill(xe, ys, xe, ye, BLACK);
// 数字
POINT_COLOR = BLACK;
LCD_ShowChar(xs + w/2 - 8, ys + h/2 - 8, '0' + keytab[idx].cmd, 16, 0);
}
触摸功能实现
static void keypad_test(void)
{
uint16_t rawX, px;
uint8_t cur, prev, pressedIdx;
uint8_t i;
// 初始状态
prev = 0;
pressedIdx = 0xFF;
init_keypad();
while (1)
{
// 更新触摸
tp_dev.scan(0);
cur = (tp_dev.sta & TP_PRES_DOWN) ? 1 : 0;
// 刚按下(0→1)
if (cur && !prev)
{
rawX = tp_dev.x[0];
px = mapX(rawX);
// 检测哪个按钮
for (i = 0; i < 3; i++)
{
if (px >= keytab[i].x0 && px <= keytab[i].x1)
{
pressedIdx = i;
draw_key(i, 1);
send_cmd(keytab[i].cmd);
break;
}
}
}
// 刚松开(1→0)
if (!cur && prev)
{
if (pressedIdx < 3)
{
draw_key(pressedIdx, 0);
pressedIdx = 0xFF;
}
}
prev = cur;
delay_ms(20);
}
}
主函数
int main(void)
{
HAL_Init();
Stm32_Clock_Init(336, 8, 2, 7);
delay_init(168);
uart_init(115200);
LED_Init();
KEY_Init();
LCD_Init();
tp_dev.init(); // 触摸初始化
LCD_Display_Dir(1);
POINT_COLOR = RED;
LCD_ShowString(20, 30, 200, 16, 16, "三键水平测试");
delay_ms(800);
LCD_Clear(WHITE);
keypad_test();
return 0;
}
由此完成开发