嵌入式中缓冲区队列的实现

在串口,IIC或SPI以及CAN等通信中,往往需要一次性发送一帧完整的数据,由于硬件发送的速度问题,硬件不能及时发送出去,就会导致数据丢失等一系列问题。通常采用建立缓冲区解决。队列可以有效的利用缓冲区空间,并且保证数据在发送和接收过程中的时序问题。现在网上有公开的队列源码,其一般由入队,出队,查询队列成员数量,创建队列,销毁队列等组成,相对比较完善,但是在串口等环境中使用存在过多的调用函数等问题。所以就以上的情况做出了改善,编写了一个精简的缓冲队列,经过测试可以保证数据传输的完整性。

一、创建结构体

结构体主要由 缓冲区,队列头指针,队列尾指针,以及队列发送完成标志位组成。

/*******
数据发送缓冲区 结构体
*****/
typedef struct 
{
    u8 TxBuff[BUFFSIZE]; //缓冲区
    u16 font;                        //头指针
    u16 rear;             //尾指针
    u8 finished;         //发送完成,0代表未发送完,1代表发送完成,发送终止
 }TxBuffer;

二 入队函数

将发送的数据存入缓冲数组,并且移动相应长度的尾指针,检查发送标志位,判断是否需要启动硬件发送。主要有两个函数,一个为单字节发送个,另一个为多字节发送。

/*
 *函数名:UsartSendData
 *描述:串口发送数据,发送单字节
 *输入:tx:发送接口
 *输出:无
 *调用:外部调用
 */
void UsartSendData(ConnIFName tx,u8 data,USART_TypeDef* u)
{
        TxBuffer* buff = GetTxBuffer(tx);
      //占用1字节用于判断是否到达缓冲区尾部
        if(buff->rear == BUFFSIZE) buff->rear=0;
        buff->TxBuff[buff->rear++]=data;
        if(buff->finished == 1)
        {
            buff->finished=0;
            if(buff->font == BUFFSIZE) buff->font=0;
            USART_SendData(u,buff->TxBuff[buff->font]);
            buff->TxBuff[buff->font] = 0xFF;
            buff->font++;
        }
}

/*
 *函数名:MultitySend()
 *描述:串口发送数据,多字节发送
 *输入:tx->发送接口 ;sendData[] 发送的数组;u->调用发送的硬件串口;len->发送的长度
 *输出:无
 *调用:外部调用
 */
void MultitySend(ConnIFName tx,u8 data[],USART_TypeDef* u,u8 len)
{
    u8 i=0;
    TxBuffer* buff = GetTxBuffer(tx);
    if(len<BUFFSIZE-buff->rear+buff->font)
    {
        for(i=0;i<len;i++)
        {
            if(buff->rear == BUFFSIZE) buff->rear=0;
            buff->TxBuff[buff->rear++] = data[i];
        }   
        if(buff->finished !=0)
        {
            if(buff->font == BUFFSIZE) buff->font=0;
            USART_SendData(u,buff->TxBuff[buff->font++]);   
            buff->finished =0;
        }
    }
}

三 出队函数

读取队列中的数据并交由硬件发送,同时移动头指针到相应位置,根据情况操作标志位。这个函数一般由发送中断调用。

/*
 *函数名:TxBuffIRQ
 *描述:串口发送
 *输入:tx:发送接口
 *输出:无
 *调用:中断调用
 */
void TxBuffIRQ(ConnIFName tx,USART_TypeDef* u)
{
        //取得该通信接口缓冲区指针
        TxBuffer* buff = GetTxBuffer(tx);
         //判断缓冲区为NULL,则发送完成,停止发送
        if(buff->font == buff->rear )   
        {
            buff->finished=1;    //发送完成置位(缓冲区为空)
        }else
        {
        //判断是否到达队列尾部,如果到达则从头开始
        /**防止由于时间差的问题导致中断重复发送缓冲区数据*****/
            if(buff->font == BUFFSIZE ) buff->font=0; 
            USART_SendData(u,buff->TxBuff[buff->font]);
            //0xff填充缓冲区
            buff->TxBuff[buff->font] = 0xff;
            buff->font++;
        }
}

四 获取队列函数

当多个队列共存时,需要由该函数传递对应队列的指针,以便操作队列。

/*
 *函数名:GetTxBuffer
 *描述:取得发送缓冲区指针
 *输入:tx:取得哪个值
 *输出:无
 *调用:内部调用
 */
TxBuffer* GetTxBuffer(ConnIFName tx)
{
        switch (tx)
        {
            case DGUSIF:
                return &DgusTxBuff; 
            case WKIF:
                return &WKTxBuff;
            case CK1IF:
                return &CKTxBuff;
            default:
                break;
        }
    return 0;
}

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值