STM32开发,移植修改官方HAL例程,实现串口Printf打印功能

STM32开发,移植修改官方HAL例程,实现串口printf打印功能

  • 1 概述
    • 1.1 资源概述
    • 1.2 实现功能
    • 1.3 移植原因
  • 2 软件适配工作
    • 2.1 STM芯片的命名规则
    • 2.2 官方例程下载
    • 2.3 官方开发板简述
  • 3. 软件修改工作
    • 3.1 文件夹去掉只读属性
    • 3.2 软件修改
    • 3.3程序流程图分析
  • 4 实验结果
  • 5 补充说明
    • 5.1 Readme文档
    • 5.2轮询方式printf函数重定义
    • 5.3中断方式方式串口发送数据
    • 5.4DMA方式串口发送数据
    • 5.5 main()函数写法

1 概述

1.1 资源概述

开发板:正点原子STM32F103 Nano开发板
CUBEMX版本:1.3.0
MDK版本:5.23
主控芯片型号:STM32F103RBT6
正点原子开发板

1.2 实现功能

移植官方例程文件,适当修改,在开发板上实现串口功能,并在电脑上位机上实现输出字符串。

1.3 移植原因

正点原子提供的HAL例程里边自带usart/sys/delay三个由正点原子开发的库函数,但是这几个库函数并非HAL函数,而是用标准函数或者直接操作寄存器实现。因此想完全通过HAL函数实现串口功能,充分了解串口的实现过程。官方例程写的非常好,逻辑结构严谨,有各种错误处理机制,特别适合移植和学习。

2 软件适配工作

2.1 STM芯片的命名规则

首先我们了解下STM32的命名规则,如下图,最后两位是封装和温度信息,如果前面的字母数字相同,那么芯片的架构资源就是完全一样,软件就能通用。正点原子的开发板是STM32F103RBT6,我们只要找到STM32F103RB的软件就能适配。
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第1张图片

2.2 官方例程下载

ST官方提供非常详细的官方例程,我们登陆ST官网搜索到F103的例程资源,此安装包同时为CUBEMX的资源包。
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第2张图片

2.3 官方开发板简述

打开文件夹,一级一级进入菜单,可以看到project文件夹,这个文件夹即为官方例程库,我们进入到UART文件夹,在进入选择STM32F103RB-Nucleo。这个Nucleo是ST官方提供的开发板。如下图,官网可以下载到全套的原理图,PCB,BOM等文件。此开发板集成STLINK V2,但是外设资源只有一个LED灯和一个按键,连高速晶振都没有,不能使用HSE时钟。有预留位置,可以自行购买焊接。此开发板淘宝价格大概80元。单板芯片和正点原子的开发板芯片相同,均为STM32F103RB,可以借用官方例程进行修改移植到正点原子开发板上。
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第3张图片
我们使用MDK软件进行开发,打开下述文件夹,打开工程文件。en.stm32cubef1(1.8.0)\STM32Cube_FW_F1_V1.8.0\Projects\STM32F103RB-Nucleo\Examples\UART\UART_Printf\MDK-ARM,
打开工程文件后的界面如下:
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第4张图片
例程使用的是内部的高速时钟HSI,配置为64MHz。我们也可以修改软件相关时钟配置,从而支持外部高速晶振,同时也可以将频率设置为最高的72MHz。
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第5张图片

3. 软件修改工作

3.1 文件夹去掉只读属性

在修改前,我们需要将文件夹属性只读去掉,否则打开工程后,很多文件上方会出现一把锁
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第6张图片
被锁住的文件将不能进行编辑,代码无法进行修改。
锁住的文件

3.2 软件修改

NUCLEO开发板LD2灯对应的GPIO是PB13,正点原子的LED0是PC0,因此我们需要将软件设置里的PB13改为PC0。下图是官方开发板LED部分原理图。当然不改没关系,这里的灯只是用来指示串口收发成功状态用的,如果有错误,LED灯将会亮起。
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第7张图片
修改GPIO口的定义

#define LED2_PIN                         GPIO_PIN_0 //这里需要改为端口0,正点原子是PC0
#define LED2_GPIO_PORT                   GPIOC//这里需要改为GPIOC,正点原子是PC0

官方例程LED是输出高有效点亮,正点原子开发板是输出低有效点亮,因此我们需要将例程中所有的LED灯的RESET改为SET,这里不一一例出。

/* Reset PIN to switch off the LED */
HAL_GPIO_WritePin(LED_PORT[Led],LED_PIN[Led], GPIO_PIN_SET);//这里需要将设为SET,正点原子开发板是输出低有效

同理SET改为RESET,这里不一一例出。

void BSP_LED_On(Led_TypeDef Led)
{
  HAL_GPIO_WritePin(LED_PORT[Led], LED_PIN[Led], GPIO_PIN_RESET); //这里需要将设为RESET,正点原子开发板是输出低有效
}

在main主函数中,需要将奇校验改为无校验,否则在PC机上的串口将会出现乱码,即使上位机设置了奇校验。原因未知,请各位知情的朋友评论留言给我。

 UartHandle.Init.Parity     = UART_PARITY_NONE; //需要设为无校验,否则在串口调试助手上显示乱码(即使助手上设置了奇偶校验)

3.3程序流程图分析

main.c文件程序流程图如下,每一个函数均有错误处理机制,以及错误后的提醒(将LED2灯点亮)
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第8张图片

4 实验结果

按一次开发板的复位按键,可以在上位机上出现对应的信息,main函数只执行一次。我们也可以将printf函数写在while(1)中,实现多次打印。
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第9张图片
这个XCOM串口调试助手在WIN10下容易出现崩溃停止响应,这里推荐WIN10官方商店的一个串口调试助手,稳定不崩溃好用。如下图:
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第10张图片

5 补充说明

5.1 Readme文档

在使用官方例程时,里边有一个Readme文档,是整个例程的说明书,写的很详细,有助于我们充分理解官方的程序。建议各位动手移植程序前先看下这个文档。
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第11张图片

5.2轮询方式printf函数重定义

以串口1为例代码如下

int fputc(int ch, FILE *f)  //轮询方式,超时机制,输出到串口函数重定义
{  	
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, sizeof(ch), 0xFFFF);
  return ch;
}
/*HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)*/
int fgetc(FILE *f)   //轮询方式,超时机制,接收到串口函数重定义
{
	uint8_t ch;	
	HAL_UART_Receive(&huart1, (uint8_t *)&ch, sizeof(ch), 0xFFFF);	
	return ch;
}

5.3中断方式方式串口发送数据

以串口1为例代码如下
1,定义要发送的数据。

uint8_t string_it[]="Int:hello world!";

2,调用串口发送函数。

HAL_UART_Transmit_IT(&huart2, (uint8_t *)string_it, sizeof(string_it));

5.4DMA方式串口发送数据

以串口1为例代码如下
1,定义要发送的数据。

uint8_t string_dma[]="DMA:hello world!";

2,调用串口发送函数。

HAL_UART_Transmit_DMA(&huart2, (uint8_t *)string_dma, sizeof(string_dma));

三者可以混用,如下图所示

	HAL_UART_Transmit_DMA(&huart2, (uint8_t *)string_dma, sizeof(string_dma));

	HAL_Delay(1);

	printf("\r\nPoling:hello world!\r\n");

	HAL_UART_Transmit_IT(&huart2, (uint8_t *)string_it, sizeof(string_it));

则输出的结果是
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第12张图片
如果将Hal_delay(1)函数注释掉,将只会输出DMA信息,如下图
STM32开发,移植修改官方HAL例程,实现串口Printf打印功能_第13张图片

5.5 main()函数写法

①:printf 可以输出一个任意的字符串,还可以有参数,而putchar只能输出一个字符。
②:printf 的返回值是正常输出的参数的数量,而 putchar 则是是否正常输出

ch=getchar();//输入

putchar(ch);//输出	

printf(ch);//输出

你可能感兴趣的:(STM32开发学习笔记)