[笔记 自用]CAN总线通信配置
1.STM32配置
波特率 = (CAN时钟 / 分频系数) / (1+Quanta in Bit Segment 1 +Quanta in Bit Segment 2 )
高速通信(接120欧末端电阻)波特率为125kBits/s ~ 1MBits/s
中断启用FIFO 0 :
2.电路
直接用的TJA1050模块,使用示波器探头观察总线电压。
设置1s发送一次数据。
注意: 两个TJA1050 CAN收发器可以不共地,本身带有隔离功能。但是需要5V供电。
波形为总线CANH 和 CANL的电压差
总线上只有发送机时的波形(一直在尝试重发):
总线上有接收机时:
接口:
PA11 -> RXD
PA12 -> TXD
TJA1050模块供电接5V,两个STM32使用不同的GND。
3.代码
不包含HAL库已经生成的部分
#define TXMODE 0 //控制接收还是发送
CAN_TxHeaderTypeDef TxHeader;
uint8_t TxData[10] = {24,26,29,51,99,110,240,12,0,21};/*发送的数据*/
int8_t SendFlag = 0;//发送成功标志
uint32_t TxMailbox=0;
uint8_t ERROR_LIST[20]={0};//故障列表
uint8_t RxData[10]={0};//接收机缓冲区
uint8_t can_data_received = 0;
uint32_t can_receive_count=0; //成功接到标志
CAN_RxHeaderTypeDef RxHeader;
/* 设置过滤器 */
void CAN_Filter_Config(void)
{CAN_FilterTypeDef can_filter;can_filter.FilterBank = 0; // 使用筛选器银行0can_filter.FilterMode = CAN_FILTERMODE_IDMASK; // 掩码模式can_filter.FilterScale = CAN_FILTERSCALE_32BIT; // 32位模式// 配置为接收所有标准ID报文 接收机只接收ID为0x12的信息can_filter.FilterIdHigh = 0x12<<5; //筛选器高16位 // 32位筛选器中 高11位是标准IDcan_filter.FilterIdLow = 0x0000; //筛选器低16位 // 32位筛选器中 高11位是标准IDcan_filter.FilterMaskIdHigh = 0B11111111111<<5; // 掩码高16位 - 0表示不关心 这里严格匹配11位的每一位标准ID 如果填写0B1111<<5 那就是只匹配最高的位IDcan_filter.FilterMaskIdLow = 0x0000; // 掩码低16位 - 0表示不关心can_filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; // 分配到FIFO0can_filter.FilterActivation = ENABLE; // 使能筛选器can_filter.SlaveStartFilterBank = 14; // 从筛选器银行14开始if (HAL_CAN_ConfigFilter(&hcan, &can_filter) != HAL_OK){ERROR_LIST[0]=1;Error_Handler();}
}void CAN_Receive_Init(void)
{/* 接收机中断初始化 */if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK){//接收FIFO 0ERROR_LIST[2]=1; Error_Handler();}
}void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcanp)//中断回调函数
{// 从FIFO0读取接收到的报文if (HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK){can_receive_count++;if( can_receive_count>1000000 ){can_receive_count=0;}//记录通信成功次数// 闪烁LED指示数据接收HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);// 这里可以添加数据处理代码// 例如:解析接收到的数据,根据ID执行不同操作等}
}void CAN_SendMessage(uint32_t id, uint8_t* data, uint8_t length)
{// 配置发送头TxHeader.StdId = id; // 标准IDTxHeader.ExtId = 0; // 扩展ID(标准帧时设为0)TxHeader.IDE = CAN_ID_STD; // 标准帧TxHeader.RTR = CAN_RTR_DATA; // 数据帧TxHeader.DLC = length; // 数据长度(0-8)// 发送消息if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, data , &TxMailbox) == HAL_OK){// 闪烁LED指示发送成功HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);}else{// LED快速闪烁表示发送错误HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);HAL_Delay(50);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);}
}int main(void)
{/* USER CODE BEGIN 1 */uint8_t i=0;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_CAN_Init();/* USER CODE BEGIN 2 */CAN_Filter_Config();//初始化筛选器HAL_CAN_Start(&hcan); //启动CAN收发器
#if (TXMODE==0)CAN_Receive_Init(); // 初始化CAN接收中断
#endifi=0;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */
#if (TXMODE==1)i++;if(i>3){i=0;}CAN_SendMessage( (0x12), TxData, 2);//发送数组前两个数据 数据识别ID为0x12HAL_Delay(1000);
#endif}/* USER CODE END 3 */
}