赞
踩
CAN 是控制器局域网络 (Controller Area Network) 的简称,它是由研发和生产汽车电子产品著称的德国 BOSCH 公司开发的,并最终成为国际标准(ISO11519以及ISO11898),是国际上应用最广泛的现场总线之一。CAN 总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN 为底层协议专为大型货车和重工机械车辆设计的 J1939 协议。近年来,它具有的高可靠性和良好的错误检测能力受到重视,被广泛应用于汽车计算机控制系统和环境温度恶劣、电磁辐射强及振动大的工业环境。
与 I2C、SPI 等具有时钟信号的同步通讯方式不同,CAN 通讯并不是以时钟信号来进行同步的,它是一种异步通讯,只具有 CAN_High 和 CAN_Low 两条信号线,共同构成一组差分信号线,以差分信号的形式进行通讯。
在stm32L4系列开发版上原理图:
开启接收中断:
Ctrl+S自动生成代码
在can.c中增加过滤器初始化代码
-
- /* Includes ------------------------------------------------------------------*/
- #include "can.h"
-
- /* USER CODE BEGIN 0 */
- #include "gpio.h"
- #include "stm32l4xx_hal.h"
- #include "stm32l4xx_hal_conf.h"
- #include <stdio.h>
- #include "hal_oled.h"
- #include "ds18b20.h"
- /* USER CODE END 0 */
-
- CAN_HandleTypeDef hcan1;
-
- /* CAN1 init function */
- void MX_CAN1_Init(void)
- {
-
- /* USER CODE BEGIN CAN1_Init 0 */
-
- /* USER CODE END CAN1_Init 0 */
-
- /* USER CODE BEGIN CAN1_Init 1 */
- void getmessage();
- /* USER CODE END CAN1_Init 1 */
- hcan1.Instance = CAN1;
- hcan1.Init.Prescaler = 16;
- hcan1.Init.Mode = CAN_MODE_NORMAL;
- hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
- hcan1.Init.TimeSeg1 = CAN_BS1_4TQ;
- hcan1.Init.TimeSeg2 = CAN_BS2_5TQ;
- hcan1.Init.TimeTriggeredMode = DISABLE;
- hcan1.Init.AutoBusOff = DISABLE;
- hcan1.Init.AutoWakeUp = DISABLE;
- hcan1.Init.AutoRetransmission = DISABLE;
- hcan1.Init.ReceiveFifoLocked = DISABLE;
- hcan1.Init.TransmitFifoPriority = DISABLE;
- if (HAL_CAN_Init(&hcan1) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN CAN1_Init 2 */
- //过滤器
- CAN_FilterTypeDef can1FilterConfig;
-
- can1FilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
- //过滤器是接收报文,不筛选
- can1FilterConfig.FilterIdHigh = 0x0000;
- can1FilterConfig.FilterIdLow = 0x0000;
- can1FilterConfig.FilterMaskIdHigh = 0x0000;
- can1FilterConfig.FilterMaskIdLow = 0x0000;
-
- can1FilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
- can1FilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
- can1FilterConfig.FilterBank = 0;
- can1FilterConfig.SlaveStartFilterBank = 13;
-
- can1FilterConfig.FilterActivation = CAN_FILTER_ENABLE; //使能过滤器
-
- //配置和激活CAN总线的接收中断功能
- if(HAL_CAN_ConfigFilter(&hcan1, &can1FilterConfig) != HAL_OK)
- {
- Error_Handler();
- }
-
- if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) !=HAL_OK)
- {
- Error_Handler();
- }
-
-
- /* USER CODE END CAN1_Init 2 */
-
- }
-
- void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
- {
-
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- if(canHandle->Instance==CAN1)
- {
- /* USER CODE BEGIN CAN1_MspInit 0 */
-
- /* USER CODE END CAN1_MspInit 0 */
- /* CAN1 clock enable */
- __HAL_RCC_CAN1_CLK_ENABLE();
-
- __HAL_RCC_GPIOB_CLK_ENABLE();
- /**CAN1 GPIO Configuration
- PB8 ------> CAN1_RX
- PB9 ------> CAN1_TX
- */
- GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
- /* CAN1 interrupt Init */
- HAL_NVIC_SetPriority(CAN1_TX_IRQn, 2, 0);
- HAL_NVIC_EnableIRQ(CAN1_TX_IRQn);
- HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 2, 0);
- HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
- /* USER CODE BEGIN CAN1_MspInit 1 */
-
- /* USER CODE END CAN1_MspInit 1 */
- }
- }
-
- void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
- {
-
- if(canHandle->Instance==CAN1)
- {
- /* USER CODE BEGIN CAN1_MspDeInit 0 */
-
- /* USER CODE END CAN1_MspDeInit 0 */
- /* Peripheral clock disable */
- __HAL_RCC_CAN1_CLK_DISABLE();
-
- /**CAN1 GPIO Configuration
- PB8 ------> CAN1_RX
- PB9 ------> CAN1_TX
- */
- HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9);
-
- /* CAN1 interrupt Deinit */
- HAL_NVIC_DisableIRQ(CAN1_TX_IRQn);
- HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);
- /* USER CODE BEGIN CAN1_MspDeInit 1 */
-
- /* USER CODE END CAN1_MspDeInit 1 */
- }
- }
-
- /* USER CODE BEGIN 1 */
-
-
- //发送函数
- CAN_TxHeaderTypeDef Tx_pHeader;
- int CAN_TX_Message(uint8_t TxData[], uint8_t length)
- {
- uint32_t TxMailboxNumber = 0x00000000U; // 存储本次发送所使用邮箱的邮箱号
- Tx_pHeader.StdId = 0x122; // 以此ID发送
- Tx_pHeader.ExtId = 0x0000; // 扩展ID(此处无用)
- Tx_pHeader.IDE = CAN_ID_STD; // 标准帧
- Tx_pHeader.RTR = CAN_RTR_DATA; // 数据帧
- Tx_pHeader.DLC = length; // 发送数据的长度
-
- Tx_pHeader.TransmitGlobalTime = DISABLE;
- //TxData发送的数据
- if(HAL_CAN_AddTxMessage(&hcan1, &Tx_pHeader, TxData, &TxMailboxNumber) !=HAL_OK)
- {
- return -1;
- }
- return TxMailboxNumber;
- }
-
-
- CAN_RxHeaderTypeDef hCAN1_RxHeader; //CAN1接收消息
-
-
- void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
- {
- uint8_t aRxData[8], i;
-
- if(HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &hCAN1_RxHeader, aRxData) ==HAL_OK)
- {
- printf("\r\nGet Rx Message Success!!\r\n");
-
- printf("[ID]:0x%lX [DLC]:%ld [Data]:", hCAN1_RxHeader.StdId,hCAN1_RxHeader.DLC);
-
- for(i=0; i<hCAN1_RxHeader.DLC; i++)
- printf("%X ", aRxData[i]);
- printf("\r\n");
-
- return Tx_pHeader.DLC; //是返回发送消息的数据长度
-
-
-
-
- // OLED_ShowString(1, 1,"helloworld",16);
- // OLED_ShowChinese(1,1,1);
-
-
-
-
- }
-
- }
-
- #if 0
- uint8_t can_receive_message(uint8_t *buf)
- {
- if(HAL_CAN_GetRxFifoFillLevel(&hcan1,CAN_RX_FIFO0)==0)
- {
- return 0;
- }
- HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0,&hCAN1_RxHeader,buf);
- return hCAN1_RxHeader.DLC;
- }
-
- #endif
-
-
- /* USER CODE END 1 */
-
- /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
在CAN分析仪和串口调试助手打印输出结果
CAN分析仪接收到的报文都是程序里面自己指定的报文
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。