本帖最后由 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翻转】
|