STM32
直播中

陈利妮

7年用户 957经验值
私信 关注
[问答]

如何实现GD32外部中断的软件配置

如何实现GD32外部中断的软件配置

回帖(1)

陆欣楠

2021-11-17 14:43:23
起因介绍

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

  

  

  GD32的外部中断介绍

  ◼ 高效的中断处理;
◼ 支持异常抢占和咬尾中断;
◼ 将系统从省电模式唤醒;
◼ 3 种触发类型:上升沿触发,下降沿触发和任意沿触发;
◼ 软件中断或事件触发;
◼ 可配置的触发源。

  

  

简单介绍下它的一些必备知识,后面我们能用得到的。
  首先就是GD32的中断线

  
  

  

这个图很清楚的表示了中断线硬件引脚之间的关系
即:所有的0号引脚例如PA0/PB0/PC0等由0线代表,所有的1号引脚有1线表示以此类推。
  各系列外部中断的差异

  
  

  

  
软件配置
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
#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);       
    }
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分