STM32 CAN模块使用详解.重点介绍以STM32F103E系列芯片为基础介绍CAN 总线的使用方法。CAN 总线在控制领域使用的非常广泛,如今大多数CPU芯片外围都扩展CAN接口。
1. 硬件基础
CAN总线工作需要两根数据线,RX和TX,即为输入总线和输出总线。一般CPU与外界通信需要接一个驱动芯片(这点很像UART接口),常用的CAN芯片主要有:SN65VHD230、PCA82C250T等,本系统使用SN65VHD230作为CAN接口芯片。而CPU提供的CAN接口为CAN_L和CAN_H。
2. 软件设计
在进行软件设计时,我们首先来看这样的一个结构体:
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter can be a value between 0 to 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter can be a value between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted.
This parameter can be a value of @ref CAN_identifier_type */
uint8_t RTR; /*!< Specifies the type of frame for the message that will be transmitted.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint8_t DLC; /*!< Specifies the length of the frame that will be transmitted.
This parameter can be a value between 0 to 8 */
uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0 to 0xFF. */
} CanTxMsg;
这是定义一个can数据包的结构体,即一个CAN数据包包含以上几个部分。
现在我们思考一个问题:由于can可连接多个节点,如果一个系统为星形网络连接方式,那么主机应该怎样区别这些从机发送的信息呢?
答案在上面那个结构体中,我们可以给每个分机定义一个ID,那么主机在接收到分机发送的数据后,通过ID号判别接收到的信息是那个从机发送的。
注意: DLC定义发送数据的长度,其范围为:0~8。
下面我们来编写CAN驱动:
对CAN模块初始化
void CAN_CfgInit(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_PortInit();
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM=DISABLE;
CAN_InitStructure.CAN_ABOM=DISABLE;
CAN_InitStructure.CAN_AWUM=DISABLE;
CAN_InitStructure.CAN_NART=DISABLE;
CAN_InitStructure.CAN_RFLM=DISABLE;
CAN_InitStructure.CAN_TXFP=DISABLE;
CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
CAN_InitStructure.CAN_Prescaler=5;
CAN_Init(CAN1, &CAN_InitStructure);
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber=0;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
// CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}
这里为can 定义一个专门的结构体,便于数据处理:
typedef struct CAN_Socket CAN;
struct CAN_Socket {
INT32U u32_StdId;
INT32U u32_ExtId;
INT8U u8_IDE;
INT8U u8_RTR;
INT8U u8_DLC;
INT8U u8_FMI;
INT8U u8_data[8];
};
|