STM32F103实现循环队列串口通信和内部串口间通信

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发送出去
			}
		}
	}
}

你可能感兴趣的:(STM32,stm32,单片机,arm)