本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发
向上代码兼容GD32F450ZGT6中使用
后续项目主要在下面该专栏中发布:
https://blog.youkuaiyun.com/qq_62316532/category_12608431.html?spm=1001.2014.3001.5482
感兴趣的点个关注收藏一下吧!
电机驱动开发可以跳转:
GD32F103RCT6/GD32F303RCT6-实战项目-无刷电机驱动(1)_gd32f103rct6例程-优快云博客
BMS电源系统开发可以跳转:
暂未放链接
DCDC-双向BUCK-BOOST实战链接:
本教程使用开发板:
因为先前F4的开发板用于BMS储能开发,涉及隐私无法在此基础上继续公布,所以就手忙脚乱的自制了一块专门用于教程的开发板,部分还未焊接完毕,焊油也未洗掉,后续会慢慢美化的。
群号:621154399
有问题欢迎大家加入我们一起交流,这个群是开源性技术交流群。
介绍
具体详细介绍可以参考F1/F3系列教程:
主要特征
异常类型
手册中对应:
代码中对应:
可以在启动文件中找到以下内容:
Default_Handler PROC
; /* external interrupts handler */
EXPORT WWDGT_IRQHandler [WEAK]
EXPORT LVD_IRQHandler [WEAK]
EXPORT TAMPER_STAMP_IRQHandler [WEAK]
EXPORT RTC_WKUP_IRQHandler [WEAK]
EXPORT FMC_IRQHandler [WEAK]
EXPORT RCU_CTC_IRQHandler [WEAK]
EXPORT EXTI0_IRQHandler [WEAK]
EXPORT EXTI1_IRQHandler [WEAK]
EXPORT EXTI2_IRQHandler [WEAK]
EXPORT EXTI3_IRQHandler [WEAK]
EXPORT EXTI4_IRQHandler [WEAK]
EXPORT DMA0_Channel0_IRQHandler [WEAK]
EXPORT DMA0_Channel1_IRQHandler [WEAK]
EXPORT DMA0_Channel2_IRQHandler [WEAK]
EXPORT DMA0_Channel3_IRQHandler [WEAK]
EXPORT DMA0_Channel4_IRQHandler [WEAK]
EXPORT DMA0_Channel5_IRQHandler [WEAK]
EXPORT DMA0_Channel6_IRQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK]
EXPORT CAN0_TX_IRQHandler [WEAK]
EXPORT CAN0_RX0_IRQHandler [WEAK]
EXPORT CAN0_RX1_IRQHandler [WEAK]
EXPORT CAN0_EWMC_IRQHandler [WEAK]
EXPORT EXTI5_9_IRQHandler [WEAK]
EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK]
EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK]
EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK]
EXPORT TIMER0_Channel_IRQHandler [WEAK]
EXPORT TIMER1_IRQHandler [WEAK]
EXPORT TIMER2_IRQHandler [WEAK]
EXPORT TIMER3_IRQHandler [WEAK]
EXPORT I2C0_EV_IRQHandler [WEAK]
EXPORT I2C0_ER_IRQHandler [WEAK]
EXPORT I2C1_EV_IRQHandler [WEAK]
EXPORT I2C1_ER_IRQHandler [WEAK]
EXPORT SPI0_IRQHandler [WEAK]
EXPORT SPI1_IRQHandler [WEAK]
EXPORT USART0_IRQHandler [WEAK]
EXPORT USART1_IRQHandler [WEAK]
EXPORT USART2_IRQHandler [WEAK]
EXPORT EXTI10_15_IRQHandler [WEAK]
EXPORT RTC_Alarm_IRQHandler [WEAK]
EXPORT USBFS_WKUP_IRQHandler [WEAK]
EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK]
EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK]
EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK]
EXPORT TIMER7_Channel_IRQHandler [WEAK]
EXPORT DMA0_Channel7_IRQHandler [WEAK]
EXPORT EXMC_IRQHandler [WEAK]
EXPORT SDIO_IRQHandler [WEAK]
EXPORT TIMER4_IRQHandler [WEAK]
EXPORT SPI2_IRQHandler [WEAK]
EXPORT UART3_IRQHandler [WEAK]
EXPORT UART4_IRQHandler [WEAK]
EXPORT TIMER5_DAC_IRQHandler [WEAK]
EXPORT TIMER6_IRQHandler [WEAK]
EXPORT DMA1_Channel0_IRQHandler [WEAK]
EXPORT DMA1_Channel1_IRQHandler [WEAK]
EXPORT DMA1_Channel2_IRQHandler [WEAK]
EXPORT DMA1_Channel3_IRQHandler [WEAK]
EXPORT DMA1_Channel4_IRQHandler [WEAK]
EXPORT ENET_IRQHandler [WEAK]
EXPORT ENET_WKUP_IRQHandler [WEAK]
EXPORT CAN1_TX_IRQHandler [WEAK]
EXPORT CAN1_RX0_IRQHandler [WEAK]
EXPORT CAN1_RX1_IRQHandler [WEAK]
EXPORT CAN1_EWMC_IRQHandler [WEAK]
EXPORT USBFS_IRQHandler [WEAK]
EXPORT DMA1_Channel5_IRQHandler [WEAK]
EXPORT DMA1_Channel6_IRQHandler [WEAK]
EXPORT DMA1_Channel7_IRQHandler [WEAK]
EXPORT USART5_IRQHandler [WEAK]
EXPORT I2C2_EV_IRQHandler [WEAK]
EXPORT I2C2_ER_IRQHandler [WEAK]
EXPORT USBHS_EP1_Out_IRQHandler [WEAK]
EXPORT USBHS_EP1_In_IRQHandler [WEAK]
EXPORT USBHS_WKUP_IRQHandler [WEAK]
EXPORT USBHS_IRQHandler [WEAK]
EXPORT DCI_IRQHandler [WEAK]
EXPORT TRNG_IRQHandler [WEAK]
EXPORT FPU_IRQHandler [WEAK]
用于中断发生后的处理查找
相信大家也看见了其中两个特殊函数,没错,就是我们在编写F1系列的UCOSIII移植教程的过程中修改的两个中断:
结构框图
EXTI包含 23 个相互独立的边沿检测电路并且可以向处理器产生中断请求或事件唤醒。 EXTI 提供 3 种触发类型:上升沿触发,下降沿触发和任意沿触发。 EXTI 中每个边沿检测电路都可以分别予以配置或屏蔽。EXTI 触发源包括来自 I/O 管脚的 16 根线以及来自内部模块的 7 根线,具体细节参考触发源表格 。通过配置 SYSCFG_EXTISSx 寄存器,所有的 GPIO 管脚都可以被选作 EXTI 的触发源,
EXTI触发源
EXTI 线编号 | 触发源 |
0 | PA0/PB0/PC0/PD0/PE0/PF0/PG0 |
1 | PA1/PB1/PC1/PD1/PE1/PF1/PG1 |
2 | PA2/PB2/PC2/PD2/PE2/PF2/PG2 |
3 | PA3/PB3/PC3/PD3/PE3/PF3/PG3 |
4 | PA4/PB4/PC4/PD4/PE4/PF4/PG4 |
5 | PA5/PB5/PC5/PD5/PE5/PF5/PG5 |
6 | PA6/PB6/PC6/PD6/PE6/PF6/PG6 |
7 | PA7/PB7/PC7/PD7/PE7/PF7/PG7 |
8 | PA8/PB8/PC8/PD8/PE8/PF8/PG8 |
9 | PA9/PB9/PC9/PD9/PE9/PF9/PG9 |
10 | PA10/PB10/PC10/PD10/PE10/PF10/PG10 |
11 | PA11/PB11/PC11/PD11/PE11/PF11/PG11 |
12 | PA12/PB12/PC12/PD12/PE12/PF12/PG12 |
13 | PA13/PB13/PC13/PD13/PE13/PF13/PG13 |
14 | PA14/PB14/PC14/PD14/PE14/PF14/PG14 |
15 | PA15/PB15/PC15/PD15/PE15/PF15/PG15 |
16 | LVD |
17 | RTC 闹钟 |
18 | USB 唤醒 |
EXTI寄存器
本章寄存器和库函数讲解,大部分我们依旧可以参考之前F1系列的文章:
具体详细介绍可以参考F1/F3系列教程:
本章以基于F1/F303以前教程为基础升级而来,因此对于重复的内容就不做过多追叙了。
按键中断控制LED实验
演示视频:
按键中断控制LED演示视频
编程要点:
1.使能 GPIO 端口时钟
2.初始化 EXTI
3.配置 NVIC
4.编写中断服务函数
我们本期讲解依旧以模块化的方式进行,以便丰富我们的外设库文件!
详细模块化编程以及按键注意事项可以参考F1文章:
通过按下按键达到翻转LED电平状态
按键在原理图中对应的引脚为:
PG2-PG6
首先便是存在于bsp_key.c中的按键初始化函数。
/**
@brief 按键驱动初始化
@param 无
@return 无
*/
void Key_GPIO_Init(void)
{
rcu_periph_clock_enable(KEY1_GPIO_CLK);
gpio_mode_set(KEY1_GPIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP,KEY1_GPIO_PIN);
gpio_mode_set(KEY2_GPIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP,KEY2_GPIO_PIN);
gpio_mode_set(KEY3_GPIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP,KEY3_GPIO_PIN);
gpio_mode_set(KEY4_GPIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP,KEY4_GPIO_PIN);
gpio_mode_set(KEY5_GPIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP,KEY5_GPIO_PIN);
以及我们的按键检测函数:
/*
* 函数名:Key_Scan
* 描述 :检测是否有按键按下
* 输入 :GPIOx:x 可以是 A,B,C,D或者 E
* GPIO_Pin:待读取的端口位
* 输出 :KEY_OFF(没按下按键)、KEY_ON(按下按键)
*/
uint8_t Key_Scan(uint32_t gpio_periph, uint32_t pin)
{
/*检测是否有按键按下 */
if(gpio_input_bit_get(gpio_periph, pin) == KEY_ON)
{
/*等待按键释放 */
while(gpio_input_bit_get(gpio_periph, pin) == KEY_ON);
return KEY_ON;
}
else
return KEY_OFF;
}
其次是存在于中断文件bsp_exti.h中的中断初始化函数:
/*********************************************************************
*
*/
/**
@brief 按键外部中断初始化
@param 无
@return 无
*/
void Key_EXTI_Init(void)
{
rcu_periph_clock_enable(RCU_SYSCFG);
// 设置优先级分组
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
nvic_irq_enable(EXTI2_IRQn, 0U, 2U);
nvic_irq_enable(EXTI3_IRQn, 0U, 2U);
nvic_irq_enable(EXTI4_IRQn, 0U, 2U);
nvic_irq_enable(EXTI5_9_IRQn, 0U, 2U);
/* connect key EXTI line to key GPIO pin */
syscfg_exti_line_config(EXTI_SOURCE_GPIOG, EXTI_SOURCE_PIN2 );
syscfg_exti_line_config(EXTI_SOURCE_GPIOG, EXTI_SOURCE_PIN3 );
syscfg_exti_line_config(EXTI_SOURCE_GPIOG, EXTI_SOURCE_PIN4 );
syscfg_exti_line_config(EXTI_SOURCE_GPIOG, EXTI_SOURCE_PIN5 );
syscfg_exti_line_config(EXTI_SOURCE_GPIOG, EXTI_SOURCE_PIN6 );
/* configure key EXTI line */
exti_init( EXTI_2 , EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_init( EXTI_3 , EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_init( EXTI_4 , EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_init( EXTI_5 , EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_init( EXTI_6 , EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_2 );
exti_interrupt_flag_clear(EXTI_3 );
exti_interrupt_flag_clear(EXTI_4 );
exti_interrupt_flag_clear(EXTI_5 );
exti_interrupt_flag_clear(EXTI_6 );
}
其次就是存放于gd32f4xx_it.c中的中断处理函数了:
void EXTI2_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_2))
{
LED1_TOG;
exti_interrupt_flag_clear(EXTI_2);
}
}
void EXTI3_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_3))
{
LED2_TOG;
exti_interrupt_flag_clear(EXTI_3);
}
}
void EXTI4_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_4))
{
LED3_TOG;
exti_interrupt_flag_clear(EXTI_4);
}
}
void EXTI5_9_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_5))
{
LED4_TOG;
exti_interrupt_flag_clear(EXTI_5);
}
if(RESET != exti_interrupt_flag_get(EXTI_6))
{
LED5_TOG;
exti_interrupt_flag_clear(EXTI_6);
}
}
抢占优先级,数字越小,优先级越高
若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高
当中断发生时,对应的中断服务函数就会被执行,我们可以在中断服务函数实现一些控制。
一般为确保中断确实发生,我们会在中断服务函数中调用中断标志位状态读取函数读取外设中断标志位并判断标志位状态。
代码完成编写,现在烧录!
与实验预期相符合,完成!
具体代码请参考例程
可以关注我,点个关注获取本节例程哦