2.12 FreeRTOS_RingBuff 环形缓存数组的使用

前面我博客写了一篇《STM32 串口传输最佳处理方式 FreeRTOS+队列+DMA+IDLE(一)》就是利用RingBuff环形缓存数组来存数据,大家可以看着那边代码来看。
详细描述一下里面的原理:看一下入队函数

static uint16_t ps_tbwr_Blue=0;//缓存所在指针

//入队的结构体
typedef struct 
{
    uint16_t start_addr;  //入队开始位置
    uint16_t len;    // 入队长度    
}BufferLoopData_Typedef

   void USART1_SendData(uint8_t *ps,uint16_t len)
{
    uint16_t i;		
    BufferLoopData_Typedef buffer_loop;
    buffer_loop.start_addr = ps_tbwr_Blue;
    buffer_loop.len = len;

    for (i=0;i<len;i++)
    {
        if (ps_tbwr_Blue >= MAX_FRAME_COMM_BUFFER_SIZE)
        {
            ps_tbwr_Blue = 0;
        }        
        txbuf_Blue_DMA[ps_tbwr_Blue] = *(ps+i);//txbuf_Blue_DMA为
        ps_tbwr_Blue++;        
    }
    xQueueSendToBack(xQueue_Blue_tx,(void *)&buffer_loop,portMAX_DELAY);   
}

大家注意了,buffer_loop.start_addr 是循环数组入队地址,buffer_loop.start_addr是在ps_tbwr_Blue累加之前的被赋值。所以,它每次入队都是上一次缓存完的位置。即出队时,数据取出的位置。ps_tbwr_Blue是一个静态变量,会一直递增过去。

出队函数如下:

void USART1_SendTask(void const * argument)
{
    uint16_t i;
    BufferLoopData_Typedef buffer_loop;
    extern uint8_t txbuf_Blue_tmp[MAX_FRAME_COMM_LEN];   
      for (;;)
    {
        xQueueReceive(xQueue_Blue_tx,&buffer_loop,portMAX_DELAY);  
		//SCB_CleanDCache();
        for (i=0;i<buffer_loop.len;i++)
        {
            if (buffer_loop.start_addr >= MAX_FRAME_COMM_BUFFER_SIZE)
            {
                buffer_loop.start_addr = buffer_loop.start_addr - MAX_FRAME_COMM_BUFFER_SIZE;
            }
            txbuf_Blue_tmp[i] = txbuf_Blue_DMA[buffer_loop.start_addr];
            
            buffer_loop.start_addr += 1;
            
        }   
        //SCB_CleanInvalidateDCache();
        Uart1_DMASend_Start(&txbuf_Blue_tmp[0],buffer_loop.len);//通过DMA发送
        xSemaphoreTake(BinarySem_UART1_tx_finish_Handle,portMAX_DELAY); //等待DMA发送成功
        taskYIELD();  
    } 
}

工作如下:

在这里插入图片描述
第一次入队时,addr1,lenth1。
此时addr=0;ps=lenth1
第二次入队时addr2,lenth2。
此时addr2=ps=lenth1; ps=lenth1+lenth2
第三次入队时addr3,lenth3。
此时addr3=ps=lenth1+len2; ps=lenth1+lenth2+lenth2.
……
所以说,就想上面说的。addr是在ps累加之前被赋值了。它就是这样一个循环的过程。
上面是环形缓存数组的一种方法,有一点点拗口,但是非常的简介,实用。
出来上面方法还有一种利用链表的方法。具体如下

方法二:环形数组封装
缺点:
进栈 ->满了后不能在入栈;
出栈->缺乏必要保护,无数据也可以出栈;导致必须与信号量与队列一起使用
利用链表`

//第一步,创建环形队列
rbCreate(&uart_rb_rx,ringBuff,MAX_SIZE);

//第二步,向环形队列写入数据
rbWrite(&uart_rb_rx, &rbmsg.buf, (size_tt) frameLen);   /*数据入环*/

//第三步骤:从环形队列读出数据
rbRead((rb_t*)&uart_rb_rx,&rbmsgBuff.buf,frameLen);      /*数据出环*/

环形链表源码如下:
loopList.c

#define LOOPLIST_C_
#include "loopList.h"
#include <stdio.h>
#include <string.h>
rb_t uart_rb_rx; //< 环形缓冲区结构体变量


void rbCreate(rb_t* rb,uint8_t *Buff,uint32_t BuffLen)//创建或者说初始化环形缓冲区
{
    if(NULL == rb)
    {
			#ifdef PRINT_RB
        printf("ERROR: input rb is NULL\n");
			#endif
        return;
    }
    rb->rbCapacity = BuffLen;
		rb->rbBuff = Buff;
    rb->rbHead = rb->rbBuff;//头指向数组首地址
    rb->rbTail = rb->rbBuff;//尾指向数组首地址
}

void rbDelete(rb_t* rb)//删除一个环形缓冲区
{
    if(NULL == rb)
    {
			#ifdef PRINT_RB
        printf("ERROR: input rb is NULL\n");
			#endif			
        return;
    }

    rb->rbBuff = NULL;//地址赋值为空
    rb->rbHead = NULL;//头地址为空
    rb->rbTail = NULL;//尾地址尾空
    rb->rbCapacity = 0;//长度为空
}

int32_t rbCapacity(rb_t *rb)//获取链表的长度
{
    if(NULL == rb)
    {
			#ifdef PRINT_RB
        printf("ERROR: input rb is NULL\n");
			#endif
        return -1;
    }

    return rb->rbCapacity;
}

int32_t rbCanRead(rb_t *rb)//返回能读的空间
{
    if(NULL == rb)
    {
			#ifdef PRINT_RB
        printf("ERROR: input rb is NULL\n");
			#endif
        return -1;
    }

    if (rb->rbHead == rb->rbTail)//头与尾相遇
    {
        return 0;
    }

    if (rb->rbHead < rb->rbTail)//尾大于头
    {
        return rb->rbTail - rb->rbHead;
    }

    return rbCapacity(rb) - (rb->rbHead - rb->rbTail);//头大于尾
}

int32_t rbCanWrite(rb_t *rb)//返回能写入的空间
{
	if(NULL == rb)
	{
		#ifdef PRINT_RB
			printf("ERROR: input rb is NULL\n");
		#endif
		return -1;
	}

	return rbCapacity(rb) - rbCanRead(rb);//总的减去已经写入的空间
}

/*   
  rb--要读的环形链表
  data--读出的数据
  count--读的个数
	缺点:没有数据时依旧能出栈,缺乏保护
*/
int32_t rbRead(rb_t *rb, void *data, size_tt count)
{
	int copySz = 0;

	if(NULL == rb)
	{
		#ifdef PRINT_RB
			printf("ERROR: input rb is NULL\n");
		#endif
			return -1;
	}

	if(NULL == data)
	{
		#ifdef PRINT_RB
			printf("ERROR: input data is NULL\n");
		#endif					
			return -1;
	}

	if (rb->rbHead < rb->rbTail)//尾大于头
	{
			copySz = min(count, rbCanRead(rb));//查看能读的个数
			memcpy(data, rb->rbHead, copySz);//读出数据到data
			rb->rbHead += copySz;//头指针加上读取的个数
			return copySz;//返回读取的个数
	}
	else //头大于等于了尾
	{
			if (count < rbCapacity(rb)-(rb->rbHead - rb->rbBuff))//读的个数小于头上面的数据量
			{
					copySz = count;//读出的个数
					memcpy(data, rb->rbHead, copySz);//
					rb->rbHead += copySz;
					return copySz;
			}
			else//读的个数大于头上面的数据量
			{
					copySz = rbCapacity(rb) - (rb->rbHead - rb->rbBuff);//先读出来头上面的数据
					memcpy(data, rb->rbHead, copySz);
					rb->rbHead = rb->rbBuff;//头指针指向数组的首地址
																									 //还要读的个数
					copySz += rbRead(rb, (char*)data+copySz, count-copySz);//接着读剩余要读的个数
					return copySz;
			}
	}
}

//缺点:数据如果没有取走,不能再往里写数据
int32_t rbWrite(rb_t *rb, const void *data, size_tt count)
{
    int tailAvailSz = 0;

    if(NULL == rb)
    {     		
			#ifdef PRINT_RB
				printf("ERROR: rb is empty \n");
			#endif				
        return -1;
    }

    if(NULL == data)
    {       
			#ifdef PRINT_RB
				printf("ERROR: data is empty \n");
			#endif			
        return -1;
    }

    if (count > rbCanWrite(rb))//如果剩余的空间不够
    {     
			#ifdef PRINT_RB
				printf("ERROR: no memory \n");
			#endif			
        return -1;
    }

    if (rb->rbHead <= rb->rbTail)//头小于等于尾
    {
        tailAvailSz = rbCapacity(rb) - (rb->rbTail - rb->rbBuff);//查看尾上面剩余的空间
        if (count <= tailAvailSz)//个数小于等于尾上面剩余的空间
        {
            memcpy(rb->rbTail, data, count);//拷贝数据到环形数组
            rb->rbTail += count;//尾指针加上数据个数
            if (rb->rbTail == rb->rbBuff+rbCapacity(rb))//正好写到最后
            {
                rb->rbTail = rb->rbBuff;//尾指向数组的首地址
            }
            return count;//返回写入的数据个数
        }
        else
        {
            memcpy(rb->rbTail, data, tailAvailSz);//填入尾上面剩余的空间
            rb->rbTail = rb->rbBuff;//尾指针指向数组首地址
                   //剩余空间                   剩余数据的首地址       剩余数据的个数
            return tailAvailSz + rbWrite(rb, (char*)data+tailAvailSz, count-tailAvailSz);//接着写剩余的数据
        }
    }
    else //头大于尾
    {
      memcpy(rb->rbTail, data, count);
      rb->rbTail += count;
      return count;
    }
}
/**@} */

/**
* @brief 向环形缓冲区写入数据
* @param [in] buf        : buf地址
* @param [in] len        : 字节长度
* @return   正确 : 返回写入的数据长度
            失败 : -1
*/
int32_t PutData(rb_t *rb ,USART_TypeDef* USARTx, uint8_t *buf, uint32_t len)
{
	int32_t count = 0;

	if(NULL == buf)
	{
			#ifdef PRINT_RB
				printf("ERROR: gizPutData buf is empty \n");
			#endif		
			return -1;
	}

	count = rbWrite(rb, buf, len);
	if(count != len)
	{
			#ifdef PRINT_RB
				printf("ERROR: Failed to rbWrite \n");
			#endif				
			return -1;
	}
	//USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);
	return count;
}

loopList.h

#ifndef _LOOPLIST_H_
#define _LOOPLIST_H_

#ifndef LOOPLIST_C_//如果没有定义  AnnularArray_C_
#define LOOPLIST_C_ extern
#else
#define LOOPLIST_C_
#endif

#include <stm32f4xx_hal.h>
#define size_tt uint16_t 
#define min(a, b) (a)<(b)?(a):(b)                   ///< 获取最小值


/** 环形缓冲区数据结构 */
typedef struct {
    size_tt rbCapacity;//空间大小
    uint8_t  *rbHead; //头
    uint8_t  *rbTail; //尾
    uint8_t  *rbBuff; //数组的首地址
}rb_t;

/****************************************************************/
/*                  数据结构定义                                */
/****************************************************************/



LOOPLIST_C_  rb_t uart_rb_rx;  //< 环形缓冲区结构体变量> rx
LOOPLIST_C_  void rbCreate(rb_t *rb,uint8_t *Buff,uint32_t BuffLen);//创建或者说初始化环形缓冲区
LOOPLIST_C_  void rbDelete(rb_t* rb);
LOOPLIST_C_  int32_t rbCapacity(rb_t *rb);//得到环形大小
LOOPLIST_C_  int32_t rbCanRead(rb_t *rb);//能读出数据的个数
LOOPLIST_C_  int32_t rbCanWrite(rb_t *rb);//还剩余的空间
LOOPLIST_C_  int32_t rbRead(rb_t *rb, void *data, size_tt count);//读取数据
LOOPLIST_C_  int32_t rbWrite(rb_t *rb, const void *data, size_tt count);
LOOPLIST_C_  int32_t PutData(rb_t *rb, USART_TypeDef* USARTx, uint8_t *buf, uint32_t len);


#endif

配合FreeRTOS队列操作,只需将长度入队,出队即可。 上面方法模块性强,更为复杂,但逻辑上更为简单,可作为模块化调用。
结合RTX:
写入环形数组:bsp_uart.c

#include "bsp_uart.h"
#include "loopList.h"
#include "app_main.h"

uint8_t ringBuff[MAX_SIZE];
pack_t rbmsg;
pack_t rbmsgBuff;

uint8_t Index_=0;
void getBlockstate1(void)
{
	int32_t rbState;
	loopData_Typedef buffer_loop;
	//优先级最高 直接覆盖
	char n=0;
	rbmsg.frame.start = 0x7c7b;  //小端模式发送的时候自动翻转为7b 7c
	rbmsg.frame.len = 2+1;
	rbmsg.frame.cmd = 'a';
	rbmsg.frame.data[n] = Index_++; n++;
	rbmsg.frame.data[n] = 0x0; n++;
	rbmsg.frame.data[n] = 0x7c; n++;
	rbmsg.frame.data[n] = 0x7d; n++;
	
	buffer_loop.addr = uart_rb_rx.rbTail;
	/*
	buffer_loop.len = 9;
	rbState=rbWrite(&uart_rb_rx, &rbmsg.buf, (size_tt) buffer_loop.len);   //数据入环
	*/
	//或者
	buffer_loop.len = frameLen;
	rbState=rbWrite(&uart_rb_rx, &rbmsg.buf, (size_tt) frameLen);   /*数据入环*/
	if(rbState!=-1)
	{
			//osSemaphoreRelease(sid_Semaphore_serialSend);
		osMessageQueuePut(mid_MsgQueue_usart1_rx,(void *)&buffer_loop,0,0);
	}
}


bsp_uart.h

#ifndef _BSP_UART_H
#define _BSP_UART_H
#include "loopList.h"

#define frameLen  100  //一帧的数据长度
#define frameItem	6		 //缓存多少帧
#define MAX_SIZE	(frameItem*frameLen)

/* 环形缓冲区数据传递信息  消息指针数组 */
typedef struct 
{
	uint8_t *addr;    /*开始地址*/
	uint16_t len;     /*数据长度*/
}loopData_Typedef;

typedef   union DATA_T
{
	
	__packed  struct frame
	{
		unsigned short start;
		unsigned short len;
		unsigned char cmd;
		unsigned char data[frameLen-5];
	}frame;
	unsigned char buf[frameLen];	
}pack_t, *p_pack_t;


extern uint8_t ringBuff[MAX_SIZE];
extern pack_t rbmsgBuff;
void getBlockstate1(void);
#endif


读取出环形数组:

#include "tx_thread.h"
#include "eventRecord.h"
#include "bsp_uart.h"

//串口数据发送线程
uint8_t popFifoEn = 0;
void tx_task(void * arg)
{
	int32_t rbStatus;
	loopData_Typedef buffer_loop;
	osStatus_t osStatus;
	P_DATA_T p;
	while(1)
	{
		osStatus=osMessageQueueGet(mid_MsgQueue_usart1_rx, (void *)&buffer_loop, NULL, 0U); // 0:the function returns instantly   osWaitForever: wait for message forever
//		osStatus = osSemaphoreAcquire(sid_Semaphore_serialSend,100);
		if(osStatus==osOK)
		{
			//rbStatus = rbRead((rb_t*)&uart_rb_rx,&rbmsgBuff.buf,buffer_loop.len);      /*数据出环*/
			//或者
			rbStatus = rbRead((rb_t*)&uart_rb_rx,&rbmsgBuff.buf,frameLen);      /*数据出环*/			
			if(rbStatus !=-1)
			{
				/*do something...*/				
				virtual_debug(usart_tx,rbmsgBuff.buf,rbmsgBuff.frame.len+6);//发送数据
			}
		}	
		osDelay(200);
	}
}

	mid_MsgQueue_usart1_rx = osMessageQueueNew(frameItem,sizeof(loopData_Typedef), NULL); 
	if (mid_MsgQueue_usart1_rx == NULL) {
		return -1;
	}
	rbCreate(&uart_rb_rx,ringBuff,MAX_SIZE);	

**方法三:环形数组封装 **
优点:更类似于消息队列,就算栈满了没有取走数据,依旧可以入堆,入栈把最开始的替换掉;
源码:
fifo.c


#include "fifo.h"
/*循环利用二维数组
push:放入数组,写地址加 NodeMax
pop:输出出来,读地址加 NodeMax
*/

P_FIFO_T FIFO_Creat(void *fifo_array, P_FIFO_T pstFifo,int nNodeMax,int nNodeSize)
{
	pstFifo->nNodeMax		= nNodeMax-1; //最后一个节点做缓存
	pstFifo->nNodeSize		= nNodeSize;
	pstFifo->nNodeCount		= 0;
	pstFifo->pvDataBuff		= (char *)fifo_array;
	pstFifo->pcNodeBuff		= (char *)pstFifo->pvDataBuff + pstFifo->nNodeSize * pstFifo->nNodeMax;
	pstFifo->pvRead			= pstFifo->pvDataBuff;
	pstFifo->pvWrite		= pstFifo->pvDataBuff;
	pstFifo->nReadTimes		= 0;
	pstFifo->nWriteTimes	= 0;
	return pstFifo;
}


void FIFO_Push(P_FIFO_T hFifo, void *pvBuff)
{
	P_FIFO_T pstFifo = hFifo;
	char *pcNewBuff = (char *)pvBuff;        
	char *pcBuffEnd = (char *)pstFifo->pvDataBuff + pstFifo->nNodeSize * pstFifo->nNodeMax;

	if (pstFifo->pvWrite == pcBuffEnd)//写入位置为最后一个节点位置
	{
		pstFifo->pvWrite = pstFifo->pvDataBuff;//切换到首个节点位置
		pstFifo->nWriteTimes++;

		if ((pstFifo->pvWrite == pstFifo->pvRead) &&
			(pstFifo->nWriteTimes > pstFifo->nReadTimes))//进栈已经比出栈多了一个轮回,此时重合,读数据丢弃最后一组数据
		{
			if (pstFifo->pvRead == pcBuffEnd)//重合在最后一个位置
			{
				pstFifo->pvRead =  pstFifo->pvDataBuff;
			}
			else
				pstFifo->pvRead = (char *)pstFifo->pvRead + pstFifo->nNodeSize;//重合在其他位置
		}
	}
	myMemcpy(pstFifo->pvWrite, pcNewBuff, pstFifo->nNodeSize);//数据进栈
	pstFifo->pvWrite = (char *)pstFifo->pvWrite + pstFifo->nNodeSize;//切换下一个组地址
	pstFifo->nNodeCount++;
}


char * FIFO_Pop(P_FIFO_T hFifo)
{
	P_FIFO_T pstFifo = hFifo;
	char *pcBuffEnd;

	if (hFifo->pvRead == hFifo->pvWrite && hFifo->nReadTimes == hFifo->nWriteTimes)//没有数据入栈	(判断次数相等有点问题,可能导致数据进行多轮的出栈)
	{
		return NULL;
	}

	
	pcBuffEnd = (char *)pstFifo->pvDataBuff  + pstFifo->nNodeSize * pstFifo->nNodeMax;

	if ( pstFifo->pvRead == pcBuffEnd)//出栈地址处于末端,切换到首个入栈地址
	{
		 pstFifo->pvRead = pstFifo->pvDataBuff;
		 pstFifo->nReadTimes++;
	}
	myMemcpy(pstFifo->pcNodeBuff, pstFifo->pvRead, pstFifo->nNodeSize);//数据出栈贝到pcNodeBuff
	pstFifo->pvRead =  (char *)pstFifo->pvRead + pstFifo->nNodeSize;//切换下一个出栈地址
	pstFifo->nNodeCount--;
	return (char*)pstFifo->pcNodeBuff;

}



void* myMemcpy(void *dst, const void *src, int size) 
{
    char *psrc, *pdst;
	if (dst == NULL || src == NULL)
		return NULL;
	if (dst <= src) {
		psrc = (char *)src;
		pdst = (char *)dst;
		while (size--)
			*pdst++ = *psrc++;
	}
	else {
		psrc = (char *)src + size - 1;
		pdst = (char *)dst + size - 1;
		while (size--) 
			*pdst-- = *psrc--;
		}
		return pdst;
}

fifo.h

#ifndef _FIFO_H_
#define _FIFO_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define NODEMAX 6
typedef struct tagFIFO_T
{
	unsigned int nNodeSize;			//每个节点的大小
	unsigned int nNodeMax;			//FIFO的长度,节点的个数
	void *pvDataBuff;				//FIFO 缓冲区内存
	void *pcNodeBuff;				//单节点缓存 默认用内存块最后一个节点做缓存(出栈数据缓存)
	void *pvRead;					//读指针       
	void *pvWrite;					//写指针
	unsigned int nNodeCount;	    //节点数量				
	unsigned int nReadTimes;        //读的轮数
	unsigned int nWriteTimes;		//写的轮数
}FIFO_T, *P_FIFO_T;



///
//	函 数 名 : FIFO_Creat
//	函数功能 : FIFO的创建
//	处理过程 : 
//				
//	参数说明 : fifo_array : fifo数组内存池
//             pstFifo    : FIFO的名称.
//			   nNodeMax   : 最大节点数,实际要减1
//             nNodeSize  : 每个节点的大小
//	返 回 值 : 0 表示成功,非0表示失败。
///
P_FIFO_T FIFO_Creat(void *fifo_array, P_FIFO_T pstFifo, int nNodeMax, int nNodeSize);


///
//	函 数 名 : FIFO_Push
//	函数功能 : 往FIFO写入数据
//	处理过程 : 
//				
//	参数说明 :	hFifo : FIFO的名称. 
//				pvBuff: FIFO节点的指针,这里是用VOID型,是任意型,后面我定义了新的结构体,使用的人可以随意更改。
//	返 回 值 : 
///
void FIFO_Push(P_FIFO_T hFifo, void *pvBuff);



///
//	函 数 名 : FIFO_Pop
//	函数功能 : 从FIFO读出数据
//	处理过程 : 
//				
//	参数说明 : hFifo : FIFO的名称.
//	返 回 值 : 对应节点的地址。需要打印出来的话,请强制转换到目标类型。
///
char * FIFO_Pop(P_FIFO_T hFifo);


///
//	函 数 名 : myMemcpy
//	函数功能 : 系统memcpy的重新实现
///
void *myMemcpy(void *dest, const void *src, int count);

#endif  //_FIFO_H_

使用:
初始化

fifoInit();

bsp_usart.c

#include "bsp_usart.h"
#include "fifo.h"
#include "app_main.h"

DATA_T  msg;
unsigned char FIFO_Tx_Array[NODEMAX][NODESIZE];
unsigned char FIFO_Rx_Array[NODEMAX][NODESIZE];

FIFO_T usart1_rx_fifo;
FIFO_T usart1_tx_fifo;

void fifoInit(void)
{
	//利用fifo(循环利用二维数组)
	FIFO_Creat(&FIFO_Rx_Array, &usart1_rx_fifo,NODEMAX, NODESIZE);
	FIFO_Creat(&FIFO_Tx_Array, &usart1_tx_fifo,NODEMAX, NODESIZE);
}

DATA_T  msg;
uint8_t pushFifoIndex=0;
void getBlockstate(void)
{
	//优先级最高 直接覆盖
	char n=0;
	msg.frame.start = 0x7c7b;  //小端模式发送的时候自动翻转为7b 7c
	msg.frame.len = 2+1;
	msg.frame.cmd = 'a';
	msg.frame.data[n] = pushFifoIndex++; n++;
	msg.frame.data[n] = 0x0; n++;
	msg.frame.data[n] = 0x7c; n++;
	msg.frame.data[n] = 0x7d; n++;
	FIFO_Push(&usart1_tx_fifo,(void *)&msg);
	osSemaphoreRelease(sid_Semaphore_serialSend);
}



bsp_usart.h

#ifndef _BSP_USART_H_
#define _BSP_USART_H_
#include "fifo.h"

#define NODESIZE 100
#define NODEMAX 6

typedef union tagDATA_T
{
	
	__packed  struct frame_t
	{
		unsigned short start;
		unsigned short len;
		unsigned char cmd;
		unsigned char data[NODESIZE];
	}frame;
	unsigned char buf[NODESIZE-5];	
} DATA_T, *P_DATA_T;


extern FIFO_T usart1_rx_fifo;
extern FIFO_T usart1_tx_fifo;

void fifoInit(void);
void getBlockstate(void);
#endif


出栈:

#include "tx_thread.h"
#include "eventRecord.h"
#include "bsp_uart.h"

//串口数据发送线程
void tx_task(void * arg)
{
	int32_t rbStatus;
	loopData_Typedef buffer_loop;
	osStatus_t osStatus;
	P_DATA_T p;
	while(1)
	{
		osStatus = osSemaphoreAcquire(sid_Semaphore_serialSend,100);
		if(osStatus == osOK)
		{
				p = (P_DATA_T)FIFO_Pop(&usart1_tx_fifo);
				if(p != NULL)
				{
					/*do something...*/				
					virtual_debug(usart_tx,p->buf,p->frame.len+6);//发送数据
				}			
		}
		osDelay(200);
	}
}

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值