问个CAN1CAN2扩展标准帧同步收发例程中,C基础问题哈
如下,往大神指点一下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;//数据缓存
}CAN_DataDef;
CAN_DataDef CAN1_Tx;
CAN_DataDef CAN1_Rx;
.......
........
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_DataDefCAN1_Rx;
就是不明白,为啥这样写,感觉是个数,放临时变量中
然后接下来的循环就有点迷了。可能就是 对 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); //从串口输出收到的数据
}
printf("\r\n");
}
}
}
n = CanReadMsg(CAN1_Rx);
从总线读取的报文一帧帧存放到CAN1_Rx数组,返回值 n 是这次读取的报文帧数。
CAN1_Rx.DataBuffer是第一帧报文数据,CAN1_Rx.DataBuffer是第二帧报文数据,以此类推。
循环 i 是打印第 i 帧报文内容。
循环 j 是打印当前帧的第 j 个数据。 乘风飞扬 发表于 2024-3-1 18:05
n = CanReadMsg(CAN1_Rx);
从总线读取的报文一帧帧存放到CAN1_Rx数组,返回值 n 是这次读取的报文帧数 ...
{:5_300:} 谢谢乘风大佬 mark一下: 省的下次再去翻找:
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=2559&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)
{
LED = 1; //关灯
}
else
{
LED = 0; //开灯
}
}
}
}
} 本帖最后由 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存放第一条报文内容,CAN1_Rx存放第二条报文内容。
我看你的代码里面只判断 CAN1_Rx.ID 如果读出多条报文的话,后面的报文都被你忽视掉了。”
REN_qian 发表于 2023-11-13 14:27
if(CAN1_Rx.ID==0x10261022)
if(CAN1_Rx.ID==0x10261023)
是这样接收两个ID的数据包吧
你的方法还是有问题,如果CAN1_Rx.ID=0x10261022,CAN1_Rx.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)
[*] { }
[*] }
[*] }
[*]
mark一下,省的下次再次翻找:
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=3280&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;
[*]}
页:
[1]