循环队列(自定义,4通道)在CAN中的使用

2022年4月1日

Kshine

1. 背景需求

(1)项目需要,使得CAN具有FIFO收发的功能。CAN1和CAN2的接收和发送都需要具有一定的数据缓冲功能。
(2)FIFO,先存入的数据,先被读出。这就像是一个管道,或者说是一个传送带。(下图请忽略)
下图请忽略
(3)存放数据的管道,长度不可能无限制的长。因而必须考虑改用环形队列。当管道装满数据后,先放的数据还没有被拿走,时效性算是最差的,因而将最新的数据(这次要放入管道的数据)覆盖最开始的数据。(下图请忽略)
(4) 在设计环形队列的时候,首尾的连接处需要格外注意。
下图请忽略2

2. 环形队列的设计

  • 在代码中的体现,实际就是一个定长的数组。
  • 可以通过双指针配合操作(相当于图中的两个小人配合操作)。(一开始试过,太绕了)
  • 可以通过单指针,知道数据个数的方式操作。(本人采取的方式,比较直接易懂)

队列设计

2.1 简述思路

  • 上图所示,是我实际写代码时,使用的思路。
  • 变量名解释:rh1 (接收通道1的开头,读取数据时的起始位置);fifoDataLen (当前已存放的字节数,可用来找到数据的尾部,即写入数据时的起始位置);RR (从rh1到数组最右边的剩余字节长度,Right Remain)。
  • 由上图可知,读取数据的位置rh1,是会变化的。每次读取N个字节,rh1就会向右移动N个字节。方便下次读到未被读出的数据
  • 在写入和读取数据的时候,都需要考虑 数组首尾连接处的特殊处理。

2.2 代码

  • 函数声明与宏定义
#define CAN_FIFO_MEMSIZE (1024)

/*---------------------------------
初始化某一端口(收发双路)的FIFO
输入参数:port 端口,1-CAN1 2-CAN2
---------------------------------*/
int init_MyFifo(uint16_t port);


/*---------------------------------
该函数一般不使用,仅在调试的时候使用。
初始化某一端口(收发双路)的FIFO,并重新指定缓冲区(缓冲区的长度还是要等于CAN_FIFO_MEMSIZE)
输入参数:port 端口,1-CAN1 2-CAN2
         rcvSnd ,1-接收通道,2-发送通道
         buf,指定的外部缓冲区
---------------------------------*/
int init_MyFifo_Buff(uint16_t port,uint8_t rcvSnd,uint8_t* buf);

/*---------------------------------
从环形队列里面读取指定长度的数据
输入参数:port 端口,1-CAN1 2-CAN2
         rcvSnd ,1-接收通道,2-发送通道
         data,用于存放读取得到的数据
         len,需要读取的字节数
---------------------------------*/
int loopBuffRead (uint32_t port,uint8_t rcvSnd,uint8_t* data,int len);

/*---------------------------------
向环形队列里面写入指定长度的数据
输入参数:port 端口,1-CAN1 2-CAN2
         rcvSnd ,1-接收通道,2-发送通道
         data,需要写入的源数据
         len,需要写入的字节数
---------------------------------*/
int loopBuffWrite(uint32_t port,uint8_t rcvSnd,uint8_t* data,int len);
  • 双路收发4通道缓冲区定义
static uint8_t  CAN1_FIFO_RCV[CAN_FIFO_MEMSIZE];
static int CAN1_FIFO_RcvLen=0;
static uint8_t  *CAN1_R=NULL; //数据开头位置

static uint8_t  CAN1_FIFO_SND[CAN_FIFO_MEMSIZE];
static int CAN1_FIFO_SndLen=0;
static uint8_t  *CAN1_S=NULL; //数据开头位置

static uint8_t  CAN2_FIFO_RCV[CAN_FIFO_MEMSIZE];
static int CAN2_FIFO_RcvLen=0;
static uint8_t  *CAN2_R=NULL; //数据开头位置

static uint8_t  CAN2_FIFO_SND[CAN_FIFO_MEMSIZE];
static int CAN2_FIFO_SndLen=0;
static uint8_t  *CAN2_S=NULL; //数据开头位置
  • 详细函数实现
int init_MyFifo(uint16_t port)
{
   
    if(port == 1)
    {
   
        CAN1_R = CAN1_FIFO_RCV;
        CAN1_S = CAN1_FIFO_SND;
        CAN1_FIFO_RcvLen = 0;
        CAN1_FIFO_SndLen = 0;
    }
    else if(port == 2)
    {
   
        CAN2_R = CAN2_FIFO_RCV;
        CAN2_S = CAN2_FIFO_SND;
        CAN2_FIFO_RcvLen = 0;
        CAN2_FIFO_SndLen = 0;
    }
    else return -1;
    //FIFO初始化时,打印该信息
    printf("-> FIFO: Port%d, Len%d\n\r",port,CAN_FIFO_MEMSIZE);
    return 0;
}

int init_MyFifo_Buff(uint16_t port,uint8_t rcvSnd,uint8_t* buf)
{
   
    if(port == 1)
    {
   
        if(rcvSnd==1)
        {
   
            CAN1_R = buf;
            CAN1_FIFO_RcvLen = 0;
        }
        else if(rcvSnd==2)
        {
   
            CAN1_S = buf;
            CAN1_FIFO_SndLen = 0;
        }
    }
    else if(port == 2)
    {
   
        if(rcvSnd==1)
        {
   
            CAN2_R = buf;
            CAN2_FIFO_RcvLen = 0;
        }
        else if(rcvSnd==2)
        {
   
            CAN2_S = buf;
            CAN2_FIFO_SndLen = 0;
        }
    }
    return 0;
}

int loopBuffRead(uint32_t port,uint8_t rcvSnd,uint8_t* data,int len)
{
   
    uint8_t *fifoAddress=NULL;
    uint8_t *p=NULL;
    int fifoDataLen = 0;
    if(len <= 0) return -2;//-2 CAN接收错误;
    if(port == 1)
    {
   
        if(rcvSnd == 1)
        {
   
            fifoAddress = CAN1_FIFO_RCV;
            fifoDataLen = CAN1_FIFO_RcvLen;
            p           = CAN1_R;
        }
        else if(rcvSnd == 2)
        {
   
            fifoAddress = CAN1_FIFO_SND;
            fifoDataLen = CAN1_FIFO_SndLen;
            p           = CAN1_S;
        }
        else
            return -2;
    }
    else if(port == 2)
    {
   
        if(rcvSnd == 1)
        {
   
            fifoAddress = CAN2_FIFO_RCV;
            fifoDataLen = CAN2_FIFO_RcvLen;
            p           = CAN2_R;
        }
        else if(rcvSnd == 2)
        {
   
            fifoAddress = CAN2_FIFO_SND;
            fifoDataLen = CAN2_FIFO_SndLen;
            p           = CAN2_S;
        }
        else
            return -2;
    }
    else
        return -2;
    if(p==NULL)return -1;
    //-------------------------------------------------//
	  
    if(len>fifoDataLen) return -3; //-3 接收缓冲区长度小于CAN报文长度。
    int RR =  fifoAddress+CAN_FIFO_MEMSIZE - p;
    if(RR <= 0)
    {
   
        RR  = CAN_FIFO_MEMSIZE;
        p   = fifoAddress;  
    }
    if(len < RR)
    {
   
        memcpy(data,p,len);
        p +=len;
    }
    else //len  >=  RR
    {
   
        //数据分两边
        memcpy(data,p,RR);
        memcpy(data+RR,fifoAddress,len-RR);
        p = fifoAddress + len-RR;
    }
    fifoDataLen -= len;
    //-------------------------------------------------//
    if(port == 1)
    {
   
        if(rcvSnd == 1)
        {
   
            CAN1_FIFO_RcvLen = fifoDataLen;
            CAN1_R           = p;
        }
        else if(rcvSnd == 2)
        {
   
            CAN1_FIFO_SndLen = fifoDataLen;
            CAN1_S           = p;
        }
    }
    else if(port == 2)
    {
   
        if(rcvSnd == 1)
        {
   
            CAN2_FIFO_RcvLen = fifoDataLen;
            CAN2_R           = p;
        }
        else if(rcvSnd == 2)
        {
   
            CAN2_FIFO_SndLen = fifoDataLen;
            CAN2_S           = p;
        }
    }	
    return 0;
}

int loopBuffWrite(uint32_t port,uint8_t rcvSnd,uint8_t* data,int len)
{
   
    uint8_t *fifoAddress=NULL;
    uint8_t *p=NULL;
    int fifoDataLen = 0;
    if(len <= 0) return -2;
    if(port == 1)
    {
   
        if(rcvSnd == 1)
        {
   
            fifoAddress = CAN1_FIFO_RCV;
            fifoDataLen = CAN1_FIFO_RcvLen;
            p           = CAN1_R;
        }
        else if(rcvSnd == 2)
        {
   
            fifoAddress = CAN1_FIFO_SND;
            fifoDataLen = CAN1_FIFO_SndLen;
            p           = CAN1_S;
        }
        else
            return -2;
    }
    else if(port == 2)
    {
   
        if(rcvSnd == 1)
        {
   
            fifoAddress = CAN2_FIFO_RCV;
            fifoDataLen = CAN2_FIFO_
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值