STM32F103C8T6配置CAN 通信(仅自学笔记)

前期准备 

硬件:

两个STM32F103C8T6  两个can模块  usb转TTL 

软件:

cubeide

生成工程

打开Cubeide我用的是1.9.0版本

首先新建一个项目

 之后选择MCU型号STM32F103C8T6

 最后输入项目名称点击完成

 项目新建完成后开始配置引脚

先配置时钟

1.

2.

 3.

 然后回到引脚配置界面配置下载方式

 最后配置CAN 和UART 

uart选择好后其他默认配置就可以

 CAN

CAN波特率计算方法 

波特率=APB1 peripheral clocks/prescaler/(TQ1+TQ2+SJW)

以STM32F103C8T6为例

如设置波特率为500K

36M/4/(9+8+1)=500K

为了方便看程序是否可以正常运行配置PC13(LED引脚)

 配置好后选择Project Manager

生成相应的.C文件 

配置好后即可生成代码

 

对项目属性进行设置

中文乱码情况

右键项目->属性

 文本编码选择GBK格式

 点击应用并关闭

浮点型不能输出的情况

 开始编写代码

 首先先对串口printf重映射编写

打开usart.c文件

在这个位置添加此代码

#include "stdio.h"

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
    HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
    return ch;
}

main.c添加此代码

      printf("asd\r\n");
	  printf("汉字测试\r\n");
	  printf("整型测试%d\r\n",123);
	  printf("浮点型测试%f\r\n",12.333);
	  HAL_Delay(1000);

编译工程并下载 打开串口助手可以看到能正常输出

 接下来对CAN进行配置

 can过滤器代码

过滤器暂时先不过滤 全部接收

在CAN.C  /* USER CODE BEGIN 0 */下添加此代码

#include "usart.h"
extern CAN_TxHeaderTypeDef Can_Tx;
extern uint8_t Txdata[8];
void CAN_User_Init(CAN_HandleTypeDef* hcan )   //用户初始化函数
{
  CAN_FilterTypeDef  sFilterConfig;
  HAL_StatusTypeDef  HAL_Status;
  sFilterConfig.FilterActivation = ENABLE;  	//激活过滤器
  sFilterConfig.FilterBank = 1;                       //过滤器1
  sFilterConfig.FilterMode =  CAN_FILTERMODE_IDMASK;  //设为掩码模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;    //设为32位
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;    //接收到的报文放入到FIFO0中
  sFilterConfig.FilterIdHigh = 0;   //基本ID放入到STID中
  sFilterConfig.FilterIdLow  = 0;
  sFilterConfig.FilterMaskIdHigh =0;
  sFilterConfig.FilterMaskIdLow  =0;
  sFilterConfig.SlaveStartFilterBank  = 0;

  HAL_Status=HAL_CAN_ConfigFilter(hcan, &sFilterConfig);
  HAL_Status=HAL_CAN_Start(hcan);  //开启CAN

  if(HAL_Status!=HAL_OK){
//	printf("开启CAN失败\r\n");
 }
 HAL_Status=HAL_CAN_ActivateNotification(hcan,CAN_IT_RX_FIFO0_MSG_PENDING);
 if(HAL_Status!=HAL_OK){
	//printf("开启挂起中段允许失败\r\n");
  }
}

/*
 发送命令函数
 StdId 			标准帧ID
 ExtId 			扩展帧ID  当标志位 IDE为CAN_ID_STD时 扩展帧无效
 IDE 			扩展帧标志位  CAN_ID_STD为标准ID CAN_ID_EXT为使用扩展ID
 RTR  			0(CAN_RTR_DATA)为数据帧 1(CAN_RTR_REMOTE)为远程帧
 DLC  			数据长度
*/
void sendOrder(uint32_t StdId,uint32_t ExtId,uint8_t IDE,uint8_t  RTR, uint8_t DLC)
{
	uint32_t pTxMailbox = 0;

	Can_Tx.StdId = StdId;//标准ID
	Can_Tx.ExtId = ExtId;//扩展ID
	Can_Tx.IDE = IDE;//CAN_ID_STD为标准ID CAN_ID_EXT为使用扩展ID
	Can_Tx.RTR = RTR;					//0(CAN_RTR_DATA)为数据帧 1(CAN_RTR_REMOTE)为远程帧
	Can_Tx.DLC = DLC;					//数据长度
	printf("TX ID:0x%X\r\n",ExtId);
	printf("TX DATA:%02X%02X%02X%02X%02X%02X%02X%02X\r\n",Txdata[0],Txdata[1],Txdata[2],Txdata[3],Txdata[4],Txdata[5],Txdata[6],Txdata[7]);
	HAL_CAN_AddTxMessage(&hcan,&Can_Tx,Txdata,&pTxMailbox);

}
void sendmessage(uint32_t StdId,uint32_t ExtId,uint8_t IDE,uint8_t  RTR, uint8_t DLC,float send_data)
{
	uint32_t pTxMailbox = 0;
	uint8_t i;
	Can_Tx.StdId = StdId;//标准ID
	Can_Tx.ExtId = ExtId;//扩展ID
	Can_Tx.IDE = IDE;//CAN_ID_STD为标准ID CAN_ID_EXT为使用扩展ID
	Can_Tx.RTR = RTR;					//0(CAN_RTR_DATA)为数据帧 1(CAN_RTR_REMOTE)为远程帧
	Can_Tx.DLC = DLC;					//数据长度
	//将浮点数转化成4个字节存在tdata[4]----tdata[7]中
	send_data=send_data*100;
		Txdata[4] = (int)send_data&0x00ff;
		Txdata[3] = (int)send_data>>8;
		Txdata[1] = 0x01;
		printf("TX ID:0x%X\r\n",Can_Tx.ExtId);
	printf("TX DATA:%02X%02X%02X%02X%02X%02X%02X%02X\r\n",Txdata[0],Txdata[1],Txdata[2],Txdata[3],Txdata[4],Txdata[5],Txdata[6],Txdata[7]);
	HAL_CAN_AddTxMessage(&hcan,&Can_Tx,Txdata,&pTxMailbox);
}

在can.h/* USER CODE BEGIN Prototypes */下

添加此代码

void CAN_User_Init(CAN_HandleTypeDef* hcan );
void sendmessage(uint32_t StdId,uint32_t ExtId,uint8_t IDE,uint8_t  RTR, uint8_t DLC,float send_data);
void sendOrder(uint32_t StdId,uint32_t ExtId,uint8_t IDE,uint8_t  RTR, uint8_t DLC);

CAN中断代码编写

stm32f1xx_it.c文件/* USER CODE BEGIN Includes *下

添加

#include "can.h"
#include "gpio.h"
#include "usart.h"

/* USER CODE BEGIN EV */下添加

extern CAN_RxHeaderTypeDef Can_Rx;
extern uint8_t Rxdata[8] ;
extern float rxdata;
uint8_t can_rx_finish_flag;//接收完成标志位

/* USER CODE BEGIN 1 */下添加

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* hcan1)
{
	uint8_t i;
	printf("***********************************************\r\n");
	HAL_CAN_GetRxMessage(&hcan,CAN_RX_FIFO0,&Can_Rx,Rxdata);

			can_rx_finish_flag=1;
     printf("RX ID:0x%X\r\n",Can_Rx.ExtId);
	 printf("RX DATA: %02X%02X%02X%02X%02X%02X%02X%02X\r\n",Rxdata[0],Rxdata[1],Rxdata[2],Rxdata[3],Rxdata[4],Rxdata[5],Rxdata[6],Rxdata[7]);

}

main.c中

/* USER CODE BEGIN 0 */下添加

CAN_TxHeaderTypeDef Can_Tx;
CAN_RxHeaderTypeDef Can_Rx;
uint8_t Rxdata[8];//CAN接收缓冲区
uint8_t Txdata[8] = {0};//CAN发送缓冲区
extern uint8_t can_rx_finish_flag;//接收完成标志位

  /* USER CODE BEGIN 2 */下添加

 CAN_User_Init(&hcan);

 /* USER CODE BEGIN 3 */下添加

 if(can_rx_finish_flag==1)//接收完成
	  		{

	  			sendmessage(0x123,0x14550151,CAN_ID_EXT,0,8,26.2);
	  			can_rx_finish_flag=0;

	  		}

接收端主要代码已编写完成

发送端只需把

 /* USER CODE BEGIN 3 */下代码改成

                Txdata[0]=0x01;
                Txdata[1]=0x01;
		        Txdata[2]=0x04;
	  			sendOrder(0x123,0x13550151,CAN_ID_EXT,0,3);
                HAL_Delay(2000);
	  			

即可

到此STM32F103C8T6配置CAN 通信即可完成

实验现象是发送端每2秒发送一条命令 ,接收端收到后打印出接收到的数据 并返回一串数据

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值