目录
1.设备硬件
三个STM32F407ZGT6开发板
三个TJA1050 CAN收发器
三个ST-LINK V2烧录器(一个也行就是比较麻烦要一直换板子烧录,个别需要找厂家要升级步骤才能使用)
三个CH340串口模块(需要找产家要驱动程序)
若干杜邦线(公对公的和母对母的)
2.设备软件
STM32CubeMX
keil μVision5
串口调试工具ATK-XCOM
3.CubeMX设计
1.创建工程
打开STM32CubeMX,点击下图所指的按钮进入创建工程界面。
按照下图指示选择单片机型号进行创建项目。
2.配置参数
配置时钟
配置烧录器模式
配置CAN1
依照下图的参数进行配置CAN1,首先要将上述的时钟配置好才能配置CAN1,配置CAN1 需要考虑时钟参数他的波特率公式为baud=时钟APB1/[(BS1+BS2+JW)*Psc]
相当于baud = 42MHz/[(4+2+1)*12]=500Kbit/s
也就是说1bit
需要2000ns
时间传输。
按照下图勾选CAN1的中断
配置串口
配置串口也是老生常谈了,这里就不细说了,要是想知道就去找我之前的详细串口介绍视频
项目管理配置
依照下图进行配置
勾选下图的位置是为了更好查看.c/.h
文件,勾选完就可以生成代码
点击生成后弹出以下窗口选择图中所指的按钮,打开项目
4.keil5代码书写
注意:所有代码均需要在USER CODE BEGIN
和USER CODE END
之间进行写入否则下次修改CubeMX的配置时会在更新代码的时候删除不在该区域之间的代码。
main.c
头文件添加
#include <stdio.h>
main函数外的函数书写
CAN_TxHeaderTypeDef TXHeader;
CAN_RxHeaderTypeDef RXHeader;
uint8_t TXmessage[8] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
uint8_t RXmessage[8];
uint32_t pTxMailbox = 0;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)//
{
if(hcan->Instance==CAN1)
{
HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&RXHeader,RXmessage);
printf("%02x\r\n",RXHeader.StdId);
}
}
HAL_StatusTypeDef CAN_SendData(uint16_t msg_ID,CAN_HandleTypeDef *hcan)
{
TXHeader.StdId=msg_ID;
TXHeader.DLC=8;
TXHeader.IDE=CAN_ID_STD;
TXHeader.RTR=CAN_RTR_DATA;
TXHeader.TransmitGlobalTime = DISABLE;
if(HAL_CAN_AddTxMessage(hcan,&TXHeader,TXmessage,&pTxMailbox)==HAL_OK)
{
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
while循环外的代码为以下内容
//烧录第一个板将以下注释解除,注释以下内容
uint8_t Recdata[4];
printf("\r\n----- CAN Test Board #1 ----- \n");
if(CAN_Filter_Set(0x111)==HAL_OK)
printf("Set filter success!");
//烧录第二个板将注释解除,注释上下内容
// printf("\r\n----- CAN Test Board #2 ----- \n");
// if(CAN_Filter_Set(0x123)==HAL_OK)
// printf("Set filter success!");
//烧录第三个板将以下注释解除,注释以上内容
// printf("\r\n----- CAN Test Board #3 ----- \n");
// if(CAN_Filter_Set(0x456)==HAL_OK)
// printf("Set filter success!");
while循环内的代码为以下内容
uint16_t msg_ID;
HAL_UART_Receive(&huart1,Recdata,sizeof(Recdata),1000);
if(Recdata[0] == '2')
{
msg_ID = 0x123;
if(CAN_SendData(msg_ID,&hcan1) == HAL_OK)
{
printf("send test success for 2 borad!\r\n");
}
}
else if(Recdata[0] == '3')
{
msg_ID = 0x456;
if(CAN_SendData(msg_ID,&hcan1) == HAL_OK)
{
printf("send test success for 3 borad!\r\n");
}
}
HAL_Delay(500);
can.c
头文件添加
#include <stdio.h>
HAL_StatusTypeDef CAN_Filter_Set(uint16_t Rec_ID)
{
CAN_FilterTypeDef canFilter;
canFilter.FilterActivation = ENABLE; //enable filter
// Configure the CAN Filter
canFilter.FilterBank = 0; //filter group number
canFilter.FilterMode = CAN_FILTERMODE_IDMASK; //mask ID mode
canFilter.FilterScale = CAN_FILTERSCALE_32BIT; //32bit
canFilter.FilterFIFOAssignment = CAN_RX_FIFO0; //FIFO0
//only receive stdID is Odd frames
canFilter.FilterIdHigh = Rec_ID<<5; //CAN_FxR1 high 16 bit
canFilter.FilterIdLow = 0x0000; //CAN_FxR1 low 16 bit
canFilter.FilterMaskIdHigh = 0xffff; //CAN_FxR2 mask high 16 bit
canFilter.FilterMaskIdLow = 0x0000; //CAN_FxR2 mask low 16 bit
if(HAL_CAN_ConfigFilter(&hcan1, &canFilter)!=HAL_OK) //Init filter
{
Error_Handler();
}
if(HAL_CAN_Start(&hcan1) != HAL_OK)//open can
{
Error_Handler();
}
if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) //open Receive Mailbox Interrupt
{
Error_Handler();
}
return HAL_OK;
}
can.h
HAL_StatusTypeDef CAN_Filter_Set(uint16_t Rec_ID);
usart.c
头文件添加
#include <stdio.h>
主题内容添加
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,1000);
return ch;
}