CAN 通讯 联合体 公用体 调试 使程序更整洁 好 20201226 C盘的路径 20201221

目的: 本次主要针对CAN协议  定义了共用体  例如一个帧  字节0 是运行模式  

字节0里面的各个位的定义不一样, 可以对字节0 整体进行操作,可以对字节0里面

的某一个位进行操作

定义CANDATA 结构体数据类型  

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

在com.c 文件中定义变量 并初始化 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

Candata=CANDATA_DEFAULTS   不能放在com init()中完成初始化   

 

 

 

如果需要在函数中进行初始化, 是否需要应用 for()循环函数赋值 ?

 

接收回调函数   并没有在 主循环中 使用   但是 还是可以发现在 不断的接收  

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

后面尝试一下  能不能把这个 CANRunMode  再变成位阈型 结构体   

将上面的 candata  中的元素 定义成 位阈型 结构体   

方法:

 

 Typedef  union _CANRunModeInfo  

 

{

 

Uint 8   Byte ;      //这样可以对一个字节 进行操作  

 

Struct

 

{

 

  Uint 8     DLC :4    ;  //最低位

 

Uint8      undef : 2;   //未定义  

 

  Uint8      mode:2     //运行模式    00 转速模式   01  转矩模式

 

 

 

 

 

}Bits

 

 

 

 

 

}CANRunModeInfo            //这个数据类型就叫做 CANRunModeInfo

 

 

 

然后新定义结构体    

 

typedef struct {

 

 

       CANRunModeInfo    CANRunMode    //上位机器的运行模式   

uint16 CANSetSpeed ;                 //上位机给定转速

 

  uint8   Press1_pul;                 //压力传感器1的标幺值

  uint8   Press2_pul;                 //压力传感器2的标幺值

 

 

}  CANDATA;

 

 

现在 我想 能不能这样  赋值    如下图  

 candata.CANRunMode =  Com_dataRxUBA[2][0];

 

第二  我能不能 这样操作  

 candata.CANRunMode.mode  这样就把 uint8 数据类型变量的最高两位CANRunMode

拿出来, 进而去判断  

 

if(candata.CANRunMode.mode ==0)  {}

if(candata.CANRunMode.mode ==1)  {}

if(candata.CANRunMode.mode ==2)  {}

if(candata.CANRunMode.mode ==3)  {}

 

 

敲打完成程序   发现  candata.CANRunMode =  Com_dataRxUBA[2][0];

是不行的。    

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

我想需要这样操作 :

 

candata.CANRunMode.Byte=  Com_dataRxUBA[2][0]; 

 

问题得到解决    

 

 

 

改正以后   

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

结构体的一个成员是联合体 数据类型 可以对位进行操作, 也可以整体操作

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

初始化  

 

 CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

引用方式  

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

用ZLG 调试   发现  联合体 按照位 操作  BITS  下的成员 可以使用  

 

 

下午接下来需要完成的任务是  

第一:更新到博客园  

第二:将你这部分实现的方式写进路程图  软件概要设计说明书

 

举一反三:

对于CAN消息的格式    因为有很多消息, 而消息的 配置格式都一样,  

这些消息的29位ID号的格式都是一样的。

这时候 可以 用指针变量     来指向不同消息的首地址, 这样就不用配置很多消息,

只用一个指针指向该消息就好。

 

定义数据类型   

共用体 可以最整体操作 也可以对位阈进行操作

 

 

需要注意: 下图中是 DLC 是 最低位开始 不是最高位开始。

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

然后定义icanmasg  message1  变量

以及指针变量  icanmsg  *pcan

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

CheckmaciD 函数定义

void CheckMACID( iCANMSG *piCANMSG ,unsigned char ackcan)reentrant

 

调用方式  

CheckMACID( & message1 ,0);    

注意 上图中 调用的 message1 是 实际参数  。是前面定义的全局变量 ,

而在定义函数的过程中  piCANMSG 是形式参数 ,调用函数的时候,将实际参数 传递给形式参数然后 参与计算。

 

 

下图是给 形式参数变量的 元素赋值  然后 发送出去。

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

因为CAN消息很多,而且帧的结构都一样, 故采用指向 ICANMSG  格式指针的方式。

 

 

 

现在开始着手发送函数的配置  

 

现在开始定义压力传感器的接入状态  然后 往上位机 上报的过程   

我定义了共用体   4个  

第7位

第6位

第5位

第4位

第3位

第2位

第1位

第0位

压力传感器4接入状态

压力传感器3接入状态

压力传感器2接入状态

压力传感器1接入状态

 

 

 

 

 

 

 

 

 

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

我的想法是  判断了GPIO 口  如果是高的话   

If(GPIO==1)  

 candata.Press_Sensor_Status.Bits.Press_Sensor1_status=1;    //正常

else   

 candata.Press_Sensor_Status.Bits.Press_Sensor1_status=2;    //故障

 然后我想   发送邮箱如何赋值  用的是字节8  

  candata.Press_Sensor_Status.Bits.Press_Sensor1_status=2;

 

  candata.Press_Sensor_Status.Bits.Press_Sensor2_status=2;

 

  candata.Press_Sensor_Status.Bits.Press_Sensor3_status=2;

 

  candata.Press_Sensor_Status.Bits.Press_Sensor4_status=2;

 

要把状态发送出去    

直接就调用   

   dataTxUBA[]=candata.Press_Sensor_Status.Byte;   就可以了   

 

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

 

下图的 idxMsgUB  实际上决定了消息通道   消息通道又是什么?

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

消息通道是什么 看下面的图

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

所以选择了3  也就是 选择了 ID号 是  0X19881205

 

 

更改前   

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

更改以后:

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

然后我在主程序 的其他地方 进行赋值     为了方便起见   

我就直接先在初始化com_init()中进行 赋值  

 

测试条件  

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

下载程序到TC234 开发板

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

测试ok   确实 是0XE8 0X03  14  1E  01  02  03  03  E4 

 

 

总结 综上 : 

 

假如我定义了 发送邮箱    定义了接收邮箱  

 

先说 发送   

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

因为我把气瓶传感器的接入状态 变成了 共用体  可以对位 对整体 分别操作  

故在主程序中   可以对位阈型成员 进行赋值  

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

然后 在CAN发送的时候  直接用  下面的赋值语句  

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

 

如果在接收的过程  

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

 

我把驱动电机的运行指令 做成了 位阈型   共用体  可以对整体和为进行 分别操作  

 

把接收的数据 直接 赋予给 联合体   candata.CANRunMode.Byte

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

 

然后就可以对位阈型成员 进行判断  

 

if( candata.CANRunMode.Bits.mode==0)   // mode   判断如果是启动状态   则置位响应的标志位

 

    {

 

 

 

}

 

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

直接 可以看到  位阈型成员 mode  就是 3  

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

那么 就可以直接 在下面的 方括号中  置位启动标志

if( candata.CANRunMode.Bits.mode==0)   // mode   判断如果是启动状态   则置位响应的标志位

    {

 

}

 

 

 

我定义了一个结构体  存放的是CAN 发送 和 接收的参数  

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

需要注意的是  

在接收 和 发送 邮箱 中

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

 

CAN 通讯 联合体 公用体 调试  使程序更整洁 好 20201226  C盘的路径  20201221

 

 

 

源程序的百度网盘链接地址 

 

上一篇:JSON与XML优缺点对比分析


下一篇:Leetcode题解(十八)