CH32V307 开发板 Wake_Up 点亮 LED1

Wake_Up控制LED1

基礎知識

GPIO(General-purpose input/output):与外部进行通信的IO口

EXTI(external interrupt):外部中断控制器

NVIC(Nested Vectored Interrupt Controller ):为EXTI设置优先级

GPIO引脚速度,GPIOSpeed_TypeDef. 引脚的输出频率影响着引脚对于数据传输速度的快慢,以及影响芯片的功耗

引脚:引脚,或称接脚或管脚,是指电子元件的末端露出部分

目標

按压Wake_Up,控制LED1亮

思路

根据:

端口功能 引脚名 功能 备注
按键 PA0 Wake_Up 按下输入1
PE4 SW1 按下输入0
PE5 SW2 按下输入0
五向开关 PE1 JOY_UP 按下输入0
PE2 JOY_DOWN 按下输入0
PD6 JOY_LEFT 按下输入0
PE3 JOY_RIGHT 按下输入0
PD13 JOY_SEL 按下输入0
LED PE11 LED1 输出0点亮
PE12 LED2 输出0点亮

当Wake_Up按键时,引脚PA0会返回1;引脚PE11输出0时,LED1会点亮。因此我们的思路是捕捉PA0的1输入,从PE11输出0

实现

根据上面的思路,我们需要在一个函数里面初始化输入,输出控制。有一个函数可以监听输入并作出相应的反应。
因此,我们有 main 函数

int main(void)
{
    EXTI_INT_INIT(); // 初始化外部中断
    GPIO_INIT();     // 初始化 GPIO
    while(1);        // 死循环
}

main函数中初始化外部中断的代码如下:
7-10 行初始化监听Wake_Up引脚关联的GPIO
13-18 行初始化外部中断/事件控制器,初始化对应应引脚的中断Line,模式,触发的方式
21-25 行初始化嵌套向量中断控制器,关联EXTI并设置抢占优先级和响应优先级

void EXTI_INT_INIT(void)
{
   GPIO_InitTypeDef  GPIO_InitStructure={0};
   EXTI_InitTypeDef EXTI_InitStructure={0};
   NVIC_InitTypeDef NVIC_InitStructure={0};

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA,ENABLE);
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//   Wake_Up PA0
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//   输入模式
   GPIO_Init(GPIOA, &GPIO_InitStructure);

   /* GPIOA ----> EXTI_Line0 */
   GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
   EXTI_InitStructure.EXTI_Line=EXTI_Line0; // 中断线 line0(对应引脚,不对应的话不会有反应)
   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断or事件
   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 按下为高电平,用上升沿
   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
   EXTI_Init(&EXTI_InitStructure); // 外部中断控制器

   /* EXTI_Line0 ----> NVIC 为中断分组,以分配两个优先级 */ 
   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn ; // IQR channel to be enabled 中断源, 此处选择EXTI0 中断
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 数字越低,中断优先级越高 抢占优先级
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        // 子优先级 (响应优先级)
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure); // initialize NVIC(嵌套向量中断控制器) peripheral ()
}

初始化输出GPIO的代码如下

void GPIO_INIT(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure={0}; //GPIO的结构体定义
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); // 在STM32对于外设的使用里面,每使用到一个外设,都要打开其对应的外设时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//    规定输出在 pin 11(LED01)
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//    输出模式:推挽输出(简单说时一种可以输出高低电平的模式)
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; // 引脚的输出频率影响着引脚对于数据传输速度的快慢,以及影响芯片的功耗
    GPIO_Init(GPIOE, &GPIO_InitStructure);
}

初始化以上后,我们还需中断服务函数,如下
1行:各厂家会根据自家的内核设计,修改对应的工具链以支持其特色功能,如沁恒微电子的RISC-V MCU所特有的HPE硬件压栈和VTF免表中断技术,需要在中断服务函数增加指令__attribute__((interrupt(“WCH-Interrupt-fast”)))

4-8行:根据中断line更改LED状态

void EXTI0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
volatile uint16_t LED_Status = 0; // 中断里使用的变量加 volatile 可当成全局变量
void EXTI0_IRQHandler(void)
{
	EXTI_ClearFlag(EXTI_Line0); //zh 置中断标志位为零
	LED_Status = !LED_Status ;  // 将 LED 状态值取反
	GPIO_WriteBit(GPIOE, GPIO_Pin_11, LED_Status); // 配置 PE11 (即 LED1) 状态
}

问题

1 GPIO_INIT 函数什么作用

初始化output的GPIO:引脚11,输出模式,speed

2 EXTI_INT_INIT 函数什么作用

初始化input的GPIO:引脚0,输入模式

初始化外部中断:外部中断线,中断or事件,哪种触发方式

初始化中断控制器:中断源,中断优先级,子优先级

3 main 函数什么作用

执行初始化,死循环让服务常驻

4 中断服务函数什么作用

发生中断时根据信号改变

参考

https://blog.csdn.net/k666499436/article/details/124181471

https://blog.csdn.net/Psidium/article/details/125904190 (很好的解释了GPIO初始化的各个属性)

https://blog.csdn.net/YOURUOLI/article/details/123394459 EXTI外部中断原理与配置

https://www.cnblogs.com/wahahahehehe/p/15216388.html 2.2 解释了__attribute__((interrupt(“WCH-Interrupt-fast”))) 的作用

你可能感兴趣的:(开发板,CH32V307,单片机,stm32,嵌入式硬件)