之前碰巧有个项目需要多个串口,用的是ST自带的5个串口没有用扩展芯片
百度网盘链接
链接:https://pan.baidu.com/s/1sC3zPWN2pGzrAn4cZ2sq9g?pwd=6666
提取码:6666
介绍
1.MCU型号:STM32F103VET6
2.标准库
遇到的问题
1.5个中断同时开启接收数据,即使设置了优先级,还是会出现卡死现象
2.5个中断开启时,printf 重定义如何兼容5个串口
3.如何将5个串口实现通用配置,兼容STF10XXX系列
4.在单片机中截取字符串,比较字符串,查找字符串
下面开始一一解答
5个串口的GPIO配置:
void USART1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// ´ò¿ª´®¿ÚGPIOµÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// ´ò¿ª´®¿ÚÍâÉèµÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// ½«USART TxµÄGPIOÅäÖÃΪÍÆÍ츴ÓÃģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// ½«USART RxµÄGPIOÅäÖÃΪ¸¡¿ÕÊäÈëģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void USART2_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// ´ò¿ª´®¿ÚGPIOµÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// ´ò¿ª´®¿ÚÍâÉèµÄʱÖÓ
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// ½«USART TxµÄGPIOÅäÖÃΪÍÆÍ츴ÓÃģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// ½«USART RxµÄGPIOÅäÖÃΪ¸¡¿ÕÊäÈëģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void USART3_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// ´ò¿ª´®¿ÚGPIOµÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// ´ò¿ª´®¿ÚÍâÉèµÄʱÖÓ
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// ½«USART TxµÄGPIOÅäÖÃΪÍÆÍ츴ÓÃģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// ½«USART RxµÄGPIOÅäÖÃΪ¸¡¿ÕÊäÈëģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void USART4_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// ´ò¿ª´®¿ÚGPIOµÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
// ´ò¿ª´®¿ÚÍâÉèµÄʱÖÓ
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
// ½«USART TxµÄGPIOÅäÖÃΪÍÆÍ츴ÓÃģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// ½«USART RxµÄGPIOÅäÖÃΪ¸¡¿ÕÊäÈëģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void USART5_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// ´ò¿ª´®¿ÚGPIOµÄʱÖÓ
RCC_APB2PeriphClockCmd((RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD), ENABLE);
// ´ò¿ª´®¿ÚÍâÉèµÄʱÖÓ
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
// ½«USART TxµÄGPIOÅäÖÃΪÍÆÍ츴ÓÃģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// ½«USART RxµÄGPIOÅäÖÃΪ¸¡¿ÕÊäÈëģʽ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
5个串口的中断和分组配置
//根据输入的USART执行对应的串口GPIO配置 为了给下面函数提供调用
void USART_GPIO_Config(USART_TypeDef* USARTx)
{
if(USARTx==USART1)
{
USART1_GPIO_Config();
}else if(USARTx==USART2)
{
USART2_GPIO_Config();
}else if(USARTx==USART3)
{
USART3_GPIO_Config();
}else if(USARTx==UART4)
{
USART4_GPIO_Config();
}else if(USARTx==UART5)
{
USART5_GPIO_Config();
}
}
//NVIC分组 为了给下面函数提供调用
void NVIC_Configuration(USART_TypeDef* USARTx,uint32_t NVIC_PriorityGroup,uint8_t PreemptionPriority,uint8_t SubPriority)
{
int DEBUG_USART_IRQ=0;
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup);
if(USARTx==USART1)
{
DEBUG_USART_IRQ=USART1_IRQn;
}else if(USARTx==USART2)
{
DEBUG_USART_IRQ=USART2_IRQn;
}else if(USARTx==USART3)
{
DEBUG_USART_IRQ=USART3_IRQn;
}else if(USARTx==UART4)
{
DEBUG_USART_IRQ=UART4_IRQn;
}else if(USARTx==UART5)
{
DEBUG_USART_IRQ=UART5_IRQn;
}
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = SubPriority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//这个函数基本就兼容了5个串口的所有配置了
void initUARTIQR(USART_TypeDef* USARTx,
uint32_t baudRate,
uint32_t NVIC_PriorityGroup,
uint8_t PreemptionPriority,
uint8_t SubPriority)
{
USART_InitTypeDef USART_InitStructure;
USART_Info usartInfo;
usartInfo.USARTx = USARTx;
usartInfo.baudRate = baudRate;
int index = 0;
while (index < MAX_NUM_USART && usartArray[index].USARTx != NULL) {
index++;
}
if (index < MAX_NUM_USART) {
usartArray[index] = usartInfo;
}
USART_GPIO_Config(USARTx);
if (USARTx == USART1) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
} else if (USARTx == USART2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
}
USART_InitStructure.USART_BaudRate = baudRate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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_Tx | USART_Mode_Rx;
USART_Init(USARTx, &USART_InitStructure);
NVIC_Configuration(USARTx,NVIC_PriorityGroup,PreemptionPriority,SubPriority);
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
USART_Cmd(USARTx, ENABLE);
}
兼容5个串口的printf 配置
void uartSendChar(USART_TypeDef* USARTx, char ch) {
if (USARTx == USART1) {
USART_SendData(USART1, ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
} else if (USARTx == USART2) {
USART_SendData(USART2, ch);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}else if (USARTx == USART3) {
USART_SendData(USART3, ch);
while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}else if (USARTx == UART4) {
USART_SendData(UART4, ch);
while (USART_GetFlagStatus(UART4, USART_FLAG_TXE) == RESET);
}else if (USARTx == UART5) {
USART_SendData(UART5, ch);
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
}
}
//以后所有打印函数都可以用这个调用
void Serial_Printf(USART_TypeDef* USARTx,char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg);
va_end(arg);
Usart_SendString(USARTx,String);
}
配置调用
//5个串口的配置 参数1 串口 ,参数2 波特率,参数3 分组几,参数4和参数5就是分组号了
initUARTIQR(USART1,115200,NVIC_PriorityGroup_1,1,1);
initUARTIQR(USART2,115200,NVIC_PriorityGroup_1,1,2);
initUARTIQR(USART3,115200,NVIC_PriorityGroup_1,1,3);
initUARTIQR(UART4,115200,NVIC_PriorityGroup_1,1,4);
initUARTIQR(UART5,115200,NVIC_PriorityGroup_1,1,5);
//5个函数的打印
Serial_Printf( USART1,"%d\n",1);
Serial_Printf( USART2,"%d\n",2);
Serial_Printf( USART3,"%d\n",3);
Serial_Printf( UART4,"%d\n",4);
Serial_Printf( UART5,"%d\n",5);
下面提一下为什么5个串口开启中断后,正确分组还是卡死
先来一个错误示范
//Interput5是一个标志位 进入中断后会置1
void UART5_IRQHandler(void)
{
uint8_t ucTemp;
if((USART_GetITStatus(UART5,USART_IT_RXNE)!=RESET)&&(Interput5==0))
{
char ch =(char) USART_ReceiveData(UART5);
//USART_SendData(UART5,ucTemp);
if (ch == '\n' || rxIndex >= RX_BUFFER_SIZE - 1) {
rxBuffer5[rxIndex] = '\0';
rxIndex = 0;
Interput5=1;
} else {
if (rxIndex < RX_BUFFER_SIZE - 1) {
rxBuffer5[rxIndex++] = ch;
}
}
}
}
是不是觉得没什么大问题还可以,????实际上单独测试这个个串口中断服务函数也确实没有问题,但是5个串口一起跑就出现了奇奇怪怪的问题???为什么呢?
看正确代码, (原因是串口进入中断后并没有执行清除标志位操作,这里是取读取DR寄存器的值来清除标志位的,如果把标志位清除放前面,判断是否进入中断放后边就行了)
void UART5_IRQHandler(void)
{
uint8_t ucTemp;
if((USART_GetITStatus(UART5,USART_IT_RXNE)!=RESET))
{
char ch =(char) USART_ReceiveData(UART5);
if(Interput5==0){
//USART_SendData(UART5,ucTemp);
if (ch == '\n' || rxIndex >= RX_BUFFER_SIZE - 1) {
rxBuffer5[rxIndex] = '\0';
rxIndex = 0;
Interput5=1;
} else {
if (rxIndex < RX_BUFFER_SIZE - 1) {
rxBuffer5[rxIndex++] = ch;
}
}
}}
}
综上所诉还是会卡死及时代码正确执行,这又是为什么?
(我总结的原因是因为串口抢占优先级频繁进入,导致卡死)
后边改成轮询的方式一次循环执行一个中断服务函数的数据
看代码
while(1){
if(Interput1){
IsUsrtx(rxBuffer1);
Interput1=0;//´®¿Ú±ê־λ¸´Î»
clearCharArray(rxBuffer1);//Çå¿Õ»º´æÇøÊý×é
}else if(Interput2) {
IsUsrtx(rxBuffer2);
Interput2=0;//´®¿Ú±ê־λ¸´Î»
clearCharArray(rxBuffer2);//Çå¿Õ»º´æÇøÊý×é
}else if(Interput3){
IsUsrtx(rxBuffer3);
Interput3=0;//´®¿Ú±ê־λ¸´Î»
clearCharArray(rxBuffer3);//Çå¿Õ»º´æÇøÊý×é
}else if(Interput4){
IsUsrtx(rxBuffer4);
Interput4=0;//´®¿Ú±ê־λ¸´Î»
clearCharArray(rxBuffer4);//Çå¿Õ»º´æÇøÊý×é
}else if(Interput5){
IsUsrtx(rxBuffer5);
Interput5=0;//´®¿Ú±ê־λ¸´Î»
clearCharArray(rxBuffer5);//Çå¿Õ»º´æÇøÊý×é
}
}
//这样就一次循环只处理一次中断接收内容,实际验证5个串按照10ms间隔不停发送,单片机完全能处理过来
好了下一个
如何在单片机中获取字符串长度,截取字符串,查找字符串,比较字符串,替换字符串呢?
我全部方法都放到了stringbuder.C里面 链接在置顶
文章来源:https://www.toymoban.com/news/detail-834328.html
调用实例:文章来源地址https://www.toymoban.com/news/detail-834328.html
//Strs是单片机收到的字符串
//截取字符串 从第0位开始截取2位
char* SbStr= SubString(Strs,0,2);
//释放内存 一定不能少
free(SbStr);
//判断是否等于字符串 U2
if (strcmp(SbStr, "U2") == 0)
{}
//判断是否查找到字符串AYUOK
if (String_IndexStr(Strs, "AYUOK") != -1)
{}
更多的自己去看把
到了这里,关于在STM32中使用5个串口收发数据的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!