本章目的:将LCD扩展板上的方向按键用起来,在LCD上显示对应的方向。
由于这个方向按键就是普通的GPIO,没有什么原理,所以直接开撸。
在read_key函数中,读取按键的GPIO值,赋值给ret对应的bit位上,然后做一个和旧值,如果值变化了才返回新值,否则返回0。
#include "key.h"
void KEY_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOA、GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入模式
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.0,1,15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入模式
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB.8,9
}
u8 read_key(void)
{
u8 ret=0;
static u8 ret_last=0;
if(!KEY_GPIO_UP)ret |= KEY_UP_PRESS;
if(!KEY_GPIO_DOWN)ret |= KEY_DOWN_PRESS;
if(!KEY_GPIO_LEFT)ret |= KEY_LEFT_PRESS;
if(!KEY_GPIO_RIGHT)ret |= KEY_RIGHT_PRESS;
if(!KEY_GPIO_CENTER)ret |= KEY_CENTER_PRESS;
if(ret!=ret_last)
{
ret_last = ret;
return ret;
}
return ret;
}
#ifndef __KEY_H__
#define __KEY_H__
#include "air32f10x.h"
#include "sys.h"
/*
A1上
A15下
B8左
A0右
B9中
*/
#define KEY_GPIO_UP PAin(1)
#define KEY_GPIO_DOWN PAin(15)
#define KEY_GPIO_LEFT PBin(8)
#define KEY_GPIO_RIGHT PAin(0)
#define KEY_GPIO_CENTER PBin(9)
typedef enum
{
KEY_UP = 0,
KEY_DOWN,
KEY_LEFT,
KEY_RIGHT,
KEY_CENTER
}key_t;
#define KEY_UP_PRESS (1<<KEY_UP)
#define KEY_DOWN_PRESS (1<<KEY_DOWN)
#define KEY_LEFT_PRESS (1<<KEY_LEFT)
#define KEY_RIGHT_PRESS (1<<KEY_RIGHT)
#define KEY_CENTER_PRESS (1<<KEY_CENTER)
void KEY_GPIO_Init(void);
u8 read_key(void);
#endif
#include
#include
#include
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include "timer.h"
#include "gui.h"
#include "rcc_clk.h"
#include "picture.h"
u8 key=0,key_last=0xFF,key_first=1;
char str[50];
int main(void)
{
RCC_ClkConfiguration(); //配置时钟
DELAY_Init(); //延时初始化
USART1_Init(115200); //串口1初始化
LED_GPIO_Init(); //LED初始化
KEY_GPIO_Init(); //KEY初始化
ST7735V_Init(); //LCD初始化
GUI_Clear(White); //LCD清屏
TIM3_Int_Init(30000-1,72-1); //定时器3初始化,10ms(216M/30k/72=100k)
TIM2_Int_Init(30000-1,36000-1); //定时器2初始化,5000ms(216M/30k/36k=0.2HZ=5000ms)
USART1_ClearBuffer(); //清空串口1接收buffer
CLK_Printf(); //打印时钟频率
printf("wuzjjj\r\n"); //打印欢迎语句
// GUI_Pic((u16*)gImage_wxhq); //LCD显示图片
GUI_ShowHzChar(0,0,"Air32F103_LCD测试",Black,White);
USART1_ClearBuffer(); //清空串口1接收buffer
while (1)
{
if(USART1_RX_STA&0x8000) //收到串口数据
{
GUI_ShowHzCharAuto(0,16,(char*)USART1_RX_BUF,Black,White);
if(strcmp((char*)USART1_RX_BUF,"LEDR_ON")==0)
LEDR_ON;
else if(strcmp((char*)USART1_RX_BUF,"LEDR_OFF")==0)
LEDR_OFF;
else if(strcmp((char*)USART1_RX_BUF,"LEDG_ON")==0)
LEDG_ON;
else if(strcmp((char*)USART1_RX_BUF,"LEDG_OFF")==0)
LEDG_OFF;
else if(strcmp((char*)USART1_RX_BUF,"LEDB_ON")==0)
LEDB_ON;
else if(strcmp((char*)USART1_RX_BUF,"LEDB_OFF")==0)
LEDB_OFF;
USART1_RX_STA = USART1_RX_STA&0x7FFF; //去掉标志位,剩下数据长度
printf("received,%d:",USART1_RX_STA); //发送辅助信息及收到的数据长度
printf("%s\r\n",USART1_RX_BUF); //将收到的数据发回
USART1_ClearBuffer(); //清空串口1接收buffer
}
key = read_key();
if((key!=key_last&&key!=0)||key_first==1)
{
GUI_Arc(80,30,7,key&KEY_UP_PRESS?Red:Gray,1);
GUI_Arc(80,70,7,key&KEY_DOWN_PRESS?Red:Gray,1);
GUI_Arc(60,50,7,key&KEY_LEFT_PRESS?Red:Gray,1);
GUI_Arc(100,50,7,key&KEY_RIGHT_PRESS?Red:Gray,1);
GUI_Arc(80,50,7,key&KEY_CENTER_PRESS?Red:Gray,1);
key_last=key;
key_first=0;
}
sprintf(str,"key=%2d",key);
GUI_ShowHzChar(0,60,str,Black,White);
delay_ms(50);
}
}
由于LCD板上关于按键的标记是错误的,下面列一下上面的丝印对应的接线。
Air32<------>LCD板
A1<------------>PA_7(上)
A15<----------->PB_11(下)
B8<----------->PA_1(左)
A0<----------->PA_0(右)
B9<----------->PA_4(中间)
3.3V<--------->3V3
GND<------->GND
支持5个方向的按键,按下后对应位置显示红色,支持多个按键同时按下。