IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F103 CAN通讯实操 -> 正文阅读

[嵌入式]STM32F103 CAN通讯实操

目的:学习使用STM32CubeIDE进行CAN通讯编程学习;

准备条件:STM32F103ZET6开发板,PA11 PA12用于CAN + TJA1040,USB-CAN适配器1个;

操作流程:

第一步:使用cubeIDE自动生成代码;

第二步: 编辑代码,loopback条件下工作,中断接收CAN消息;

第三步:连接USB-CAN适配器,进行通讯测试。

详细操作步骤如下:

Step1:cubeIDE 生成project;File\New\STM32 Project;

Step2: Part Number中输入 STM32F103ZE, 选择LQFP144 package;

Step3:配置晶振和调试方法(PinOUT&Configuration)

Step4:配置时钟Clock Configration,确认APB1 peripheral clocks(MHz) = 16

bxCAN 对应的时钟为:APB1外设时钟; 见《STM32F10xx中文参考手册》“2.3 存储器映像” page28/547;

Step5: 配置bxCAN的波特率为100K

Step6:配置bxCAN的接收中断

Step7:配置读取中断的优先级别为15; USB low priority or CAN RX0 interrupts, preemption Priority =15;

Step8:生成代码后,在main.c中添加bxCAN初始化代码:

static?void?MX_CAN_Init(void)

{



??/* USER CODE BEGIN CAN_Init 0 */



??/* USER CODE END CAN_Init 0 */



??/* USER CODE BEGIN CAN_Init 1 */



??/* USER CODE END CAN_Init 1 */

??hcan.Instance?= CAN1;

??hcan.Init.Prescaler?= 16;

??hcan.Init.Mode?= CAN_MODE_NORMAL;

??hcan.Init.SyncJumpWidth?= CAN_SJW_1TQ;

??hcan.Init.TimeSeg1?= CAN_BS1_6TQ;

??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 */

???CAN_FilterTypeDef?_CAN_FilterTypeDef;

_CAN_FilterTypeDef.FilterBank?= 0; // filter 0

_CAN_FilterTypeDef.FilterMode?= CAN_FILTERMODE_IDMASK; // mask mode

_CAN_FilterTypeDef.FilterScale?= CAN_FILTERSCALE_32BIT;

_CAN_FilterTypeDef.FilterIdHigh?= 0;

_CAN_FilterTypeDef.FilterIdLow?= 0;

_CAN_FilterTypeDef.FilterMaskIdHigh?= 0;

_CAN_FilterTypeDef.FilterMaskIdLow?= 0; // set mask 0 to receive all ??can id

_CAN_FilterTypeDef.FilterFIFOAssignment?= CAN_RX_FIFO0; // assign to fifo0

_CAN_FilterTypeDef.FilterActivation?= CAN_FILTER_ENABLE;// enable can filter

_CAN_FilterTypeDef.SlaveStartFilterBank?= 27;

if(HAL_CAN_ConfigFilter(&hcan,&_CAN_FilterTypeDef) != HAL_OK)

Error_Handler();

if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)

Error_Handler();

if(HAL_CAN_Start(&hcan) != HAL_OK)

Error_Handler();

??/* USER CODE END CAN_Init 2 */



}

Step9:生成代码后,在main.c中添加bxCAN读、写、中断接收代码:

/* USER CODE BEGIN 0 */
#define Tx_Error 3
#define Rx_Error 2
#define Rx_OK 0
CAN_TxHeaderTypeDef Tx_pHeader;
/*
 * @brief: CAN Send Message.
 * @param: "TxData[]" stored the message of ready to send, which length must between 0 and 8.
 * @param: "length" stored the number of the data (one data is 8 bit) of ready to send.
 * @retval: Tx_Error: send error; other: the mailbox which has been used, this parameter can be a CAN_TX_MAILBOX0,
 * 																						   CAN_TX_MAILBOX1,
 * 																						   CAN_TX_MAILBOX2.
 */
uint32_t CAN_TX_Message(uint8_t TxData[], uint8_t length)
{

	uint32_t TxMailboxNumber = 0x00000000U;    // 存储本次发所使用邮箱的邮箱号

	Tx_pHeader.StdId = 0x030;    // 以此ID发
	Tx_pHeader.ExtId = 0x0000;    // 扩展ID(此处无用)
	Tx_pHeader.IDE = CAN_ID_STD;    // 标准
	Tx_pHeader.RTR = CAN_RTR_DATA;    // 数据
	Tx_pHeader.DLC = length;    // 发数据的长度
	Tx_pHeader.TransmitGlobalTime = DISABLE;

	if(HAL_CAN_AddTxMessage(&hcan, &Tx_pHeader, TxData, &TxMailboxNumber) != HAL_OK)
	{
		return Tx_Error;
	}
	return TxMailboxNumber;
}

CAN_RxHeaderTypeDef Rx_pHeader;
/*
 * @brief: CAN Receive Message.
 * @param: "RxData[]" will store the message which has been received, which length must between 0 and 8.
 * @retval: receive status.
 */
uint32_t CAN_RX_Message(uint8_t RxData[])
{

	uint8_t aData[8];    // 缓存接收到的信息

	Rx_pHeader.StdId = 0x000;	// 接收ID(此处无用,can接收有的ID号)
	Rx_pHeader.ExtId = 0x0000;
	Rx_pHeader.IDE = CAN_ID_STD;	// 接收标准
	Rx_pHeader.DLC = 8;		// 接收8bit数据
	Rx_pHeader.RTR = CAN_RTR_DATA;	// 接收数据
	Rx_pHeader.FilterMatchIndex = 0;	// 使用0号过滤器
	Rx_pHeader.Timestamp = 0;

	if(HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &Rx_pHeader, aData) != HAL_OK)
	{
		return Rx_Error;
	}
	else
	{
		// 取出接收到的信息
		for(uint8_t i = 0; i<Rx_pHeader.DLC; i++)
		{
			RxData[i] = aData[i];
		}
		return Rx_OK;
	}
}

uint8_t RxData[8] = {0};    // 缓存接收到的信息
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    // 判断是哪路的CAN发生了中
	if(hcan->Instance == CAN1)
	{
		if(CAN_RX_Message(RxData) != Rx_OK)
		{
            // 接收信息失败
			printf("MCU Received CAN Data ERROR!!!");
            printf("\n\r");
			printf("\n\r");
		}
		else
		{
            // 接受信息成功,处理数
			printf("MCU Received CAN Data: ");
			for(uint8_t i = 0; i<8; i++)
			{
				printf("%d ", RxData[i]);
			}
            printf("\n\r");
			printf("\n\r");
		}
	}
}
uint8_t TxData[8] = {0};    // 缓存待发送的信息
uint8_t length = 0x00;    // 待发送信息的长度
/* USER CODE END 0 */

Step10:生成代码后,在main.c中添加main函数中添加主代码:

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();
  /* USER CODE BEGIN 2 */
  	TxData[7] = 0x1a;    // 给定待发送的信息
    TxData[6] = 0x1b;
    TxData[5] = 0x1c;
    TxData[4] = 0x1d;
    TxData[3] = 0x1e;
    TxData[2] = 0x1f;
    TxData[1] = 0x10;
    TxData[0] = 0x11;
    length = 0x08;    // 更新待发送信息的数据长度
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  if (CAN_TX_Message(TxData, length) == Tx_Error)    // 轮询方式发CAN信息
	 	  {
	 		  Error_Handler();
	 	  }
	 	  HAL_Delay(500);    // 延时0.5
  }
  /* USER CODE END 3 */
}

结果:调试成功后,可以在usb can收到消息

使用注意事项:

stm32的bxCAN配置和使用流程在cubeide软件中如下:

Step1: ioc文件里图形化使能can并配置工作时钟、波特率、工作模式、中断优先级;

Step2:自动生成代码后,在can.c文件里添加滤波器的配置并使能FIFO中断;

Step3:在MX_CAN_Init初始化完毕后启动can,才能发送信息;

Step4:在main.c文件下的main()外用户自定义中断回调函数。

常见错误点总结:

  1. 没有启动can,can是无法发送信息、接收不到信息的。对应库函数HAL_CAN_Start。
  2. 没有使能FIFO中断,can是不会中断的。
  3. 回调函数的函数名使用错误(因为有多个用途不同的函数名),can中断后不调用该函数。对应函数名:HAL_CAN_RxFifo0MsgPendingCallback;
  4. CAN调试的时候,可以先使用loopback模式,进行发送接收测试,没问题后,再设置为normal模块,连接USB-CAN适配器,进行实际测试;
  5. 波特率设置中的 Time Quanta Bit Segmenet1 和Time Quanta Bit Segmenet 2,尽量大于2,否则会影响发送和接收的稳定性。
  6. 希望自己能记住,同时看到的人也有帮助。
  7. 本文的源代码下载链接:https://download.csdn.net/download/qq_23313467/86730136

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:58:04  更:2022-10-08 21:00:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:33:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码