返回列表 发新帖我要提问本帖赏金: 10.00元(功能说明)

[单片机芯片] CH32V003配置GPIO为上拉输入实现按键输入控制LED翻转

[复制链接]
2391|0
 楼主| lilijin1995 发表于 2022-10-23 11:40 | 显示全部楼层 |阅读模式
GPIO, IO, LED, gp, pi
本帖最后由 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 内部设置上拉。 1966993-20221015152112367-79777915.png
3.2.2 软件设计:
打开我们的按键实验工程可以看到,我们引入了 key.c 文件以及头文件 key.h。下面我们首先打开 key.c 文件,代码如下:
  1. #ifndef MYBSP_KEY_C_
  2. #define MYBSP_KEY_C_


  3. void Key_Init(void)
  4. {
  5.     GPIO_InitTypeDef GPIO_InitStructure = {0};

  6.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  7.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.     GPIO_Init(GPIOC, &GPIO_InitStructure);
  11. }


  12. void Key_Handle(void)
  13. {
  14.     static uint8_t bounce=0,bounce1=0,i = 0;
  15.     if(KEY1)
  16.     {
  17.         bounce=1;
  18.     }else{
  19.         if(bounce)
  20.         {
  21.             bounce=0;
  22.             GPIO_WriteBit(GPIOC, GPIO_Pin_3, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
  23.         }
  24.     }

  25.     if(KEY2)
  26.     {
  27.         bounce1=1;
  28.     }else{
  29.         if(bounce1)
  30.         {
  31.             bounce1=0;
  32.             GPIO_WriteBit(GPIOC, GPIO_Pin_4, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
  33.         }
  34.     }
  35.     Delay_Ms(10);
  36. }



  37. #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,我们再来看这个寄存器的定义;
1966993-20221015152211652-1060367293.png

上图是CFGLR寄存器的的描述,MODEy配置的是输入或输出;CNFy描述的是什么模式下的输入和什么模式下的输出;我们用以扫描按键的,当然选择输入模式并且选择上拉模式;y=1或2,故而MODE1=00B和CNF3=01B,MODE4=00B和CNF5=01B;
接下来我们看看头文件 key.h 里面的代码:

  1. /*
  2. * Key.h
  3. *
  4. *  Created on: Oct 19, 2022
  5. *      Author: Administrator
  6. */

  7. #ifndef MYBSP_KEY_H_
  8. #define MYBSP_KEY_H_

  9. #include "debug.h"

  10. #define     KEY1       GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)
  11. #define     KEY2       GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)
  12. void Key_Init(void);
  13. void Key_Handle(void);

  14. #endif /* MYBSP_KEY_H_ */


这段代码里面最关键就是 2 个宏定义:

  1. #define     KEY1       GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)
  2. #define     KEY2       GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)


这里我们采取的是库函数的读取IO 口的值。库函数的本质就是操作寄存器,跳转到定义可以看到它是读取INDR寄存器的:

  1. /*********************************************************************
  2. * @fn      GPIO_ReadInputDataBit
  3. *
  4. * [url=home.php?mod=space&uid=247401]@brief[/url]   GPIOx - where x can be (A..G) to select the GPIO peripheral.
  5. *
  6. * @param    GPIO_Pin - specifies the port bit to read.
  7. *             This parameter can be GPIO_Pin_x where x can be (0..15).
  8. *
  9. * [url=home.php?mod=space&uid=266161]@return[/url]  The input port pin value.
  10. */
  11. uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
  12. {
  13.     uint8_t bitstatus = 0x00;

  14.     if((GPIOx->INDR & GPIO_Pin) != (uint32_t)Bit_RESET)
  15.     {
  16.         bitstatus = (uint8_t)Bit_SET;
  17.     }
  18.     else
  19.     {
  20.         bitstatus = (uint8_t)Bit_RESET;
  21.     }

  22.     return bitstatus;
  23. }


用库函数实现的好处是在各个 CH32 芯片上面的移植性非常好,不需要修改任何代码。
最后,我们看看 main.c 里面编写的主函数代码如下:
  1. /*********************************************************************
  2. * @fn      main
  3. *
  4. * [url=home.php?mod=space&uid=247401]@brief[/url]   Main program.
  5. *
  6. * [url=home.php?mod=space&uid=266161]@return[/url]  none
  7. */
  8. int main(void)
  9. {
  10.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  11.     Delay_Init();
  12.     USART_Printf_Init(115200);
  13.     printf("Demo:Eg2_Key_GPIOInput\r\n");
  14.     printf("SystemClk:%d\r\n",SystemCoreClock);
  15.     LED_Init();
  16.     Key_Init();
  17.     while(1)
  18.     {
  19.         Key_Handle();

  20.     }
  21. }

主函数代码比较简单,先进行一系列的初始化操作,然后在死循环中调用按键扫描函数Key_Handle()扫描按键值,最后根据按键值控制 LED 的翻转。
3.2.3 下载验证:
按下KEY1,LED1翻转,按下KEY2,则是LED2翻转;
至此,我们的本节的学习就结束了。本节,作为CH32 的入门第三个例子,介绍了 CH32的 IO 作为输入的使用方法,同时巩固了前面的学习。希望大家在开发板上实际验证一下,从而加深印象。

3.2.3 学习视频:【CH32V003配置GPIO为上拉输入实现按键输入控制LED翻转】



打赏榜单

21小跑堂 打赏了 10.00 元 2022-10-28
理由:恭喜通过原创审核!期待您更多的作品~

您需要登录后才可以回帖 登录 | 注册

本版积分规则

56

主题

165

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部