STM32学习笔记6:CAN的应用(三机通信)

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 BEGINUSER 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;
}

5.成果展示

在这里插入图片描述

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值