stm32基于Ucos消息队列的空闲中断信息读取储存和发送
来源:互联网 发布:海关数据编码查询 编辑:程序博客网 时间:2024/05/29 14:14
最近做一个中继,一边是基于Wifi的网络,一边是基于串口的嵌入式设备。两者之间通过中继进行通信。
具体结构:
网络设备(手机,pad,PC等等)→→ WIFI网络→→ UART1→→ STM32消息队列→→UART2→→ 嵌入式设备
直连的话会遇到以下 2 个问题:
1.当WIFI网络或嵌入式设备发送来的数据过多,接收后来不及发送给另一边。数据会丢失
2.数据不定长
所以用了下面 2 个解决方法:
1.基于Ucos的消息队列:将接收到的数据立刻存入队列中,达到一个缓冲的目的。保证接收到数据都发送出去,当然缓冲时的数据不能多余消息队列的开的大小。(消息队列开的过大会造成硬件中断,所有程序无法执行。)
2.串口空闲中断,当串口idle中断时,通过控制DMA通道的使能,来接收数据。节约CPU资源。稳定可靠。
PCB截图:
开始码代码:
STM32的Ucos移植就不说了,网上一抓一大把。
首先搭建任务,很明显这个项目里需要两个Task。
一个是Task_ReadFromWifi(),用来从wifi网络中读取数据,然后存入消息队列
另一个是Task_ReadFromUart(),用来从嵌入式设备中读取数据,然后存入消息队列
构建任务,每一个任务相当于一个线程。他需要三个必须的东西:身份证(任务管理模块),房子(栈),大脑(代码块)。
首先分别设置优先级和分配栈
<span style="font-size:18px;"><span style="font-size:18px;">/*******************ÉèÖÃÈÎÎñÓÅÏȼ¶*******************/#define TASK_READFROMWIFI_PRIO 5#define TASK_READFROMUART_PRIO 6//#define TASK_TESTLED_PRIO 6/************ÉèÖÃÕ»´óС£¨µ¥Î»Îª OS_STK £©************/#define TASK_READFROMWIFI_STK_SIZE 256#define TASK_READFROMUART_STK_SIZE 256//#define TASK_TESTLED_STK_SIZE 20</span></span>
定义任务
<span style="font-size:18px;">OS_STK task_readfromwifi[TASK_READFROMWIFI_STK_SIZE];OS_STK task_readfromuart[TASK_READFROMUART_STK_SIZE];</span>
完成准备任务后,再去main内创建并开始任务:
<span style="font-size:18px;"> BSP_Init(); OSInit(); OSTaskCreate(Task_ReadFromWifi,(void *)0, &task_readfromwifi[TASK_READFROMWIFI_STK_SIZE-1], TASK_READFROMWIFI_PRIO);OSTaskCreate(Task_ReadFromUart,(void *)0, &task_readfromuart[TASK_READFROMUART_STK_SIZE-1], TASK_READFROMUART_PRIO);OSStart();</span>
<span style="font-size:18px;">void Task_ReadFromWifi(void *p_arg){uint8_t *s; INT8U err; while (1) { s = OSQPend(QSem,0,&err); if(err==OS_NO_ERR) { printf("\r\nMsgFromPhone =\r\n "); Puts_UART2(s);//´®¿Ú2·¢Ë͸øPad } OSTimeDly(20); }}//↑任务1</span>
<span style="font-size:18px;">//↓任务2void Task_ReadFromUart(void *p_arg){uint8_t *s;INT8U err;while(1){s=OSQPend(QSem2,0,&err);if(err==OS_NO_ERR){printf("\r\nMsgFromPC =\r\n ");Puts_UART2(s);Puts_UART1(s);//´®¿Ú1·¢Ë͸øµçÄÔ}OSTimeDly(20);}}</span>
搭建好基本的后,准备消息队列:(调试过程中,出于贪心,我想把数列开的大一点,所以#define了
MsgQequeTabNum 20,结果硬件中断,单步调试发现,程序都不运行到main的第一句话就直接炸了,后来发现时栈溢出的原因,坑了好久。)
<span style="font-size:18px;">#define MSG_QUEUE_TABNUM 10extern OS_EVENT *QSem;extern OS_MEM *PartitionPt;extern uint8_t Partition[MSG_QUEUE_TABNUM][400];extern void *MsgQeueTb[MSG_QUEUE_TABNUM];extern OS_EVENT *QSem2;extern OS_MEM *PartitionPt2;extern uint8_t Partition2[MSG_QUEUE_TABNUM][400];extern void *MsgQeueTb2[MSG_QUEUE_TABNUM];</span>
然后再Main内:
<span style="font-size:18px;">QSem = OSQCreate(&MsgQeueTb[0],MSG_QUEUE_TABNUM); PartitionPt=OSMemCreate(Partition,MSG_QUEUE_TABNUM,400,&err);QSem2 = OSQCreate(&MsgQeueTb2[0],MSG_QUEUE_TABNUM); PartitionPt2=OSMemCreate(Partition2,MSG_QUEUE_TABNUM,400,&err);</span>
<span style="font-size:18px;">//OS_EVENT *QSem;void *MsgQeueTb[MSG_QUEUE_TABNUM];OS_MEM *PartitionPt;uint8_t Partition[MSG_QUEUE_TABNUM][400];// OS_EVENT *QSem2; void *MsgQeueTb2[MSG_QUEUE_TABNUM]; OS_MEM *PartitionPt2; uint8_t Partition2[MSG_QUEUE_TABNUM][400];</span>
接下来只需要配置串口的空闲中断就可以了,空闲中断有很多优点:
可以接受不定长数组;
并且更加节约资源,不需要你在一个线程内一直在等待接收数据,或者像之前一样用查询的方式去监听;
谁用谁知道!。
之前转的一篇文章已经很详细的给了stm32串口空闲中断的代码和介绍了,
里面有各个模块的配置 GPIO DMA UART NVIC
在此就不多说了。
可移步:
http://blog.csdn.net/lxk7280/article/details/49700663
注意一点就是DMA的不同频道对应的外设是不同的,不要弄错了,整理了一下,贴上来:
DMA1 Channel1:ADC1 TIM2_CH3 TIM4_CH1 DMA1
DMA1 Channel2:USART3_TX TIM1_CH1 TIM2_UP TIM3_CH3 SPI1_RX
DMA1_Chanel3:USART3_RXTIM1_CH2TIM3_CH4TIM3_UPSPI1_TX
DMA1_Chanel4:USART1_TXTIM1_CH4TIM1_TRIGTIM1_COMTIM4_CH2SPI/I2S2_RXI2C2_TX
DMA1_Chanel5:USART1_RXTIM1_UPSPI/I2S2_TXTIM2_CH1TIM4_CH3I2C2_RX
DMA1_Chanel6:USART2_RXTIM1_CH3TIM3_CH1TIM3_TRIGI2C1_TX
DMA1_Chanel7:USART2_TXTIM2_CH2TIM2_CH4TIM4_UPI2C1_RX
DMA2_Chanel1:SPI/I2S3_RXTIM5_CH4TIM5_TRIGTIM8_CH3TIM8_UP
DMA2_Chanel2:SPI/I2S3_TXTIM5_CH3TIM5_UPTIM8_CH4TIM8_TRIGTIM8_COM
DMA2_Chanel3:UART4_RXTIM6_UPDAC1TIM8_CH1
DMA2_Chanel4:SDIOTIM5_CH2TIM7_UPDAC2
DMA2_Chanel5:ADC3UART4_TXTIM5_CH1TIM8_CH2
果然不丢失数据了诶,实际测试以10ms的间隔同时互相发送数据,完全没有问题。我们有理由相信1ms的间隔也是没问题的,`(*∩_∩*)′,不过这个项目的中继也不会接受那么高频率的数据的。。。
WIFI网络的手机和设备串口效果图:
WIFI网络的PC和设备串口效果图:
- stm32基于Ucos消息队列的空闲中断信息读取储存和发送
- STM32的串口空闲中断
- stm32的串口空闲中断接收数据
- stm32的串口空闲中断接收数据
- IPC--消息队列 message queue(消息队列的创建,信息的发送和接收)
- ucos消息队列的使用
- 基于IAR和STM32的uCOS-II移植
- 基于消息队列的信息传输机制
- STM32串口中断接收和中断发送
- STM32的串口中断发送
- 基于对话框的空闲消息处理
- uCOS-II邮箱和消息队列
- uCOS-II邮箱和消息队列
- uCOS-II邮箱和消息队列
- UCOS消息队列的使用【转+原创】
- UCOS消息队列的使用【转】
- uCOS II 消息队列的使用方法
- uCOS II 消息队列的使用方法
- 注解(浅谈Dagger,ButterKnife,Roboguide)
- linux-2.6.32在mini2440开发板上移植之DM9000网卡移植
- sicily 1308. Dependencies among J
- APUE学习笔记——标准I/O
- x86计算机启动过程分析
- stm32基于Ucos消息队列的空闲中断信息读取储存和发送
- iOS界面卡顿及解决方案
- JAVA 正则表达式
- 谈谈JavaScript里对象的创建和继承(一)
- 使用通道和byteBuffer进行大文件分批传输
- Android Studio导入Eclipse项目源码
- Android开发之SharedPreferences详解
- iOS开发:设计常用炫酷第三方库
- 安卓自定义控件之坐标存储类