打印

GD32系列外部中断

[复制链接]
3489|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
磨砂|  楼主 | 2021-7-2 15:41 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
起因介绍

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


使用特权

评论回复
沙发
磨砂|  楼主 | 2021-7-2 15:43 | 只看该作者
GD32的外部中断介绍

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


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


使用特权

评论回复
板凳
磨砂|  楼主 | 2021-7-2 15:44 | 只看该作者
首先就是GD32的中断线


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


使用特权

评论回复
地板
磨砂|  楼主 | 2021-7-2 15:45 | 只看该作者
各系列外部中断的差异


使用特权

评论回复
5
磨砂|  楼主 | 2021-7-2 15:46 | 只看该作者
软件配置

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时钟,第四个意思为开启系统时钟。


使用特权

评论回复
6
磨砂|  楼主 | 2021-7-2 15:47 | 只看该作者
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


使用特权

评论回复
7
磨砂|  楼主 | 2021-7-2 15:48 | 只看该作者
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
}


使用特权

评论回复
8
磨砂|  楼主 | 2021-7-2 15:50 | 只看该作者
这个意思也很清楚,根据不同系列单片机,选择不同语句,我这里用的是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的中断标志位


使用特权

评论回复
9
磨砂|  楼主 | 2021-7-2 15:51 | 只看该作者
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


使用特权

评论回复
10
磨砂|  楼主 | 2021-7-2 15:52 | 只看该作者
工程示例


#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);
                }
                        */
        }
}


使用特权

评论回复
11
磨砂|  楼主 | 2021-7-2 15:53 | 只看该作者
//外部中断初始化函数引脚为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);
         
         
         

}


使用特权

评论回复
12
磨砂|  楼主 | 2021-7-2 15:55 | 只看该作者
//中断服务函数
void EXTI5_9_IRQHandler(void)
{
       
    if (exti_interrupt_flag_get(EXTI_6) ==1)
                        {
        read_data(get);
        exti_interrupt_flag_clear(EXTI_6);       
    }
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

85

主题

3886

帖子

2

粉丝