第一章 GD32学习笔记1(高难度工程,点亮一个LED灯)
第二章 GD32学习笔记2(按键控制LED灯)
文章目录
- 系列文章目录
- 前言
- 一、程序基本流程
- 二、添加新的源文件
- 1.systick.c
- 2.gd32f4xx_it.c
- 三、代码实现
- 1.修改管脚初始化函数
- 2.主函数
- 总结
前言
前面第一章介绍了如何从新建工程开始,通过合理的初始化GPIO,点亮一个LED灯,本章在第一章的基础之上,加入独立按键输入,来控制LED灯,初学的小伙伴可以先把第一章的内容实现了,再在第一章的工程里面添加代码。
一、程序基本流程
初始化->检测按键输入->根据按键输入情况控制LED灯
二、添加新的源文件 1.systick.c
systick.c是兆易公司提供的一个十分有用的Demo,里面给不熟悉定时器的用户提供了一个延时接口函数,函数原型如下:
/*!
\brief delay a time in milliseconds
\param[in] count: count in milliseconds
\param[out] none
\retval none
*/
void delay_1ms(uint32_t count)
{
delay = count;
while(0U != delay){
}
}
里面只有一个参数需设置,count代表需要延时的毫秒数,这个用在哪一会讲。
在这个源文件的里已经写好了一个初始化函数,我们在程序运行时要调用它:
void systick_config(void)
{
/* setup systick timer for 1000Hz interrupts */
if(SysTick_Config(SystemCoreClock / 1000U)){
/* capture error */
while (1){
}
}
/* configure the systick handler priority */
NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
2.gd32f4xx_it.c
这个文件在以后的讲解中会经常用到,用于存放中断服务函数,在兆易官方提供的gd32f4xx_it.c里面已经存在了一个中断服务函数,在程序运行的过程中会触发到它(至于怎么触发的先挖一个坑)。
/*!
\brief this function handles SysTick exception
\param[in] none
\param[out] none
\retval none
*/
void SysTick_Handler(void)
{
delay_decrement();
}
同样的流程,将以上两个源文件通过分组管理添加到工程中,再将对应的头文件粘贴到工程文件夹/User/Include中,完成以后你的工程分组应该变成了这样:
自此完成按键控制LED灯的前期准备工作就完成了,接下来就是写代码。
三、代码实现 1.修改管脚初始化函数
在第一个点亮LED灯的工程中我们只用到了一个PC6管脚,它连接到一端接地的LED灯,现在我们需要有另一个管脚接独立按键,当按键按下时,单片机能接收到一个输入信号,由这个信号来控制PC6抬高或拉低。
在我所有的这块板子上,有一个User Key能供我使用,从原理图得知这个独立按键连接在芯片的PA0管脚上,另一端接GND,且PA0有一个上拉电阻接VCC,也即是说每当独立按键被按下,芯片就会接收到一个低电平信号。
(关于按键旁边电容的作用,哪天我有兴趣写模拟电路的文章再讲,这里再挖一个坑)
所以我们需要做的就是在GPIO初始化里面添加一个PA0,并对其功能进行设置,GPIO初始化的代码就变成了这个样子:
void GPIO_Config(void)
{
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_0);
gpio_output_options_set(GPIOA, GPIO_PUPD_PULLUP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
}
先将GPIOA的通道时钟使能,使用gpio_mode_set将PA0设置为输入模式,带上拉电阻,用gpio_output_options_set将管脚速度设为50MHz,那么GPIO的初始化就改完了。
接下来要写按键控制LED的逻辑,在官方提供的GPIO函数库中给用户提供了一个能够判断某个管脚是否有高电平输入的函数,其原型如下:
FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)
{
if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){
return SET;
}else{
return RESET;
}
}
当有外部高电平输入时返回值为SET,否则返回RESET,那么我们只需要在我们控制LED的函数里面调用这个函数,并判断它的返回值,当返回值为RESET时控制LED灯亮灭。
具体实现如下:
void Key_Control(void)
{
if(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0))
{
delay_1ms(100);
if(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0))
{
LED_TOGGLE;
}
while(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0)){}
}
}
在这里我们调用了一个延时函数,delay_1ms(),目的是延时消抖,在电路中,当按键按下后,管脚的电平并不是一下就从高电平跳转到低电平的,可能会有杂波影响到芯片管脚对当前所处电平的判断,所以加一个延时函数,当有电平发生由高到低的变化时,先给它100ms让它冷静冷静,再进行电平判断,如果还是低电平,那说明按键被按下。
在第一个工程中,我们已经写好了两个宏定义来表示开灯和关灯,我们在这个工程里面希望实现的是当按键按下,原本开灯变成关灯,原本关灯变成开灯,所有开灯关灯的判断条件都是一样的,很难用一个if语句去实现这个功能,但是官方库给我们提供了另一个方法,能让控制LED管脚的状态翻转,即原本为低翻转为高,原本为高翻转为低,先把宏定义贴出来:
GLOB_METERCOMM_EXTERN void GPIO_Config(void);
GLOB_METERCOMM_EXTERN void Key_Control(void);
#define LED_ON gpio_bit_set(GPIOC, GPIO_PIN_6) //置位PC6
#define LED_OFF gpio_bit_reset(GPIOC, GPIO_PIN_6) //复位PC6
#define LED_TOGGLE gpio_bit_toggle(GPIOC, GPIO_PIN_6)//翻转PC6
在这个头文件中,首先对已写好的按键控制函数Key_Control()进行了声明,以便主函数能够调用它,然后定义了LED_TOGGLE,gpio_bit_toggle的原型如下:
/*!
\brief toggle GPIO pin status
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_bit_toggle(uint32_t gpio_periph, uint32_t pin)
官方的注释也简单明了,功能就是翻转管脚状态。
主函数的内容就十分简单了,先调用两个初始化函数,然后在while(1)死循环中调用按键控制函数:
int main(void)
{
systick_config();
GPIO_Config();
while(1)
{
Key_Control();
}
}
编译后下载到板子里面,来看看功能实现:
620d61f5
总结
1.按键输入要设置GPIO为输入模式
2.按键需要延时函数消抖(最好有)
其实总结没什么可写的,就提一个我个人的疑问吧,接按键的管脚PA6明明接了上拉电阻,为什么在初始化里面即使不设置上拉也不影响功能的实现?
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)