环形队列串口通信

/** @copyright  Copyright(c)2014-2011 XXXX Co.,Ltd. All rights reserved.
  ******************************************************************************
  * @file       uart.h
  * @brief      
  * @details    
  * @author     匠在江湖(ID:1234)
  * @version    V1.0
  * @date       2014/05/08
  ******************************************************************************
  * @attention
  * 
  * @par 修改日志:
  * <table>
  * <tr><th>Date        <th>Version <th>Author(ID:xxxxxx)   <th>Description</tr>
  * <tr><td>2014/05/08  <td>V1.0    <td>匠在江湖(ID:1234)   <td>创建初始版本</tr>
  * </table>
  ******************************************************************************
  */


#ifndef UART_H_
#define UART_H_
/* Includes *******************************************************************/
#include"base.h"

#ifdef __cplusplus
 extern "C"{
#endif

/* Exported types *************************************************************/
typedef struct
{
    RingQueueTypeS RxRingQueue; //接收环形队列
    
    u8 TxSize; //发送字节数
    u8 *TxBuf; //发送缓存指针
}UartTypeS;

/* Exported constants *********************************************************/
/* Exported macro *************************************************************/
/* Exported functions *********************************************************/
extern u8 UartxTxOutput(UartTypeS *uartx, u8 *pdat); //串口发送输出
extern u8 UartxTxIT(UartTypeS *uartx, u8 *txBuf, u8 txSize); //串口发送-中断方式
extern u8 UartxRxInput(UartTypeS *uartx, u8 dat); //串口接收输入
extern u8 UartxRxIT(UartTypeS *uartx, u8 *rxBuf, u8 rxBufSize); //串口接收-中断方式
extern void UartxInit(UartTypeS *uartx, u8 *rxFifo, u8 rxFifoSize); //串口初始化

#ifdef __cplusplus
}
#endif

#endif /* UART_H_ */

/********************************* END OF FILE ********************************/
/** @copyright  Copyright(c)2014-2011 XXXX Co.,Ltd. All rights reserved.
  ******************************************************************************
  * @file       uart.c
  * @brief      
  * @details    
  * @author     匠在江湖(ID:1234)
  * @version    V1.0
  * @date       2014/05/08
  ******************************************************************************
  * @attention
  * 
  * @par 修改日志:
  * <table>
  * <tr><th>Date        <th>Version <th>Author(ID:xxxxxx)   <th>Description</tr>
  * <tr><td>2014/05/08  <td>V1.0    <td>匠在江湖(ID:1234)   <td>创建初始版本</tr>
  * </table>
  ******************************************************************************
  */


/* Includes *******************************************************************/
#include "uartx.h"
#include "queue.h"
#include "mcu.h"
/* Private typedef ************************************************************/
/* Private constants **********************************************************/
/* Private macro **************************************************************/
#define UART_TX_TRG_START()         UART0_TIF_SET() //传输中断标志 置位
/* Private variables **********************************************************/
/* Private function prototypes ************************************************/


/**
  ******************************************************************************
  * @brief  串口发送输出 函数
  * @param  *uartx 串口类型指针
  * @param  *pdat 串口发送缓存地址
  * @return 1-有数据发送; 0-无数据发送
  * @note   在MCU串口处理函数中调用该函数,并将发送缓存地址为参数传入
  ******************************************************************************
  */
u8 UartxTxOutput(UartTypeS *uartx, u8 *pdat)
{
    if(uartx->TxSize)
    {
        *pdat = *uartx->TxBuf++;
        uartx->TxSize--;
        return 1;
    }
    return 0;
}

/**
  ******************************************************************************
  * @brief  串口发送中断方式 函数
  * @param  *uartx  串口类型指针
  * @param  *txBuf  待发数据块指针
  * @param  txSize 待发数据字节
  * @return 1-忙; 0-加载发送数据成功
  * @note   
  ******************************************************************************
  */
u8 UartxTxIT(UartTypeS *uartx, u8 *txBuf, u8 txSize)
{
    if(!uartx->TxSize)
    {
        uartx->TxBuf = txBuf;
        uartx->TxSize = txSize;
        UART_TX_TRG_START(); //发送触发启动
        return 0;
    }
    return 1;
}

/**
  ******************************************************************************
  * @brief  串口接收输入 函数
  * @param  dat 串口收到的1字节数据
  * @return 0-写入成功;1-队列已满
  * @note   在MCU串口处理函数中调用该函数,并将接收到的数据作为参数传入
  ******************************************************************************
  */
u8 UartxRxInput(UartTypeS *uartx, u8 dat)
{
    return WriteByteToRingQueue(&uartx->RxRingQueue, dat);
}

/**
  ******************************************************************************
  * @brief  串口接收中断方式 函数
  * @param  *uartx  串口类型指针
  * @param  *txBuf  待接收数据缓存指针
  * @param  rxBufSize 待接收数据缓存字节
  * @return 接收到的字节
  * @note   
  ******************************************************************************
  */
u8 UartxRxIT(UartTypeS *uartx, u8 *rxBuf, u8 rxBufSize)
{
    u8 dat;
    u8 rxSize = 0;

    while(rxSize < rxBufSize)
    {
        if( ReadByteFromRingQueue(&uartx->RxRingQueue, &dat) ) break; //返回:0-读出成功;1-队列已空
        rxBuf[rxSize++] = dat; //读取队列数据 到 接收缓存
    }
    
    while(s_uart.RxIn < RX_BUF_SIZE) //读取位置 小于 接收缓存大小
    {
        if( ReadByteFromRingQueue(&s_uart.RxRingQueue, &dat) ) break; //返回:0-读出成功;1-队列已空
        s_uart.RxBuf[s_uart.RxIn++] = dat; //读取队列数据 到 接收缓存
    }

    if(s_uart.RxIn >= PROTOCOL_HEAD_SIZE) //小于 协议头字节 退出
    {
        offset = 0;
        while((s_uart.RxIn - offset) >= PROTOCOL_HEAD_SIZE) //处理的数据字节要 大于 协议头字节
        {
            if(*(u16 *)&s_uart.RxBuf[offset + FRAME_HEAD_SI] != FRAME_HEAD) //查找帧头
            {
                offset++; //帧头错误,继续查找
                continue;
            }
            
            rxSize = s_uart.RxBuf[offset + FRAME_LEN_SI] + PROTOCOL_HEAD_SIZE; //整帧字节长
            if(rxSize > RX_BUF_SIZE) //判断整帧字节长是否超出缓存
            {
                offset++; //帧长超出缓存,数据错误,继续查找下个帧头
                continue;
            }

            if((s_uart.RxIn - offset) < rxSize) break; //接收数据不够一帧,结束查找

            if(GetBCC((u8 *)&s_uart.RxBuf[offset], rxSize)) //校验
            {
                offset++; //校验出错,继续查找下个帧头
                continue;
            }

            UartRxHandle(&s_uart.RxBuf[offset]); //校验成功,接收数据进行处理
            
            offset += rxSize; //偏移到下帧
        }

        s_uart.RxIn -= offset; //索引前移
        for(i=0; i<s_uart.RxIn; i++) //s_uart.RxIn 大于零,说明存在待处理数据
        {
            s_uart.RxBuf[i] = s_uart.RxBuf[i + offset]; //丢弃处理后的数据,待处理数据前移
        }
    }
    
    return rxSize;
}
/**
  ******************************************************************************
  * @brief   接收解包 函数
  * @param   None
  * @return  None
  * @note    在MCU主函数while循环中调用该函数
  ******************************************************************************
  */
void UartRxUnpack(void)
{
    u8 offset;
    u8 rxSize;
    u8 dat;
    u8 i;

    while(s_uart.RxIn < RX_BUF_SIZE) //读取位置 小于 接收缓存大小
    {
        if( ReadByteFromRingQueue(&s_uart.RxRingQueue, &dat) ) break; //返回:0-读出成功;1-队列已空
        s_uart.RxBuf[s_uart.RxIn++] = dat; //读取队列数据 到 接收缓存
    }

    if(s_uart.RxIn >= PROTOCOL_HEAD_SIZE) //小于 协议头字节 退出
    {
        offset = 0;
        while((s_uart.RxIn - offset) >= PROTOCOL_HEAD_SIZE) //处理的数据字节要 大于 协议头字节
        {
            if(*(u16 *)&s_uart.RxBuf[offset + FRAME_HEAD_SI] != FRAME_HEAD) //查找帧头
            {
                offset++; //帧头错误,继续查找
                continue;
            }
            
            rxSize = s_uart.RxBuf[offset + FRAME_LEN_SI] + PROTOCOL_HEAD_SIZE; //整帧字节长
            if(rxSize > RX_BUF_SIZE) //判断整帧字节长是否超出缓存
            {
                offset++; //帧长超出缓存,数据错误,继续查找下个帧头
                continue;
            }

            if((s_uart.RxIn - offset) < rxSize) break; //接收数据不够一帧,结束查找

            if(GetBCC((u8 *)&s_uart.RxBuf[offset], rxSize)) //校验
            {
                offset++; //校验出错,继续查找下个帧头
                continue;
            }

            UartRxHandle(&s_uart.RxBuf[offset]); //校验成功,接收数据进行处理
            
            offset += rxSize; //偏移到下帧
        }

        s_uart.RxIn -= offset; //索引前移
        for(i=0; i<s_uart.RxIn; i++) //s_uart.RxIn 大于零,说明存在待处理数据
        {
            s_uart.RxBuf[i] = s_uart.RxBuf[i + offset]; //丢弃处理后的数据,待处理数据前移
        }
    }
}
/**
  ******************************************************************************
  * @brief  串口初始化 函数
  * @param  *uartx  串口类型指针
  * @param  *rxFifo  接收FIFO指针
  * @param  rxFifoSize 接收FIFO字节
  * @return None
  * @note   
  ******************************************************************************
  */
void UartxInit(UartTypeS *uartx, u8 *rxFifo, u8 rxFifoSize)
{
    uartx->RxRingQueue.In = 0; //写入的位置
    uartx->RxRingQueue.Out = 0; //读出的位置
    uartx->RxRingQueue.BufSize = rxFifoSize; //缓存字节数
    uartx->RxRingQueue.Buf = rxFifo; //缓存指针

    uartx->TxSize = 0; //发送字节数
    uartx->TxBuf = 0; //发送缓存指针
}

/********************************* END OF FILE ********************************/

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值