天天看点

GD32系列外部中断起因介绍GD32的外部中断介绍软件配置工程示例

起因介绍

因为公司之前用GD32F4和周立功的CSM300产品的一个SPI转CAN模块,做了个产品,其在收到CAN帧时INT引脚会为由高电平转为低电平。需要做一个中断接收的程序防止丢包。

GD32系列外部中断起因介绍GD32的外部中断介绍软件配置工程示例

GD32的外部中断介绍

◼ 高效的中断处理;

◼ 支持异常抢占和咬尾中断;

◼ 将系统从省电模式唤醒;

◼ 3 种触发类型:上升沿触发,下降沿触发和任意沿触发;

◼ 软件中断或事件触发;

◼ 可配置的触发源。

GD32系列外部中断起因介绍GD32的外部中断介绍软件配置工程示例

简单介绍下它的一些必备知识,后面我们能用得到的。

首先就是GD32的中断线

GD32系列外部中断起因介绍GD32的外部中断介绍软件配置工程示例

这个图很清楚的表示了中断线和硬件引脚之间的关系

即:所有的0号引脚例如PA0/PB0/PC0等由0线代表,所有的1号引脚有1线表示以此类推。

各系列外部中断的差异

GD32系列外部中断起因介绍GD32的外部中断介绍软件配置工程示例

软件配置

1. 时钟配置

不同系列的GD32单片机的时钟配置略有差别,

void rcu_config(void)
{
#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X
rcu_periph_clock_enable(RCU_GPIOA);
#elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X
rcu_periph_clock_enable(RCU_GPIOA);
#if defined GD32F1X0 || GD32F3X0 || GD32E23X
rcu_periph_clock_enable(RCU_CFGCMP);
#elif defined GD32F4XX
rcu_periph_clock_enable(RCU_SYSCFG);
#endif
#endif
}
           

代码意思为,前两个if所判断的单片机只需要配置相应引脚所在的组的时钟就可以了,第三个if意思为开启RCU_CFGCMP时钟,第四个意思为开启系统时钟。

2. GPIO引脚的配置

对需要配置外部中断的引脚进行初始化

void gpio_config(void)
{
#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X
 gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
#elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X
 gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
#endif
}
           

主要区别就是不同系列单片机的初始化函数不同,一个是

gpio_init

一个是

gpio_mode_set

3. 外设配置

在代码中,首先使能

EXTI中断,之后配置EXTI源以及所需要的边沿,最后清除EXTI中断标志。

void exti_config(void)
{
#if defined GD32F10X_HD|| GD32F30X_HD || GD32F1X0 || GD32F20X_CL || GD32F4XX || GD32F3X0 || GD32E10X ||
GD32E23X
#if defined GD32F1X0 || GD32F3X0 || GD32E23X || GD32F4XX
#if defined GD32E23X
/* enable and set key EXTI interrupt to the lowest priority */
nvic_irq_enable(EXTI0_1_IRQn, 2U);
 #elif defined GD32F4XX
 nvic_irq_enable(EXTI0_IRQn, 2U,0U);
#elif defined GD32F1X0 || GD32F3X0
nvic_irq_enable(EXTI0_1_IRQn, 2U,0U);
#endif
/* connect key EXTI line to key GPIO pin */
syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN0);
/* configure key EXTI line */
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_0);
#else
 nvic_irq_enable(EXTI0_IRQn, 2U,0U);
 gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_0);
/* configure key EXTI line */
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_0);
#endif
#endif
}
           

这个意思也很清楚,根据不同系列单片机,选择不同语句,我这里用的是GD32F4系列所以使用到

//nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  
		nvic_irq_enable(EXTI5_9_IRQn, 2U, 0U);

        /* connect key EXTI line to key GPIO pin */
        syscfg_exti_line_config(EXTI_SOURCE_GPIOD, EXTI_SOURCE_PIN6);

        /* configure key EXTI line */
        exti_init(EXTI_6, EXTI_INTERRUPT, EXTI_TRIG_RISING);
        exti_interrupt_flag_clear(EXTI_6);
	 
           

这四句话。

详细解读下重要语句

第一句,因为我这里用的是D6脚所以这里的中断号选择

EXTI5_9_IRQn

,后面参数参考上面的代码选择就可以了

第二句,这里需要配置为你所需要配置的外部中断引脚(我这里是D6脚)

第三句,因为我这里是D6脚,由上面那个表可知我们需要选择6号中断线即EXTI_6

第四句,清EXTI_6的中断标志位

4. 中断处理函数

void EXTI5_9_IRQHandler(void)
{
if(exti_interrupt_flag_get(EXTI_6) == SET)
{
//用户代码
 exti_interrupt_flag_clear(EXTI_6);
}
}
           

因为我的中断号为

EXTI5_9_IRQn

所以我的中断函数名为

EXTI5_9_IRQHandler

工程示例

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "GPIO.h"
#include "SPI.h"
#include "CSM300.h"


/************************************************************************
 GD32F407开发板实验:SPI通讯实验
 技术支持:010-57273301
 淘宝店铺:乾勤科技
 官网:http://www.qianqin.com.cn/
 作者:	QianQin
*************************************************************************/
/************************************************************************
发送和接收数组组成
*第一个字节       帧头
*第二个字节       帧数据长度(除了帧头帧尾都算)
*第三个字节		    帧类型  扩展帧为0x08 标准帧为0x00
*第四第五个字节   帧ID,此为标准帧ID仅有两个字节,扩展帧字节变为四个
*第六~十三字节    数据  
*第十四字节       帧尾
******************************************************************************/
unsigned char send1[8]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
unsigned char send2[8]={0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};
unsigned char get[14];
void  initexit(void);


int main(void)
{
 	Gpio_Init();
	systick_config();
	rcu_config();
	SPI0_Init();//SPI初始化
	ConfigModule();		//配置CSM300芯片参数
	Mode_Init();
    initexit();
	while(1)
	{		
	
		delay_1ms(100);
		Write_bytes(send1,0x555);//发数据测试
//		delay_1ms(100);	
//		Write_bytes(send2,0x285);//发数据测试
		
	
	
	//read_status();//读状态测试
		
	/*	此为查询接收
	//can卡发数据接收测试解除这部分函数屏蔽记得把前面的  delay_1ms(100);   给屏蔽
		if(0==gpio_input_bit_get(GPIOD, GPIO_PIN_6))//检测INT脚是否为低电平
		{
		read_data(get);
		}
			*/
	}
}
//外部中断初始化函数引脚为D6
 void  initexit(void)
 {
	    rcu_periph_clock_enable(RCU_SYSCFG);
	 	//	rcu_periph_clock_enable(RCU_GPIOD);//要读取PC12的电平,需要开启RCU_GPIOC时钟
		  gpio_mode_set(RCU_GPIOD, GPIO_MODE_INPUT, GPIO_PUPD_NONE,GPIO_PIN_6);//将引脚PC12设为下拉输入 	
	
	    //nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  
			nvic_irq_enable(EXTI5_9_IRQn, 2U, 0U);                               //因为下面是EXTI_6所以这里要选EXTI5_9_IRQn,其中断函数就是EXTI5_9_IRQHandler

        /* connect key EXTI line to key GPIO pin */
        syscfg_exti_line_config(EXTI_SOURCE_GPIOD, EXTI_SOURCE_PIN6); //这边因为是D6脚所以要选EXTI_6  同理A4脚就是EXTI_4

        /* configure key EXTI line */
        exti_init(EXTI_6, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
        exti_interrupt_flag_clear(EXTI_6);
	 
	 
	 
 
 }

 //中断服务函数
 void EXTI5_9_IRQHandler(void)
{
	
    if (exti_interrupt_flag_get(EXTI_6) ==1) 
			{
        read_data(get);
        exti_interrupt_flag_clear(EXTI_6);	
    }
}

           

继续阅读