一、所用材料:
STM32F103C6T6最小系统板
STM32CUBEMX(HAL库软件)
MDK5
串口调试助手
二、所学内容:
初步学习如何使用STM32的CAN通讯功能,在本章节主要达到板内CAN通讯的效果,即32发送CAN信息再在CAN接收中断中用串口打印出来。
三、CUBEMX配置:
第一步:老三件套-RCC,SYS,时钟树配置
第二步:串口配置
第三步:CAN配置
关键步骤:
- 波特率设置:1M bit/s,具体配置如下图
- TEST MODE - Loopback
- 打开接收中断RX0
四、MDK5配置:
一、can.h头文件配置
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __CAN_H__
#define __CAN_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern CAN_HandleTypeDef hcan;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_CAN_Init(void);
/* USER CODE BEGIN Prototypes */
void CANFilter_Config(void);
void CAN1_Send_Test(void);
void CAN_Start_Init(void);
void CAN1_Send(uint8_t* cdata);
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __CAN_H__ */
二、can.c源文件配置
/* Includes ------------------------------------------------------------------*/
#include "can.h"
/* USER CODE BEGIN 0 */
#include "stdio.h"
#include "usart.h"
#include "main.h"
static CAN_TxHeaderTypeDef TxMessage; //CAN发送的消息的消息头
static CAN_RxHeaderTypeDef RxMessage; //CAN接收的消息的消息头
/* USER CODE END 0 */
CAN_HandleTypeDef hcan;
/* CAN init function */
void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 4;
hcan.Init.Mode = CAN_MODE_LOOPBACK;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_5TQ;
hcan.Init.TimeSeg2 = CAN_BS2_3TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN_Init 2 */
/* USER CODE END CAN_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_GPIOA_CLK_ENABLE();
/**CAN GPIO Configuration
PA11 ------> CAN_RX
PA12 ------> CAN_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* CAN1 interrupt Init */
HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USB_LP_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();
/**CAN GPIO Configuration
PA11 ------> CAN_RX
PA12 ------> CAN_TX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
/* CAN1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
/* USER CODE BEGIN CAN1_MspDeInit 1 */
/* USER CODE END CAN1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/*******************
接受信息过滤器
*******************/
void CANFilter_Config(void)
{
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0; //CAN过滤器编号,范围0-27
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; //CAN过滤器模式,掩码模式或列表模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //CAN过滤器尺度,16位或32位
sFilterConfig.FilterIdHigh = 0x000 << 5; //32位下,存储要过滤ID的高16位
sFilterConfig.FilterIdLow = 0x0000; //32位下,存储要过滤ID的低16位
sFilterConfig.FilterMaskIdHigh = 0x0000; //掩码模式下,存储的是掩码
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = 0; //报文通过过滤器的匹配后,存储到哪个FIFO
sFilterConfig.FilterActivation = ENABLE; //激活过滤器
sFilterConfig.SlaveStartFilterBank = 0;
if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
else{ printf("HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) is HAL_OK\r\n"); }
}
/*******************
中断接受
*******************/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t data[8];
HAL_StatusTypeDef status;
status = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, data);
if (HAL_OK == status)
{
printf("--->Data Receieve!\r\n");
printf("RxMessage.StdId is %#x\r\n", RxMessage.StdId);
printf("data[0] is 0x%02x\r\n", data[0]);
printf("data[1] is 0x%02x\r\n", data[1]);
printf("data[2] is 0x%02x\r\n", data[2]);
printf("data[3] is 0x%02x\r\n", data[3]);
printf("data[4] is 0x%02x\r\n", data[4]);
printf("data[5] is 0x%02x\r\n", data[5]);
printf("data[6] is 0x%02x\r\n", data[6]);
printf("data[7] is 0x%02x\r\n", data[7]);
printf("<---\r\n");
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
}
}
/*******************
发送函数
*******************/
void CAN1_Send_Test(void)
{
uint32_t TxMailbox;
uint8_t data[4] = {0x01, 0x02, 0x03, 0x04};
TxMessage.IDE = CAN_ID_STD; //设置ID类型
TxMessage.StdId = 0x111; //设置ID号
TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧
TxMessage.DLC = 4; //设置数据长度
if (HAL_CAN_AddTxMessage(&hcan, &TxMessage, data, &TxMailbox) != HAL_OK)
{
Error_Handler();
}
// else{ printf("HAL_CAN_AddTxMessage(&hcan, &TxMessage, data, &TxMailbox) is HAL_OK\r\n"); }
}
void CAN1_Send(uint8_t* cdata)
{
uint32_t TxMailbox;
TxMessage.IDE = CAN_ID_STD; //设置ID类型
TxMessage.StdId = 0x111; //设置ID号
TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧
TxMessage.DLC = 8; //设置数据长度
if (HAL_CAN_AddTxMessage(&hcan, &TxMessage, cdata, &TxMailbox) != HAL_OK)
{
Error_Handler();
}
}
/*******************
CAN启动函数
*******************/
void CAN_Start_Init(void)
{
if (HAL_CAN_Start(&hcan) != HAL_OK)
{
Error_Handler();
}
else{ printf("HAL_CAN_Start(&hcan) is HAL_OK\r\n"); }
/* 3. Enable CAN RX Interrupt */
if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {
Error_Handler();
}
else{ printf("HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) is HAL_OK\r\n"); }
}
/* USER CODE END 1 */
三、main.c文件配置
int main(void)
{
/* USER CODE BEGIN 1 */
/* 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();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
CANFilter_Config();
CAN_Start_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
CAN1_Send_Test();
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
四、串口打印结果:
五、本文对应代码分享:
https://download.csdn.net/download/qq_45854134/88522530