STM32串口处理单个数据简单,处理字符串就有点费脑筋,今天在此做下记录
学习了 添加链接描述和B站
的教程,才知道可以用循环队列来处理,万分感谢2位大大
串口2连接有人4G通信模块,自带MQTT协议,可以同时收发4组主题消息,使用中断接收,代码:
//串口中断
int jie_shou_len = 0;
char shu_ju[128]={0};
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
{
USART_ClearITPendingBit(USART2, USART_IT_RXNE);//清空接收标志
shu_ju[jie_shou_len]= USART_ReceiveData(USART2);//(USART2->DR); //读取接收到的数据
jie_shou_len++;
if (jie_shou_len >= CHANG_DU)
{
jie_shou_len = 0;
}
if (jie_shou_len > 0)
{
if ((shu_ju[jie_shou_len-1]=='\r')||(shu_ju[jie_shou_len-1] == '\n'))
{
jie_shou_len--;
shu_ju[jie_shou_len] = 0;//字符串以0结尾
if ((jie_shou_len>0) && (jie_shou_len<CHANG_DU))
{
cun_shu_ju(shu_ju);//将数组[0]指针传入
jie_shou_len = 0;//重新开始接收新数据
}
}
}
}
}
列队处理:
//.h
#define CHANG_DU 128 //接收缓冲区长度
#define DUI_LIE 4 //最大保存消息数
extern int get_shu_ju(char* shu_zu); //获取缓冲区消息
extern int cun_shu_ju(char* shu_zu); //保存消息到缓冲区
uint8_t Head = 0; //头指针置于起始位
uint8_t Tail = 0; //尾指针置于起始位
//.h
static char data_u3[DUI_LIE][CHANG_DU] = { 0 };
int get_shu_ju(char* shu_zu)
{
if (Head == Tail)
{
return -1;
}
strcpy(shu_zu, data_u3[Head]);
Head = (Head + 1) % DUI_LIE;
return 0;
}
int cun_shu_ju(char* shu_zu)
{
if ((Tail+1) % DUI_LIE == Head)
{
return -1;
}
if (strlen(shu_zu) >= CHANG_DU)
{
strncpy(data_u3[Tail], shu_zu, CHANG_DU - 1);
data_u3[Tail][CHANG_DU - 1] = 0;
}
else
{
strcpy(data_u3[Tail], shu_zu);
}
Tail = (Tail + 1) % DUI_LIE;
return 0;
}
//main文件查询
char u2_data[CHANG_DU];
while(1)
{
/*判断缓冲区有无消息*/
/*有消息就提取消息到u2_data并进行处理*/
if (get_shu_ju(u2_data) == 0)//如果缓冲区有消息,就进入处理
{
printf("asdad + = %s\r\n", u2_data);
}
}
此外,还找到了一种STM32内部不同波特率串口之间通信的办法,实际上也是用的消息列队,不过忘记了出处,原作者请谅解
//fifo.h
#ifndef _FIFO_H_
#define _FIFO_H_
#include "stm32f10x.h"
#define FIFO_SIZE 256
typedef struct
{
uint8_t Buf[FIFO_SIZE]; //定义缓冲区,大小用FIFO_SIZE定义
volatile uint32_t Read; //定义读取指针
volatile uint32_t Write; //定义写入指针
}FIFOTypeDef;
extern FIFOTypeDef USART1_fifo;
extern FIFOTypeDef USART2_fifo;
void PutChar(uint8_t c);
uint8_t GetChar(uint8_t* c);
void PutChar1(uint8_t c);
uint8_t GetChar1(uint8_t* c);
#endif
//fifo.c
#include "fifo.h"
FIFOTypeDef USART1_fifo; //定义串口1的队列fifo
FIFOTypeDef USART2_fifo; //定义串口2的队列fifo
void PutChar(uint8_t c)
{
USART1_fifo.Buf[USART1_fifo.Write] = c; //写入数据到缓冲区
if (++USART1_fifo.Write >= FIFO_SIZE) //写入指针超出缓冲区最大值,返回最初位置
{
USART1_fifo.Write = 0;
}
}
uint8_t GetChar(uint8_t* c)
{
if (USART1_fifo.Read == USART1_fifo.Write) //如果没有存入数据,则返回0
{
return 0;
}
else
{
*c = USART1_fifo.Buf[USART1_fifo.Read]; //读取数据,传入到指针c
if (++USART1_fifo.Read >= FIFO_SIZE) //读取指针超出缓冲区最大值,返回最初位置
{
USART1_fifo.Read = 0;
}
return 1; //成功读取数据返回1
}
}
void PutChar1(uint8_t c)
{
USART2_fifo.Buf[USART2_fifo.Write] = c;
if (++USART2_fifo.Write >= FIFO_SIZE)
{
USART2_fifo.Write = 0;
}
}
uint8_t GetChar1(uint8_t* c)
{
if (USART2_fifo.Read == USART2_fifo.Write)
{
return 0;
}
else
{
*c = USART2_fifo.Buf[USART2_fifo.Read];
if (++USART2_fifo.Read >= FIFO_SIZE)
{
USART2_fifo.Read = 0;
}
return 1;
}
}
//配置
#include "stm32f10x.h"
#include "fifo.h"
/*******************************************************************************
* Function Name : UIF_Init
* Description : 初始化串口
* Input : USARTx = USART1,2,3
* : BPS = 1200, 4800,,,
* : STB = 1,5,2,15
* Return : None
*******************************************************************************/
void UIF_Init(USART_TypeDef* USARTx, uint32_t BPS, uint32_t STB)
{
uint32_t Dly;
USART_InitTypeDef USART_InitStruct; //定义串口结构体
NVIC_InitTypeDef NVIC_InitStructure; //定义中断结构体
USART_ClearFlag(USARTx, USART_FLAG_TC);
USART_DeInit(USARTx); //复位串口x
USART_InitStruct.USART_BaudRate = BPS;
USART_InitStruct.USART_WordLength = USART_WordLength_8b; //8位字节长度数据
if (STB == 1)
USART_InitStruct.USART_StopBits = USART_StopBits_1;
else if (STB == 5)
USART_InitStruct.USART_StopBits = USART_StopBits_0_5;
else if (STB == 15)
USART_InitStruct.USART_StopBits = USART_StopBits_1_5;
else
USART_InitStruct.USART_StopBits = USART_StopBits_2;
USART_InitStruct.USART_Parity = USART_Parity_No; //无奇偶检验位
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //接收 发送模式
USART_Init(USARTx, &USART_InitStruct); //初始化串口x
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //使能串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级2级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级2级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
if (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == SET)
{
USART_ClearFlag(USARTx, USART_FLAG_TC)
}
USART_Cmd(USARTx, ENABLE); //使能串口x
for (Dly = 0; Dly < 0xFFFF; Dly++);
USART_ClearFlag(USARTx, USART_FLAG_TC);
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); //开启接收中断
}
/*******************************************************************************
* Function Name : GPIO_Config
* Description : 初始化IO
* Input : None
* Return : None
*******************************************************************************/
void GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
| RCC_APB2Periph_GPIOB
| RCC_APB2Periph_AFIO
| RCC_APB2Periph_USART1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //USART1_TX Output
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; //USART1_RX Input
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2; //USART2_TX Output
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; //USART2_RX Input
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/*******************************************************************************
* Function Name : NVIC_Configuration
* Description : 设置NVIC中断分组
* Input : None
* Return : None
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
}
/*******************************************************************************
* Function Name : USART_SendByte
* Description : 发送一个字节
* Input : USARTx = USART1,2,3
Data = 要发送的数据
* Return : None
*******************************************************************************/
void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data)
{
USARTx->DR = (Data & (uint16_t)0x01FF);;
while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) != SET);
}
/*******************************************************************************
* Function Name : USART1_IRQHandler
* Description : 串口1中断服务程序
* Input : None
* Return : None
*******************************************************************************/
void USART1_IRQHandler(void)
{
u8 res;
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //如果接收到数据
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清空接收标志
res = USART_ReceiveData(USART1);
PutChar(res); //压入数据到串口1缓冲区
}
//溢出,如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题
if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) == SET)
{
USART_ClearFlag(USART1, USART_FLAG_ORE); //读SR其实就是清除标志
USART_ReceiveData(USART1); //读DR
}
}
/*******************************************************************************
* Function Name : USART2_IRQHandler
* Description : 串口2中断服务程序
* Input : None
* Return : None
*******************************************************************************/
void USART2_IRQHandler(void)
{
u8 Res;
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
{
USART_ClearITPendingBit(USART2, USART_IT_RXNE);//清空接收标志
Res = USART_ReceiveData(USART2);//(USART2->DR); //读取接收到的数据
PutChar1(Res); //压入数据到串口2缓冲区
}
//溢出,如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题
if (USART_GetFlagStatus(USART2, USART_FLAG_ORE) == SET)
{
USART_ClearFlag(USART2, USART_FLAG_ORE); //读SR其实就是清除标志
USART_ReceiveData(USART2); //读DR
}
}
//main
/*******************************************************************************
* Function Name : main
* Description : 主函数
* Input : None
* Return : None
*******************************************************************************/
int main(void)
{
uint8_t byte;
GPIO_Config();
NVIC_Configuration();
UIF_Init(USART1, 115200, 1); //串口1波特率115200,1位停止位
UIF_Init(USART2, 9600, 1); //串口2波特主9600,1位停止位 //使能串口
while (1)
{
if (USART1_fifo.Write != USART1_fifo.Read) //如果读取指针不等于写入指针,说明缓冲区有数据
{
if (GetChar(&byte)) //如果读取数据成功,返回1
{
USART_SendByte(USART2, byte); //把串口1的缓冲区数据通过串口2发送出去
}
}
if (USART2_fifo.Read != USART2_fifo.Write) //如果读取指针不等于写入指针,说明缓冲区有数据
{
if (GetChar1(&byte)) //如果读取数据成功,返回1
{
USART_SendByte(USART1, byte); //把串口2的缓冲区数据通过串口1发送出去
}
}
}
}