键盘
- 本次培训需要实现一个键盘的功能
- 目标
完全熟悉软件操作(iar,mdk任选1)
完全理解gpio操作,完全掌握gpio的使用方法
了解智能车资料的来源
GPIO概述
- 概念
GPIO (General Purpose I/O),通用输入输出端口。 - 应用
GPIO基本都是用于芯片与片外器件或设备的交互。
检测数字输入,如键盘或开关信号;
驱动LED,蜂鸣器或LCD等其他指示器;
控制片外器件,较高级的使用可以用它们(通过 程序)模拟很多器件的时序达到控制相应器件的 目的,比如模拟SPI和模拟总线等。
- 参考资料: stm32gpio
流水灯实验
- 流水灯思路
在主函数或中断函数内使用逻辑代码编写程序,如if、swicth,实现单片机上的Led灯交替闪烁
- 函数介绍
- gpio初始化函数
gpio操作函数全都在文件MK60_gpio.c中
//-------------------------------------------------------------------------------------------------------------------
// @brief gpio 初始化
// @param ptx_n 选择的引脚
// @param ddr 引脚方向 GPI:输入 GPO:输出
// @param dat 引脚输出数据(如果设置为输出)
// @return void
// @since v1.0
// Sample usage: gpio_init(A5,GPO,0); //初始化A5为gpio模式,设置为输出模式,初始化输出低电平
//-------------------------------------------------------------------------------------------------------------------
void gpio_init(PTX_n ptx_n, GPIO_MOD ddr, uint8 dat)
gpio输出电平设置函数
//-------------------------------------------------------------------------------------------------------------------
// @brief 设置引脚状态
// @param ptx_n 选择的引脚
// @param dat 1为高电平,0为低电平
// @return void
// @since v1.0
// Sample usage: gpio_set(A5,0); //设置A5为低电平
//-------------------------------------------------------------------------------------------------------------------
void gpio_set(PTX_n ptx_n, uint8 dat)
系统延时函数
//-------------------------------------------------------------------------------------------------------------------
// @brief 毫秒级systick延时函数
// @param ms 延时多少毫秒
// @return void
// @since v1.0
// Sample usage: systick_delay_ms(1000); //延时1000毫秒
//-------------------------------------------------------------------------------------------------------------------
void systick_delay_ms(uint32 ms)
- 实现代码 main.c
#include "headfile.h"
#define LED2 D1
#define LED3 D0
int main(void)
{
get_clk();//上电后必须运行一次这个函数,获取各个频率信息,便于后面各个模块的参数设置
gpio_init(LED2,GPO,1); //初始化LED2为高电平
gpio_init(LED3,GPO,1); //初始化LED3为高电平
while(1)
{
gpio_turn(LED2);
systick_delay_ms(100);
gpio_turn(LED3);
systick_delay_ms(100);
}
}
键盘原理
- gpio上拉下拉
信号输入脚刚刚只是进行了初始化,没有配置上下拉;
如果没有上拉下拉,信号输入脚处于悬空状态,这样输入的有可能是0 有可能是1 输出上拉下拉可以防止悬空状态。
上拉电阻简单来说就是把电平拉高, 通常用4.7-10K的电阻接到Vcc电源
下拉电阻则是把电平拉低,电阻接到GND地线上。 - 上下拉函数(MK60_port.c)
//-------------------------------------------------------------------------------------------------------------------
// @brief PORT初始化
// @param ptx_n 端口
// @param cfg 端口属性配置,如触发选项和上拉下拉选项
// @return void
// @since v1.0
// Sample usage: port_init (A14, IRQ_RISING | PF | ALT1 | PULLUP ); //初始化 A14 管脚,上升沿触发中断,带无源滤波器,复用功能为GPIO并设置为输入 ,上拉电阻
// set_irq_priority(PORTA_IRQn,1); //设置优先级
// enable_irq(PORTA_IRQn); //打开PORTA中断开关
// EnableInterrupts; //打开总的中断开关
//-------------------------------------------------------------------------------------------------------------------
void port_init(PTX_n ptx_n,uint32 cfg)
- 上拉示例
port_init(A14,PF | ALT1 | PULLUP ) ;
除此之外需要一个函数获得此时针脚的电压状态,也叫做电平
//-------------------------------------------------------------------------------------------------------------------
// @brief 读取引脚状态
// @param ptx_n 选择的引脚
// @return 管脚的状态 1为高电平,0为低电平
// @since v1.0
// Sample usage: uint8 status = gpio_get(A5); //读取A5为状态
//-------------------------------------------------------------------------------------------------------------------
uint8 gpio_get(PTX_n ptx_n)
轮询实现键盘
代码仅供参考思路
一个按键如何检测是否按下
#include "headfile.h"
int main(void)
{
get_clk();//上电后必须运行一次这个函数,获取各个频率信息,便于后面各个模块的参数设置
//此处编写用户代码(例如:外设初始化代码等)
gpio_init(A5,GPO,1);
gpio_init(A6,GPI,0);
port_init(A6,PF | ALT1 | PULLDOWN);
for(;;)
{
//此处编写需要循环执行的代码
if(gpio_get(A6)==1)
{
systick_delay_ms(10);
gpio_init(A5,GPI,0);
port_init_NoAlt(A5,PULLDOWN);
gpio_init(A6,GPO,1);
if(gpio_get(A5))
printf("A5 A6");
}
}
}
- 六个按键9种状态思路
每行每列都与单片机引脚相连(看原理图)若把行K1、K2、K3置为高电平,gpi,把列K4、K5、K6、K7置为低电平,gpo,当Key1被按下,K1与K4导通,K1端就变为低电平,gpio_get函数检测K1的电平变化就可以判断第一行被按下;此时还需要判断出哪列被按下才能判断出被按下的是哪个按(平面坐标系的点)判断列,就要把上面的行与列的输入输出互换(列设为输入、高电平,行变成输出、低电平)要注意的是要把设为GPI的端口设为上拉电阻模式(porl_pull),使其保持高电平。
- 任务
建立一个函数,把按键功能的语句放里面,在主函数里调用并执行.
检测到按键被按下,就执行流水灯程序
for(;;)
{
key_founction();
LED_blink();
}
- 键盘按下流水灯闪烁
- 键盘按下返回按下键盘的编号
下一篇: 参考答案.