找回密码
 立即注册
查看: 209|回复: 5

问个CAN1CAN2扩展标准帧同步收发例程中,C基础问题哈

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-23 08:28
  • 签到天数: 42 天

    [LV.5]常住居民I

    14

    主题

    54

    回帖

    390

    积分

    中级会员

    积分
    390
    发表于 2024-3-1 16:41:34 | 显示全部楼层 |阅读模式
    如下,往大神指点一下
    typedef struct
    {
            u8        DLC:4;          //数据长度, bit0~bit3
            u8        :2;             //空数据, bit4~bit5
            u8        RTR:1;          //帧类型, bit6
            u8        FF:1;           //帧格式, bit7
            u32        ID;             //CAN ID
            u8        DataBuffer[8];  //数据缓存
    }CAN_DataDef;

    CAN_DataDef CAN1_Tx;      
    CAN_DataDef CAN1_Rx[8];  

    .......
    ........
    void main(void)
    {
           

        u8 i,j,n,sr;  
    .....
    ........
    if(B_Can1Read)//如果标志为1,即确认CAN1缓存收到数据
            {
                B_Can1Read = 0; //标志清0

                CANSEL = 0;         //选择CAN1模块
    //***********************
    从这里开始、、、、 有点读不懂了
                n = CanReadMsg(CAN1_Rx);    // 这里是 写的是 CAN1_Rx   ,前面结构体声明后,定义的是一个结构体数组 CAN_DataDef  CAN1_Rx[8];
    就是不明白,为啥这样写,感觉是个数,放临时变量中
    然后接下来的循环就有点迷了。  可能就是    对 u8 i,j,n     不理解吧

                if(n>0)
                {
                    for(i=0;i<n;i++)  
                    {
                     // CanSendMsg(&CAN1_Rx);  //CAN总线原样返回

                        printf("CAN1:ID=0x%08lX DLC=%d FF=%d RTR=%d ",CAN1_Rx.ID,CAN1_Rx.DLC,CAN1_Rx.FF,CAN1_Rx.RTR);   //串口打印帧信息

                        for(j=0;j<CAN1_Rx.DLC;j++)
                        {
                            printf("0x%02X ",CAN1_Rx.DataBuffer[j]);    //从串口输出收到的数据
                        }
                        printf("\r\n");
                    }
                }
            }

    回复 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 08:59
  • 签到天数: 143 天

    [LV.7]常住居民III

    27

    主题

    1343

    回帖

    4187

    积分

    论坛元老

    积分
    4187
    发表于 2024-3-1 18:05:12 | 显示全部楼层
    n = CanReadMsg(CAN1_Rx);
    从总线读取的报文一帧帧存放到CAN1_Rx[8]数组,返回值 n 是这次读取的报文帧数。
    CAN1_Rx[0].DataBuffer[j]是第一帧报文数据,CAN1_Rx[1].DataBuffer[j]是第二帧报文数据,以此类推。
    循环 i 是打印第 i 帧报文内容。
    循环 j 是打印当前帧的第 j 个数据。
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-4-23 08:28
  • 签到天数: 42 天

    [LV.5]常住居民I

    14

    主题

    54

    回帖

    390

    积分

    中级会员

    积分
    390
     楼主| 发表于 2024-3-2 21:30:09 | 显示全部楼层
    乘风飞扬 发表于 2024-3-1 18:05
    n = CanReadMsg(CAN1_Rx);
    从总线读取的报文一帧帧存放到CAN1_Rx[8]数组,返回值 n 是这次读取的报文帧数 ...

    谢谢乘风大佬
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-4-23 08:28
  • 签到天数: 42 天

    [LV.5]常住居民I

    14

    主题

    54

    回帖

    390

    积分

    中级会员

    积分
    390
     楼主| 发表于 2024-3-4 10:59:53 | 显示全部楼层
    mark一下: 省的下次再去翻找:

    https://www.stcaimcu.com/forum.p ... &extra=page%3D5

    例如,收到CAN ID为0x345的报文,第一个数据为0就关灯,否则就开灯
            if(B_CanRead)
            {
                B_CanRead = 0;
                
                n = CanReadMsg(CAN1_Rx);    //读取接收内容
                if(n>0)
                {
                    for(i=0;i<n;i++)
                    {
                        if(CAN1_Rx.ID == 0x345)
                        {
                            if(CAN1_Rx.DataBuffer[0] == 0)
                            {
                                LED = 1;    //关灯
                            }
                            else
                            {
                                LED = 0;    //开灯
                            }
                        }
                    }
                }
            }
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-4-23 08:28
  • 签到天数: 42 天

    [LV.5]常住居民I

    14

    主题

    54

    回帖

    390

    积分

    中级会员

    积分
    390
     楼主| 发表于 2024-3-4 13:11:08 | 显示全部楼层
    本帖最后由 QW123 于 2024-3-11 21:23 编辑

    mark一下: 省的下次再去翻找:
    https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4969&extra=page%3D3&page=1

    现在主机要发送两条数据,两个ID号,单片机只是收到数据后解析数据内容进行控制即可。
    遇到的问题是主机同时发两条数据包,只能收到第一个ID数据,第二个ID数据收不到,主机要发多次数据之后,第二个数据才可以收到。
    现在例程只是收发一条数据包,没有收发多条数据的。。
    。。。。

    n = CanReadMsg(CAN1_Rx);    //读取接收内容
    通过这个函数读取FIFO缓冲区里面所有的报文,返回值 n 表示当前读取的报文个数,存放在CAN1_Rx寄存器里。
    如果读到2条报文的话,其中CAN1_Rx[0]存放第一条报文内容,CAN1_Rx[1]存放第二条报文内容。
    我看你的代码里面只判断 CAN1_Rx[0].ID 如果读出多条报文的话,后面的报文都被你忽视掉了。”

    REN_qian 发表于 2023-11-13 14:27
    if(CAN1_Rx[0].ID==0x10261022)
    if(CAN1_Rx[1].ID==0x10261023)
    是这样接收两个ID的数据包吧


    你的方法还是有问题,如果CAN1_Rx[1].ID=0x10261022,CAN1_Rx[0].ID=0x10261023,就判断不到了。
    建议用例程的结构来判断

    •     n = CanReadMsg(CAN1_Rx);    //读取接收内容
    •     if(n>0)
    •     {
    •         for(i=0;i<n;i++)
    •         {
    •             if(CAN1_Rx.ID==0x10261022)
    •             {    }
    •             if(CAN1_Rx.ID==0x10261023)
    •             {    }
    •         }
    •     }


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-4-23 08:28
  • 签到天数: 42 天

    [LV.5]常住居民I

    14

    主题

    54

    回帖

    390

    积分

    中级会员

    积分
    390
     楼主| 发表于 2024-3-4 14:47:09 | 显示全部楼层

    mark一下,省的下次再次翻找:
    https://www.stcaimcu.com/forum.p ... &extra=page%3D3


    1秒定时时间到后发送两帧can数据,结果是每次只发送一条什么原因,大神给指导
    ...

    参考最新的屠龙刀例程包,或者STC32G库函数例程包里CAN总线例程,在“CanSendMsg”函数里增加发送完成判断(B_CanxSend ),上一帧数据发送完成后再发送本次数据,避免产生覆盖


    • void CanSendMsg(CAN_DataDef *CAN)
    • {
    •     u32 CanID;
    •     u8 RX_Index,i;
    •     if(CANSEL)  //判断是否CAN2
    •     {
    •         while(B_Can2Send);  //等待CAN2上次发送完成
    •     }
    •     else
    •     {
    •         while(B_Can1Send);  //等待CAN1上次发送完成
    •     }
    •     if(CAN->FF)     //判断是否扩展帧
    •     {
    •         CanID = CAN->ID << 3;
    •         CanWriteReg(TX_BUF0,CAN->DLC|((u8)CAN->RTR<<6)|0x80);        //bit7: 标准帧(0)/扩展帧(1), bit6: 数据帧(0)/远程帧(1), bit3~bit0: 数据长度(DLC)
    •         CanWriteReg(TX_BUF1,(u8)(CanID>>24));
    •         CanWriteReg(TX_BUF2,(u8)(CanID>>16));
    •         CanWriteReg(TX_BUF3,(u8)(CanID>>8));
    •         CanWriteReg(TX_BUF0,(u8)CanID);
    •         RX_Index = 1;
    •         for(i=0;((i<CAN->DLC) && (i<8));i++)        //数据长度为DLC,最多不超过8
    •         {
    •             CanWriteReg((u8)(TX_BUF0 + (RX_Index++&3)),CAN->DataBuffer);   //写入有效数据
    •         }
    •         while(RX_Index&3)   //判断已读数据长度是否4的整数倍
    •         {
    •             CanWriteReg((u8)(TX_BUF0 + (RX_Index++&3)),0x00);  //写入填充数据,一帧数据占据4的整数倍缓冲区空间,不足补0
    •         }
    •     }
    •     else    //发送标准帧
    •     {
    •         CanID = (u16)(CAN->ID << 5);
    •         CanWriteReg(TX_BUF0,CAN->DLC|((u8)CAN->RTR<<6));  //bit7: 标准帧(0)/扩展帧(1), bit6: 数据帧(0)/远程帧(1), bit3~bit0: 数据长度(DLC)
    •         CanWriteReg(TX_BUF1,(u8)(CanID>>8));
    •         CanWriteReg(TX_BUF2,(u8)CanID);
    •         RX_Index = 3;
    •         for(i=0;((i<CAN->DLC) && (i<8));i++)        //数据长度为DLC,最多不超过8
    •         {
    •             CanWriteReg((u8)(TX_BUF0 + (RX_Index++&3)),CAN->DataBuffer);   //写入有效数据
    •         }
    •         while(RX_Index&3)   //判断已读数据长度是否4的整数倍
    •         {
    •             CanWriteReg((u8)(TX_BUF0 + (RX_Index++&3)),0x00);  //写入填充数据,一帧数据占据4的整数倍缓冲区空间,不足补0
    •         }
    •     }
    •     CanWriteReg(CMR ,0x04);                //发起一次帧传输
    •     if(CANSEL)  //判断是否CAN2
    •     {
    •         B_Can2Send = 1;     //设置CAN2发送忙标志
    •     }
    •     else
    •     {
    •         B_Can1Send = 1;     //设置CAN1发送忙标志
    •     }
    • }


    在中断函数里清除发送完成标志"B_Can1Send ":
    • if((isr & 0x04) == 0x04)  //TI
    • {
    •     CANAR = ISR;
    •     CANDR = 0x04;    //CLR FLAG
    •     B_Can1Send = 0;
    • }



    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-18 04:31 , Processed in 0.061201 second(s), 48 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表