分布式系统项目需要,这次弄个CAN总线来布局,仅见CAN的冰山一角。
本次使用扩展帧模式。
STM32 对CAN的定义–库 CAN结构体定义 说明:
寄存器映射:
typedef struct
{
vu32 MCR;
vu32 MSR;
vu32 TSR;
vu32 RF0R;
vu32 RF1R;
vu32 IER;
vu32 ESR;
vu32 BTR;
u32 RESERVED0[88];
CAN_TxMailBox_TypeDef sTxMailBox[3];
CAN_FIFOMailBox_TypeDef sFIFOMailBox[2];
u32 RESERVED1[12];
vu32 FMR;
vu32 FM1R;
u32 RESERVED2;
vu32 FS1R;
u32 RESERVED3;
vu32 FFA1R;
u32 RESERVED4;
vu32 FA1R;
u32 RESERVED5[8];
CAN_FilterRegister_TypeDef sFilterRegister[14];
} CAN_TypeDef;
CAN消息发送:
/* CAN Tx message structure definition */
typedef struct
{
u32 StdId;
u32 ExtId;
u8 IDE;
u8 RTR;
u8 DLC;
u8 Data[8];
} CanTxMsg;
CAN消息接收:
/* CAN Rx message structure definition */
typedef struct
{
u32 StdId;
u32 ExtId;
u8 IDE;
u8 RTR;
u8 DLC;
u8 Data[8];
u8 FMI;
} CanRxMsg;
关于库函数相关结构体的定义,详情对照手册瞅瞅,,,不多说,也说不清。
滤波器设置:基于stm32的can总线彻底研究
对扩展数据帧过滤:
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)CAN_ID<<3)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)CAN_ID<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ~((u32)CAN_ID <<16); –
CAN_FilterInitStructure.CAN_FilterMaskIdLow = ~((u32)CAN_ID );
对标准数据帧过滤:—没试过,不做说明
CAN_FilterInitStructure.CAN_FilterIdHigh= (((u32)CAN_ID0<<21)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
数据收发:—解析
先上我们的协议说明:
这里只关心红线标注的….
不一一说明啦,上结构
/*定制协议版 扩展帧摘过来的帧头包 */
typedef struct ExtIdPack{
u32 Frame_Sn:4;//帧ID
u32 Valid_NB:5;//有效帧个数
u32 Echo_Flag_T:1;//发送类型--应答表示,1代表应答回复,0代表主动发送
u32 Commond:8;//功能码,命令字。从0x01开始,0x00暂时保留。
u32 DeviceID:11;//设备地址
//struct ExtIdPack *pNext;
}ExtIdPackage,*pExtIdPackage;
extern ExtIdPackage parsing;
extern pExtIdPackage pParsing;
typedef struct
{
ExtIdPackage ExtId;
u8 IDE;
u8 RTR;
u8 DLC;
u8 Data[8];
//u8 FMI;
} MyCanRxMsg;
extern MyCanRxMsg myCanRxMsg;
这样子定义,使用方便很多。
使用eg:
switch(myCanRxMsg.ExtId.Commond)
{
case 0x01:{ //查询 读取固件版本信息("01")
//协议填充...
if(myCanRxMsg.DLC){FRAME_RESET();break;} //数据不合规矩,pass
myCanRxMsg.DLC=sizeof(GetVersion)/sizeof(u8);
memcpy(&myCanRxMsg.Data[0],&GetVersion[0],myCanRxMsg.DLC);
memcpy(&TxMessage.ExtId,&myCanRxMsg,sizeof(MyCanRxMsg));//数据拷贝
CAN_Transmit(&TxMessage);
FRAME_RESET();
break;
}
。。。。
以上,有点乱,,,看着烦躁,赶紧切换页面————别砸电脑@
问:
本打算说说滤波器这块的设置来着–详细的
结果翻手册也没太弄明白 32-bit identifier 32-bit mask 为啥子要<<移动三位,如下。
/*
* 函数名:CAN_Filter_Config
* 描述 :CAN的过滤器 配置
* 输入 :无
* 输出 : 无
* 调用 :内部调用
*/
static void CAN_Filter_Config(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/*CAN过滤器初始化*/
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器组0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //工作在标识符屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //过滤器位宽为单个32位。
CAN_FilterInitStructure.CAN_FilterIdHigh= ((u32)0x00140000<<3)>>16; //要过滤的ID高位
CAN_FilterInitStructure.CAN_FilterIdLow= (((u32) 0x00140000<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要过滤的ID低位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFEB; //过滤器高16位每位必须匹配
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF; //过滤器低16位每位必须匹配
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FilterFIFO0; //过滤器被关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //使能过滤器
CAN_FilterInit(&CAN_FilterInitStructure);
/*CAN通信中断使能*/
CAN_ITConfig(CAN_IT_FMP0 /*| CAN_IT_FF0 | CAN_IT_FOV0*/, ENABLE); //
CAN_ITConfig(CAN_IT_TME, DISABLE); // 发送中断
}
这里
等待 神 前来说明,叩谢…..
留存…………………