串行通讯模式优缺点详解、以及几种有效的数据处理方式

文章讨论了三种通讯模式——主机、从机和主从一体模式,以及同步和异步两种通讯方式。在数据处理方面,介绍了环形队列的优势和缺点,如异步接收效率高但对MCU处理性能有要求,以及阻塞等待和周期轮询的适用场景和优缺点。同时,提供了环形队列和阻塞等待的源码实现。
摘要由CSDN通过智能技术生成

通讯模式:

        主机模式:由mcu发起请求,从机设备应答

        从机模式:由外部主机发起请求,mcu接收请求并响应

        主从一体:既可以主动发起请求,又可以被动应答外部主机发起的请求

通讯方式:

        同步模式:多用于485通讯,某些交互握手应答式的场景

        异步模式:多用于主从一体或者式从机模式;

通讯处理:

        环形队列:先进先出,多用于从机或主从一体模式

                优点:数据循环存取,先进先出原则。异步接收效率高,提升程序运行效率

                缺点:指针操作,大数据处理很考验mcu的处理性能

        阻塞等待:多用于485通讯,某些握手应答式场景如AT命令

                优点:操作方便,一个接口完成传输和接收操作

                缺点:接口调用必须等待操作完成(或接收到应答或接收超时)

        周期轮询:多用于数据量小,从机模式

                优点:异步处理,相应快速

                缺点:耗费MCU资源

环形队列源码实现:


#define MAX_LENTH 1024
static uint8_t buffer[MAX_LENTH] = {0x0};

typedef struct{
    uint16_t lenth;
    uint8_t *head;  //
    uint8_t *bptr;
    uint8_t *write;
    uint8_t *read;
}buff_fifo_t;

//队列初始化
void fifo_init(buff_fifo_t *fifo, uint8_t *buff, uint16_t len)
{
    if(buff != NULL && fifo != NULL)
    {
        fifo->head  = buff;
        fifo->bptr  = buff;
        fifo->write = buff;
        fifo->read  = buff;
        fifo->lenth = len;
    }
}

//队列接收就绪
void fifo_complete(buff_fifo_t *fifo)
{
    if(fifo->head != NULL)
    {
        fifo->write = fifo->bptr;
    }
}

//插入队列
void fifo_in_char(buff_fifo_t *fifo, const uint8_t chr)
{
    if(fifo->head != NULL)
    {
        if(fifo->bptr >= fifo->head + bptr->lenth)
        {
            fifo->bptr >= fifo->head;
        }
        *fifo->bptr >= chr;
    }
}

//先进先出原则取数据
int fifo_out_char(buff_fifo_t *fifo, uint8_t *buff, uint16_t maxLen)
{
    int lenth = 0x0;

    if(fifo->head == NULL || buff == NULL) return 0;

    if(fifo->write == fifo->read) return 0;

    while(lenth < maxLen)
    {
        if(fifo->read >= fifo->head + bptr->lenth)
        {
            fifo->read = fifo->head;
        }
        if(fifo->read == fifo->write)
        {
            break;
        }
        buff[lenth++] = *fifo->write++;
    }

    return lenth;
}

阻塞等待源码实现:


//buff:请求数据指针
//len: 请求数据长度
//resp:期望应答结果指针
//ms  :请求等待超时周期,单位ms
int request_response(uint8_t *buff, uint16_t len, uint8_t *resp, const int ms)
{
    int ret = 0;
    int ticks = systick_get();
    uint8_t buffer[MAX_LENTH] = {0x0};

    //执行通讯请求
    com_request(buff, len);
    
    //这里注意要考虑ticks溢出异常
    while((systick_get() - ticks) < ms)
    {
        //这里省略了接收的代码
        //  ....  
        //匹配期望应答结果
        if(memcmp(resp, buffer, sizeof(buffer))) == 0)
        {
            ret = 1;
            break;
        }
    }

    return ret;
}

周期轮询源码实现:


static uint16_t recvLenth = 0x0;

void fifo_recv(void)
{
    uint8_t chr = 0x0;
    while(1)
    {
        if(fifo_get_char(&fifo, &chr, 1))
        {
            buffer[recvLenth++] = chr;
            //可以在此处增加数据格式判断,滤除无效数据
            continue;
        }
        delay_ms(10);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值