本帖最后由 lilijin1995 于 2022-10-23 11:53 编辑
#申请原创#
@21小跑堂
3.2 Eg2_Key_GPIOInput上一章,我们介绍了CH32V003 的 IO 口作为输出的使用,这一章,我们将向大家介绍如何使用 CH32V003 的 IO 口作为输入用。在本章中,我们将利用PC1与PC2,来控制板载的两个 LED 的亮灭。通过本章的学习,你将了解到 CH32V003 的 IO 口作为输入口的使用方法。 3.2.1硬件设计:硬件过于简单,这里展示一下原理图,根据原理图和实物图可知,两颗灯是通过跳线的方式灵活的让你分配引脚的;这里选择PC4和PC3,按键的输入我们选用PC1和PC2作为KEY1 和KEY2 的IO;这里需要注意的是:KEY1 和 KEY2 是低电平有效的,并且外部都没有上下拉电阻,所以,需要在 CH32V003 内部设置上拉。
3.2.2 软件设计:打开我们的按键实验工程可以看到,我们引入了 key.c 文件以及头文件 key.h。下面我们首先打开 key.c 文件,代码如下: #ifndef MYBSP_KEY_C_
#define MYBSP_KEY_C_
void Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void Key_Handle(void)
{
static uint8_t bounce=0,bounce1=0,i = 0;
if(KEY1)
{
bounce=1;
}else{
if(bounce)
{
bounce=0;
GPIO_WriteBit(GPIOC, GPIO_Pin_3, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
}
}
if(KEY2)
{
bounce1=1;
}else{
if(bounce1)
{
bounce1=0;
GPIO_WriteBit(GPIOC, GPIO_Pin_4, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
}
}
Delay_Ms(10);
}
#endif /* MYBSP_KEY_C_ */
这段代码包含 2 个函数,void Key_Init(void)和 void Key_Handle(void),KEY_Init()是用来初始化按键输入的 IO 口的。首先使能 GPIOC 时钟,然后实现 PC1、PC2 的输入设置,这里和上节的输出配置差不多,只是这里用来设置成的是输入而上节是输出。Key_Handle()函数,则是用来扫描这2个 IO 口是否有按键按下。Key_Handle()函数,支持释放响应方式,这样的好处就是可以防止按一次多次触发,而坏处就是在需要长按的时候比较不合适。 Key_Handle在扫描到按键有动作时候就是对相应的LED进行翻转; 我们不妨打开GPIO_Init,可以看到初始化GPIO口其实就是配置CFGLR,我们再来看这个寄存器的定义;
上图是CFGLR寄存器的的描述,MODEy配置的是输入或输出;CNFy描述的是什么模式下的输入和什么模式下的输出;我们用以扫描按键的,当然选择输入模式并且选择上拉模式;y=1或2,故而MODE1=00B和CNF3=01B,MODE4=00B和CNF5=01B; 接下来我们看看头文件 key.h 里面的代码:
/*
* Key.h
*
* Created on: Oct 19, 2022
* Author: Administrator
*/
#ifndef MYBSP_KEY_H_
#define MYBSP_KEY_H_
#include "debug.h"
#define KEY1 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)
#define KEY2 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)
void Key_Init(void);
void Key_Handle(void);
#endif /* MYBSP_KEY_H_ */
这段代码里面最关键就是 2 个宏定义:
#define KEY1 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)
#define KEY2 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)
这里我们采取的是库函数的读取IO 口的值。库函数的本质就是操作寄存器,跳转到定义可以看到它是读取INDR寄存器的:
/*********************************************************************
* @fn GPIO_ReadInputDataBit
*
* [url=home.php?mod=space&uid=247401]@brief[/url] GPIOx - where x can be (A..G) to select the GPIO peripheral.
*
* @param GPIO_Pin - specifies the port bit to read.
* This parameter can be GPIO_Pin_x where x can be (0..15).
*
* [url=home.php?mod=space&uid=266161]@return[/url] The input port pin value.
*/
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
if((GPIOx->INDR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}
用库函数实现的好处是在各个 CH32 芯片上面的移植性非常好,不需要修改任何代码。 最后,我们看看 main.c 里面编写的主函数代码如下: /*********************************************************************
* @fn main
*
* [url=home.php?mod=space&uid=247401]@brief[/url] Main program.
*
* [url=home.php?mod=space&uid=266161]@return[/url] none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("Demo:Eg2_Key_GPIOInput\r\n");
printf("SystemClk:%d\r\n",SystemCoreClock);
LED_Init();
Key_Init();
while(1)
{
Key_Handle();
}
}
主函数代码比较简单,先进行一系列的初始化操作,然后在死循环中调用按键扫描函数Key_Handle()扫描按键值,最后根据按键值控制 LED 的翻转。 3.2.3 下载验证:按下KEY1,LED1翻转,按下KEY2,则是LED2翻转; 至此,我们的本节的学习就结束了。本节,作为CH32 的入门第三个例子,介绍了 CH32的 IO 作为输入的使用方法,同时巩固了前面的学习。希望大家在开发板上实际验证一下,从而加深印象。
3.2.3 学习视频:【CH32V003配置GPIO为上拉输入实现按键输入控制LED翻转】
|