关于STM32中多串口工作的问题

2019-08-13 22:22发布

各位大虾:
      本人刚接触STM32,菜鸟一个。 我最近遇到一个关于STM32中5个串口同时工作的问题,自己忙了一个多月,也查了不少资料,但问题依旧没有解决,所以当自己努力后还没解决问题就要向吧里的各位兄弟姐妹求教了,废话不多说,直奔主题

    任务要求是,4路串口分别接收各路数据,然后由一个串口发给上位机;每路数据一共5个字节    {FF 81 数据位 数据位 校验和  }  前两个是帧头和状态位,当中是两个数据位 ,最后是校验和

    我的设计思路是: 让串口2~5这四个串口分时接收数据,然后通过串口1发送给电脑; 即先让串口2工作,把串口3、4、5关掉,只有当串口2收到中断里面的正确的状态位并通过串口1发送出去之后关掉串口2,然后使能串口3,当串口3工作完后关掉串口3,如此以往

在中断里面所做的工作就是判断帧头、状态位、校验和正确则置标志位,总的来讲程序设计思路简单;

    我所碰到的问题:只让串口2和3接收,串口1发出,即在代码中注释掉串口4和5工作的部分,工作非常正常,一点问题也没有;
                               但是当加入串口4让串口2、3、4同时工作,偶尔这3个串口能正确收几次程序就死掉,运气不好的时候,刚轮到串口4工作就死掉了,但是我把其它串口工作部分注释掉只让串口4收串口1发又是正常的,我现在很纠结,不知道问题出在哪?也不知道该怎么解决?自己调了一个多月,没什么进展,前来向各位兄弟姐妹求教,望指点一二,谢谢!(我用的是战舰板调的,有没有战舰板上短路帽插错导致这种现象的可能?)

附上源码

这是USART.C  [mw_shl_code=c,true]#include "sys.h" #include "usart.h" u8 USART2_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. u8 USART3_RX_BUF[USART_REC_LEN]; u8 UART4_RX_BUF[USART_REC_LEN]; u8 UART5_RX_BUF[USART_REC_LEN]; u8 m=0; u8 n=0; u8 p=0; u8 q=0; u8 i=0; u16 USART2_RX_STA=0; //接收状态标记//接收状态标记 u16 USART3_RX_STA=0; u16 UART4_RX_STA=0; //接收状态标记 u16 UART5_RX_STA=0; //初始化串口1`5 //bound:波特率 void uart_init(u32 bound){ //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); //使能USART1,GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2|RCC_APB1Periph_USART3, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4|RCC_APB1Periph_UART5, ENABLE); USART_DeInit(USART1); //复位串口1`5 USART_DeInit(USART2); USART_DeInit(USART3); USART_DeInit(UART4); USART_DeInit(UART5); //USART1_TX USART2_TX PA.9 PA.2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_9; //PA.9与PA.2 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9 //USART1_RX USART2_RX PA.10 PA.3 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10 //USART3_TX PB.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.10 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PA9 //USART3_RX PB.11 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PA10 //UART4_TX UART5_TX PC10 PC12 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_12; //PC10 PC12 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC10 PC12 //UART4_RX PC11 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC11 //UART5_RX PD2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化 PD2 //USART1 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口 //USART2 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART2, &USART_InitStructure); //初始化串口 //USART3 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART3, &USART_InitStructure); //初始化串口 //UART4 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(UART4, &USART_InitStructure); //初始化串口 //UART5 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(UART5, &USART_InitStructure); //初始化串口 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断 NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断 NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启中断 NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);//开启中断 USART_Cmd(USART1, ENABLE); //使能串口 /* USART_Cmd(USART2, ENABLE); USART_Cmd(USART3, ENABLE); USART_Cmd(UART4, ENABLE); USART_Cmd(UART5, ENABLE); */ } void USART2_IRQHandler(void) //串口2中断服务程序 { u8 Res2; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) // { Res2=USART_ReceiveData(USART2);//(USART2->DR); //读取接收到的数据 USART2_RX_BUF[USART2_RX_STA]=Res2; USART2_RX_STA++; if(USART2_RX_STA==5) { USART2_RX_STA=0; i=USART2_RX_BUF[0]+USART2_RX_BUF[1]+USART2_RX_BUF[2]+USART2_RX_BUF[3]; if(USART2_RX_BUF[0]==0XFF&&USART2_RX_BUF[1]==0X81&&i==USART2_RX_BUF[4]) { m=0x01; } else {m=0;} } } } void USART3_IRQHandler(void) //串口3中断服务程序 { u8 Res3; if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) // { Res3=USART_ReceiveData(USART3);//(USART2->DR); //读取接收到的数据 USART3_RX_BUF[USART3_RX_STA]=Res3; USART3_RX_STA++; if(USART3_RX_STA==5) { USART3_RX_STA=0; i=USART3_RX_BUF[0]+USART3_RX_BUF[1]+USART3_RX_BUF[2]+USART3_RX_BUF[3]; if(USART3_RX_BUF[0]==0XFF&&USART3_RX_BUF[1]==0X81&&i==USART3_RX_BUF[4]) { n=0x01; } else {n=0;} } } } void UART4_IRQHandler(void) //串口4中断服务程序 { u8 Res4; if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET) // { Res4=USART_ReceiveData(UART4);//读取接收到的数据 UART4_RX_BUF[UART4_RX_STA]=Res4; UART4_RX_STA++; if(UART4_RX_STA==5) { UART4_RX_STA=0; i=UART4_RX_BUF[0]+UART4_RX_BUF[1]+UART4_RX_BUF[2]+UART4_RX_BUF[3]; if(UART4_RX_BUF[0]==0XFF&&UART4_RX_BUF[1]==0X81&&i==UART4_RX_BUF[4]) { p=0x01; } else {p=0;} } } } void UART5_IRQHandler(void) //串口5中断服务程序 { u8 Res5; if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET) { Res5=USART_ReceiveData(UART5);//读取接收到的数据 UART5_RX_BUF[UART5_RX_STA]=Res5; UART5_RX_STA++; if(UART5_RX_STA==5) { UART5_RX_STA=0; i=UART5_RX_BUF[0]+UART5_RX_BUF[1]+UART5_RX_BUF[2]+UART5_RX_BUF[3]; if(UART5_RX_BUF[0]==0XFF&&UART5_RX_BUF[1]==0X81&&i==UART5_RX_BUF[4]) { q=0x01; } else {q=0;} } } } USART.H部分的源码[/mw_shl_code] [mw_shl_code=c,true]#ifndef __USART_H #define __USART_H #include "stdio.h" #include "sys.h" #define USART_REC_LEN 5 //定义最大接收字节数 200 extern u8 USART2_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u8 USART3_RX_BUF[USART_REC_LEN]; extern u8 UART4_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u8 UART5_RX_BUF[USART_REC_LEN]; extern u8 m; extern u8 n; extern u8 p; extern u8 q; extern u16 USART2_RX_STA; //接收状态标记 extern u16 USART3_RX_STA; extern u16 UART4_RX_STA; //接收状态标记 extern u16 UART5_RX_STA; //如果想串口中断接收,请不要注释以下宏定义 void uart_init(u32 bound); #endif [/mw_shl_code]
main.c部分源码
  [mw_shl_code=c,true]#include "sys.h" #include "usart.h" int main(void) { u8 t=0; NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(9600); //串口初始化为9600 while(1) { //串口2 USART_Cmd(USART2, ENABLE); //使能串口2 while(m!=0X01); { USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);//在此处要关闭中断 m=0; for(t=0;t<5;t++) { USART_SendData(USART1, USART2_RX_BUF[t]);//向串口1发送数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束 } USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启串口中断 } USART_Cmd(USART2, DISABLE); //失能串口2 //串口3 USART_Cmd(USART3, ENABLE); while(n!=0X01); { USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);//在此处要关闭中断 n=0; for(t=0;t<5;t++) { USART_SendData(USART1, USART3_RX_BUF[t]);//向串口1发送数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束 } USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //开启串口中断 } USART_Cmd(USART3, DISABLE); //串口4 USART_Cmd(UART4, ENABLE); while(p!=0X01); { USART_ITConfig(UART4, USART_IT_RXNE, DISABLE);//在此处要关闭中断 p=0; for(t=0;t<5;t++) { USART_SendData(USART1, UART4_RX_BUF[t]);//向串口1发送数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束 } USART_ITConfig(UART4, USART_IT_RXNE, ENABLE); //开启串口中断 } USART_Cmd(UART4, DISABLE); // 串口5 USART_Cmd(UART5, ENABLE); while(q!=0X01); { USART_ITConfig(UART5, USART_IT_RXNE, DISABLE);//在此处要关闭中断 q=0; for(t=0;t<5;t++) { USART_SendData(USART1, UART5_RX_BUF[t]);//向串口1发送数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束 } USART_ITConfig(UART5, USART_IT_RXNE, ENABLE); //开启串口中断 } USART_Cmd(UART5, DISABLE); } } [/mw_shl_code]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
正点原子
1楼-- · 2019-08-14 03:33
死机的时候,是死在哪里?
仿真跟踪看过没有?
小李刀
2楼-- · 2019-08-14 06:25
就是程序在主函数运行完串口2、串口3的工作部分后,到串口4就不行了,请问原子,是我哪的配置有问题还是程序逻辑上有问题?
Admin
3楼-- · 2019-08-14 08:20
看还是很难看出问题。
还是要debug调试具体到底是在哪里出问题
zzpxx
4楼-- · 2019-08-14 12:06
 精彩回答 2  元偷偷看……
weilexuexi12
5楼-- · 2019-08-14 12:21
您好请问您问题解决了吗》?我也遇到类似的问题了了,求指点啊。
hstar
6楼-- · 2019-08-14 13:54
跑个RTOS吧,操作系统里面的消息队列完全可以实现你的需求,完全不需要关掉串口再开启什么的。

一周热门 更多>