大部分国产低端MCU没有空闲中断怎么办?

设计背景:
针对大部分国产低端mcu(arm-cortexm0)来说,并没有空闲中断,此时就需要一个定时器timer配合来完成此任务。对于uart接受不定长数据,空闲中断还是非常实用的!
知识点:
freertos的二值信号量 timer uart
空闲中断的原理:
idle中断叫空闲中断,不叫帧中断。那么什么叫空闲,怎么定义空闲呢?在实际发送数据的时候,比如一串字符串,其实发送的两个字符之间间隔非常短,所以在两个字符之间不叫空闲。空闲的定义是总线上在一个字节的时间内没有再接收到数据,空闲中断是检测到有数据被接收后,总线上在一个字节的时间内没有再接收到数据的时候发生的。而总线在什么情况时,会有一个字节时间内没有接收到数据呢?一般就只有一个数据帧发送完成的情况,所以串口的空闲中断也叫帧中断。
开发环境:
win10, mdk5.28, hc32l136
设计步骤: 这里不做长篇大论,列举了重要的核心部分讲解,便于大家移植。附件中带有完整的工程代码。
首先定义一个结构体和信号量。
extern semaphorehandle_t at_rx_semaphore;
/*用于空闲中断判断*/typedef struct{uint16_t uart_cnt;uint16_t timer_cnt;}stcuart_idle;
extern stcuart_idle uart_idle;
2. 串口部分代码:
/********************************************************************************************** *函数功能:初始化uart *uartx:选择初始化uart端口号 *parity:奇偶校验位 *说明io用使用复位模式2,dma默认是使能***********************************************************************************************/void bsp_uartx_init(m0p_uart_typedef *uartx, uint32_t baud, en_uart_mmdorck_t parity){ if(uartx == m0p_uart0) { uart0_init(baud,parity); enablenvic(uart0_irqn, irqlevel3, true); ///《系统中断使能 } if(uartx == m0p_uart1) { enablenvic(uart1_irqn, irqlevel3, true); ///《系统中断使能 } }
//串口0模块配置static void uart0_init(uint32_t baud, en_uart_mmdorck_t parity){ stc_gpio_cfg_t stcgpiocfg; stc_uart_cfg_t stccfg; stc_uart_baud_t stcbaud;
ddl_zero_struct(stcgpiocfg); ddl_zero_struct(stccfg); ddl_zero_struct(stcbaud);
sysctrl_setperipheralgate(sysctrlperipheralgpio,true); //gpio外设模块时钟使能
stcgpiocfg.endir = gpiodirout; gpio_init(gpioporta,gpiopin9,&stcgpiocfg); gpio_setafmode(gpioporta,gpiopin9,gpioaf1); //配置pa09 为uart0 tx stcgpiocfg.endir = gpiodirin; gpio_init(gpioporta,gpiopin10,&stcgpiocfg); gpio_setafmode(gpioporta,gpiopin10,gpioaf1);//配置pa10 为uart0 rx
sysctrl_setperipheralgate(sysctrlperipheraluart0,true);//uart0外设模块时钟使能
stccfg.enrunmode = uartmskmode3; //模式3 if(parity == uartmskeven) { stccfg.enmmdorck = uartmskeven; //偶校验 } else if(parity == uartmskodd) { stccfg.enmmdorck = uartmskodd; //奇校验 } else { stccfg.enrunmode = uartmskmode1; //模式1,奇偶检验无效 } stccfg.enstopbit = uartmsk1bit; //1位停止位 stccfg.stcbaud.u32baud = baud; //波特率9600 stccfg.stcbaud.enclkdiv = uartmsk8or16div; //通道采样分频配置 stccfg.stcbaud.u32pclk = sysctrl_getpclkfreq(); //获得外设时钟(pclk)频率值 uart_init(m0p_uart0, &stccfg); //串口初始化
uart_clrstatus(m0p_uart0,uartrc); //清接收请求 uart_clrstatus(m0p_uart0,uarttc); //清发送请求 uart_enableirq(m0p_uart0,uartrxirq); //使能串口接收中断 //uart_enableirq(m0p_uart0,uarttxirq); //使能串口发送中断 //使能dma发送, dma相关通道使能后,如果tx buff为空,会立马启动传输 uart_enablefunc(m0p_uart0,uartdmatxfunc); }
3. 编写uart中断函数
在这里采用了循环数组接收,没有使用队列,可以省点资源,效果差不多,数组处理更方便。
4. timer定时器,这里选用2ms周期中断,并通过uart中断中启动,在timer中断中关闭。
#include “bsp_timer.h”
#include “bsp_uart.h”
semaphorehandle_t binsem_uart_idle;
//timer3 配置,用于uart0 的空闲中断void bsp_timer3_init(uint16_t u16period){ uint16_t u16arrvalue; uint16_t u16cntvalue; stc_tim3_mode0_cfg_t stctim3basecfg; //结构体初始化清零 ddl_zero_struct(stctim3basecfg);
sysctrl_setperipheralgate(sysctrlperipheraltim3, true); //base timer外设时钟使能
stctim3basecfg.enworkmode = tim3workmode0; //定时器模式 stctim3basecfg.enct = tim3timer; //定时器功能,计数时钟为内部pclk stctim3basecfg.enprs = tim3pclkdiv32; //pclk/32 stctim3basecfg.encntmode = tim316bitarrmode; //自动重载16位计数器/定时器 stctim3basecfg.bentog = false; stctim3basecfg.bengate = false; stctim3basecfg.engatep = tim3gatepositive;
tim3_mode0_init(&stctim3basecfg); //tim3 的模式0功能初始化 u16arrvalue = 0x10000 - u16period ; tim3_m0_arrset(u16arrvalue); //设置重载值(arr = 0x10000 - 周期) u16cntvalue = 0x10000 - u16period; tim3_m0_cnt16set(u16cntvalue); //设置计数初值 tim3_clearintflag(tim3uevirq); //清中断标志 tim3_mode0_enableirq(); //使能tim3中断(模式0时只有一个中断) enablenvic(tim3_irqn, irqlevel3, true); //tim3 开中断 //tim3_m0_run(); //tim3 运行}
/*去初始化,进低功耗功耗前调用此接口*/void bsp_timer3_deinit(void){ stc_tim3_mode0_cfg_t stctim3basecfg; ddl_zero_struct(stctim3basecfg); //结构体初始化清零 tim3_mode0_init(&stctim3basecfg); tim3_clearintflag(tim3uevirq); //清中断标志 tim3_mode0_disableirq(); tim3_m0_stop();}
uart和timer如何配合使用,上面的函数已经给出了。
最后,中断中已经给出了信号量,后续如何处理呢?
用一个任务去接收信号就好了:
实验效果:
原文标题:国产低端mcu(arm-cortexm0)没有空闲中断怎么办?这样设计!
文章出处:【微信公众号:嵌入式arm】欢迎添加关注!文章转载请注明出处。


[图文]深圳广播电台
UPS测评方法
一加7评测 不将就理念最好的体现
魅族最强旗舰魅族Pro6Plus现降至冰点价,三星890处理器性能了它性能的缺陷
一年一度 精彩更盛 | Samtec邀您参与2023 ICCAD
大部分国产低端MCU没有空闲中断怎么办?
智能电车系列之车载雷达“激光雷达”
华为彭松:深化战略合作,华为全面支撑广东电信产数协同快速发展
三星AMOLED屏幕生产量突破10亿 霸占99%市场
苹果多项专利曝光,AR耳机将可支持无线充电
使用跟踪的激光雷达看得更远
嵌入式Linux设计:文件系统和引导加载程序
福清首座5G智能垃圾分类屋能通过5G系统连接,实现数据可视化
MediaTek发布天玑8000 系列轻旗舰5G移动平台
为什么大家都喜欢用C语言编写操作系统
IBM Watson为什么会失败?
打破旧有网络模式,正当其时
三星A51白色版曝光搭载三星Exynos 9611处理器和后置四摄设计
汇川技术荣获CMCD2023年度运动控制领域最具影响力品牌奖
工业互联网产业联盟企业一览