CAN通信介绍
开启CAN配置
首先开启HSE时钟,外接的8M的晶振。
打开时钟树,将PCLK1的频率设置为36MHz。
开启CAN通信,并设置波特率,我这里设置的是250K。
CAN波特率 = APB1_PCLK1/分频/(tq1 + tq2 + ss)
其他频率可以参考其他大佬的设置
波特率配置表
开启接收中断,这里根据需求选择RX0,我们只用FIFO0
这里测试,我们选择回环模式。
CAN过滤器
注意:不配置过滤器就无法接收数据。
掩码模式和列表模式需要提前了解,这里就不详细介绍了。
这里FilterScale选32位,就是FilterId高低一起作用。选16位,就是FilterIdHigh/FilterIdLow单独作用。FilterMaskId在列表模式与FilterId作用一致。
掩码遇1按位比较,列表就是白名单。
typedef struct
{
uint32_t FilterIdHigh; //CAN_FiR1寄存器的高16位
uint32_t FilterIdLow; //CAN_FiR1寄存器的低16位
uint32_t FilterMaskIdHigh; //CAN_FiR2寄存器的高16位
uint32_t FilterMaskIdLow; //CAN_FiR2寄存器的低16位
uint32_t FilterFIFOAssignment; //通过筛选器的报文存在FIFO0还是FIFO1中
uint32_t FilterBank; //此次配置用的是哪个筛选器。用单CAN的取值为0-13
uint32_t FilterMode; //掩码模式或列表模式
uint32_t FilterScale; //32位或16位
uint32_t FilterActivation; //使能或失能
uint32_t SlaveStartFilterBank; //CAN1和CAN2一起用的时候,为CAN2分配筛选器的个数
} CAN_FilterTypeDef;
这里我选的列表模式,毕竟总线上没有太多设备,我也就是固定收某几个设备的信息。
代码部分
typedef struct // 定义发送数据结构体
{
uint8_t conn : 1; // 按位定义
uint8_t estop : 1;
uint8_t alarm : 1;
uint8_t reset : 1;
uint8_t other:4;
uint8_t other2[7];
} SendDataStruct;
CAN_TxHeaderTypeDef can_Tx;
CAN_RxHeaderTypeDef can_Rx;
uint8_t sendBuf[8] = {0};
uint8_t recvBuf[8] = {0};
uint32_t box;
CAN_FilterTypeDef can_Filter = {0};
char aRxBuffer[100];
int aRxBufferIndex = 0;
uint8_t canSendData[8] = {0};
uint16_t CanFilterListSTID1 = 0x126;
// CAN接收中断回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can_Rx, recvBuf);
HAL_UART_Transmit( &huart1 , (uint8_t *)&recvBuf, sizeof(recvBuf), 0xFFFF);
}
// 串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart1)
{
if(aRxBufferIndex >= 100) {
aRxBufferIndex = 0;
}
aRxBufferIndex ++;
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer[aRxBufferIndex], 1);
}
}
HAL_CAN_Start(&hcan); // CAN启动
can_Tx.StdId = 0x108; // can发送消息头
can_Tx.ExtId = 0;
can_Tx.IDE = CAN_ID_STD;
can_Tx.RTR = CAN_RTR_DATA;
can_Tx.DLC = 8; // 数据长度
can_Tx.TransmitGlobalTime = DISABLE;
can_Filter.FilterIdHigh = (CanFilterListSTID1<<5)|(0x00<<4);; // can过滤器配置
can_Filter.FilterIdLow = 0;
can_Filter.FilterMaskIdHigh = 0;
can_Filter.FilterMaskIdLow = 0;
can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
can_Filter.FilterBank = 0;
can_Filter.FilterMode = CAN_FILTERMODE_IDLIST; // 列表模式,白名单
can_Filter.FilterScale = CAN_FILTERSCALE_16BIT; // 16位
can_Filter.FilterActivation = CAN_FILTER_ENABLE;
HAL_CAN_ConfigFilter(&hcan, &can_Filter);
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING); // 开启can中断接收
while (1)
{
can_Tx.StdId = CanFilterListSTID1;
SendDataStruct sendData = {0};
sendData.estop = 1;
HAL_CAN_AddTxMessage(&hcan, &can_Tx, &sendData, &box);
HAL_Delay(1000);
}