HAL STM32使用环形缓冲区域 读取数据包

tjc_usart_hmi.c

#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include "tjc_usart_hmi.h"
#include <stddef.h>
#include "usart.h"
#include <string.h>
#include <stdlib.h>

typedef struct
{
    uint16_t Head;   										// 头指针 指向可读起始地址  每读一个,数字+1
    uint16_t Tail;											// 尾指针	指向可写的起始地址	 每写一个,数字+1,当尾指针超过数组大小,
																				// 则尾指针又指向数组首地址。
    uint16_t Lenght;										// 长度
    uint8_t  Ring_data[RINGBUFF_LEN];		// 数据缓冲区
}RingBuff_t;

RingBuff_t ringBuff;	//创建一个ringBuff的缓冲区
uint8_t RxBuff[1];    // 串口接收地址

#define STR_LENGTH 40        // 定义串口发送的缓冲大小

//字符串发送函数			HMISends("n0.val=2333");
void HMISends(char *fmt, ...)		  
{
	
	char buffer[STR_LENGTH];
	const char endFlag[13]="\xff\xff\xff";
	uint8_t len;
	va_list arg;           
	
	va_start(arg, fmt);     
	vsnprintf((char *)buffer,STR_LENGTH,fmt,arg);
	va_end(arg);		
	
	strcat(buffer,endFlag);
	
	len=strlen(&buffer);
	
  HAL_UART_Transmit(&huart1,(uint8_t *)&buffer,len,0xffff);   			
}

/********************************************************
函数名:  	HAL_UART_RxCpltCallback
功能:    	串口接收中断,将接收到的数据写入环形缓冲区
**********************************************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)   
    {
        HAL_UART_Receive_IT(&huart1,&RxBuff[0],1);
				writeRingBuff(RxBuff[0]);
    }
}

/********************************************************
函数名:  	initRingBuff
功能:    	初始化环形缓冲区
输入参数:
返回值: 		void
修改记录:
**********************************************************/
void initRingBuff(void)
{
  //初始化相关信息
  ringBuff.Head = 0;
  ringBuff.Tail = 0;
  ringBuff.Lenght = 0;
}

/********************************************************
函数名:  	writeRingBuff
功能:    	往环形缓冲区写入数据  每次写入一个数据
**********************************************************/
void writeRingBuff(uint8_t data)
{
  if(ringBuff.Lenght >= RINGBUFF_LEN) 								//判断缓冲区是否已满
  {
    return ;
  }
  ringBuff.Ring_data[ringBuff.Tail]=data;							//写入到尾数据
  ringBuff.Tail = (ringBuff.Tail+1)%RINGBUFF_LEN;			//防止越界非法访问 Tail=RINGBUFF_LEN 就为0
																											//如果Tail指针已经到达缓冲区的末尾,那么Tail+1就会变成0   
  ringBuff.Lenght++;}																	// 数据长度+1

/********************************************************
函数名:  	deleteRingBuff
功能:    	删除串口缓冲区中相应长度的数据  从头删除指定长度
输入参数:	要删除的长度
**********************************************************/
void deleteRingBuff(uint16_t size)
{
	if(size >= ringBuff.Lenght)        // 确保小于以有数据
	{
	    initRingBuff();
	    return;
	}
	for(int i = 0; i < size; i++)
	{
		if(ringBuff.Lenght == 0)//判断非空
		{
		initRingBuff();
		return;
		}
		ringBuff.Head = (ringBuff.Head+1)%RINGBUFF_LEN;//防止越界非法访问
		ringBuff.Lenght--;
	}
}



/********************************************************
函数名:  	read1BFromRingBuff
功能:    	从串口缓冲区读取1字节数据
输入参数:		position:读取的位置
返回值: 		所在位置的数据(1字节)  
**********************************************************/
uint8_t read1BFromRingBuff(uint16_t position)
{
	uint16_t realPosition = (ringBuff.Head + position) % RINGBUFF_LEN;
	return ringBuff.Ring_data[realPosition];
}




/********************************************************
函数名:  	getRingBuffLenght
功能:    	获取串口缓冲区的数据数量
返回值: 		串口缓冲区的数据数量
**********************************************************/
uint16_t getRingBuffLenght()
{
	return ringBuff.Lenght;
}


/********************************************************
函数名:  	isRingBuffOverflow
功能:    	判断环形缓冲区是否已满
返回值: 		1:环形缓冲区已满 , 2:环形缓冲区未满
**********************************************************/
uint8_t isRingBuffOverflow()
{
	return ringBuff.Lenght == RINGBUFF_LEN;
}

void tjcUsartHmi_Init(){
	HAL_UART_Receive_IT(&huart1,&RxBuff[0],1);			// 打开串口中断
	initRingBuff();																	// 初始化串口缓冲区
}	



//串口数据帧长度:6字节
//帧头      led编号  LED状态    帧尾
//0x55      1字节    1字节     0xffffff
//例子1:上位机代码  printh 55 01 00 ff ff ff  含义:1号led关闭
//例子2:上位机代码  printh 55 04 01 ff ff ff  含义:4号led打开
//例子3:上位机代码  printh 55 00 01 ff ff ff  含义:0号led打开
//例子4:上位机代码  printh 55 04 00 ff ff ff  含义:4号led关闭

#define FRAMELENGTH 6  // 数据包的长度

// 数据包解析函数
void UsartDataAnalysis()
{
	  while(usize >= FRAMELENGTH)    // 如果以及接收的数据长于数据包的长度
	  {
		  //校验帧头帧尾是否匹配
		  if(u(0) != 0x55 || u(3) != 0xff || u(4) != 0xff || u(5) != 0xff)
		  {
			  //不匹配删除1字节
			  udelete(1);
		  }else
		  {
			  //匹配,跳出循环
			  break;
		  }
	  }

	  //进行解析
	  if(usize >= FRAMELENGTH && u(0) == 0x55 && u(3) == 0xff && u(4) == 0xff && u(5) == 0xff)
	  {
       // 读取对应字节  //
		  udelete(FRAMELENGTH);							// 删除对应数据包的
	  }
}

tjc_usart_hmi.h

#ifndef __TJCUSARTHMI_H_
#define __TJCUSARTHMI_H_

#include "main.h" 

#define RINGBUFF_LEN	(500)     //定义最大接收字节数 500

extern uint8_t RxBuff[1];

#define usize getRingBuffLenght()
#define code_c() initRingBuff()
#define udelete(x) deleteRingBuff(x)
#define u(x) read1BFromRingBuff(x)


void tjcUsartHmi_Init();
void HMISends(char *fmt, ...);
void initRingBuff(void);
void writeRingBuff(uint8_t data);
void deleteRingBuff(uint16_t size);
uint16_t getRingBuffLenght(void);
uint8_t read1BFromRingBuff(uint16_t position);


#endif

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于使用 STM32F103 板上的串口进行收发任意长度数据包,你可以采用以下步骤: 1. 初始化串口:根据你的需求选择一个串口(如 USART1)并初始化它。确保你已经正确配置了串口的波特率、数据位、停止位和校验位等参数。 2. 接收数据:使用中断或轮询的方式从串口接收数据。如果使用中断,你可以在接收中断处理函数中读取接收寄存器(如 USART_DR)获取接收到的数据。如果使用轮询方式,你可以通过查询状态标志(如 USART_SR)检查接收寄存器是否有数据,并使用 USART_DR 读取数据。 3. 处理数据:你可以将接收到的数据存储在缓冲区中,可以是一个数组或环形缓冲区。如果你的数据包有固定长度,你可以在接收到足够长度的数据后进行处理。如果没有固定长度,你可以定义一个特定的结束符作为数据包的结束标志,例如换行符 '\n'。 4. 发送数据:当你需要发送数据时,你可以将数据存储在发送缓冲区中,然后使用中断或轮询方式发送数据。如果使用中断方式,你可以在发送中断处理函数中将缓冲区的数据逐个发送出去。如果使用轮询方式,你可以查询状态标志(如 USART_SR)检查发送寄存器是否为空,并使用 USART_DR 发送数据。 5. 注意事项:在处理数据和发送数据时,要确保缓冲区的大小足够大,以防止数据溢出。此外,还要注意处理接收到的异常情况,如数据溢出、帧错误、奇偶校验错误等。 需要注意的是,以上步骤只是一个简单的示例,你可以根据具体需求进行相应的修改和扩展。同时,你还可以参考 STM32F103 的官方文档和相关的示例代码来更详细地了解和实现串口收发功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值