STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)

本篇详细的记录了如何使用STM32CubeMX配置 STM32F103C8T6 的硬件CAN接口与另一个开发板之间通信。

1.硬件设计

STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第1张图片
我这里使用的TJA1050T作为CAN通信收发器,连接f103的PA11,PA12两个管脚,分别作为接收和发送管脚,CAN收发器的H和L之间需要加120欧姆电阻用来做阻抗匹配。

2.Cubemx配置CAN

先选择芯片,我这里用的是stm32f103c8t6STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第2张图片
我这里用的是J-Link,所以要选择Serial Wire,使用DIO和CLK两个管脚下载程序
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第3张图片

接着在RCC中设置时序,我使用的是外部时钟,
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第4张图片
CAN收发使用的是PCLK1,这里使用外部时钟倍频后,PCLK1的时钟频率为36M
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第5张图片
接着配置CAN外设
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第6张图片
先设置CAN通信波特率,我们的目标通信波特率是500KHz,分频系数选择6,那么设一个未知数X,X=6M/500K,那么X=12,因此,BS1+BS2+SJW=12,最终我们会得到BS1,BS2,以及SJW的值
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第7张图片
开启CAN接收中断CAN RX0
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第8张图片

接着设置串口一用于单片机在接收到数据后将数据发送到上位机,默认波特率是115200就可以
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第9张图片
最后设置工程
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第10张图片
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第11张图片
3.编写程序
总体程序的流程图如下STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第12张图片
我们这里对这些设备不做任何过滤,先对过滤器进行配置,放在CAN.C文件中

 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();
       }

}

然后在CAN.C文件中定义接收和发送消息变量:
static CAN_TxHeaderTypeDef TxMessage; //CAN发送的消息的消息头
static CAN_RxHeaderTypeDef RxMessage; //CAN接收的消息的消息头
在CAN.C最后编写CAN接收中断函数:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    uint8_t  data[8];
    HAL_StatusTypeDef	status;
    
    if (hcan == hcan) {	
        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("<---\r\n");
            
        }
    }
}

编写CAN发送测试数据函数

void CAN1_Send_Test()
{
    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();
     }	
}

编写开启CAN函数

void CAN_Start_Init()
{
  if (HAL_CAN_Start(&hcan) != HAL_OK) 
    {
        Error_Handler();
     }

    
    /* 3. Enable CAN RX Interrupt */
    if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) !=  HAL_OK) {
        Error_Handler();
    }
}

重置printf函数
在main.c中添加#include"stdio.h"

//使用printf
int fputc(int ch,FILE *f)
{
    uint8_t temp[1]={ch};
    HAL_UART_Transmit(&huart1,temp,1,2);
}

接着在main函数中将函数开启,

  MX_CAN_Init();//can初始化
  MX_USART1_UART_Init();
  CANFilter_Config();
  CAN_Start_Init();
  CAN1_Send_Test(); 

给第二块F103C8T6下载程序时,把Send发送函数中,将ID号进行修改,
这个工程中容易出现错误的地方就在发送函数中,HAL_CAN_AddTxMessage(&hcan, &TxMessage, data, &TxMailbox),第四个参数需要自己定义一个32位数,不然的话程序会陷入死循环,我们可以在这个函数的定义中看到关于这个属性的介绍,这个参数是CAN在发送完一帧数据后返回的值,因此需要自己定义一个变量来存放。
STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)_第13张图片
程序参考了Mculover666这位博主的文章STM32CubeMX | 36 - 使用CAN总线进行双板通信(TJA1050)并进行了修改,最终实现了双板通信以及三板和四板通信

你可能感兴趣的:(STM32,stm32,物联网,嵌入式硬件)