本篇,我们来到很基础的串口通讯,串口主要常用于程序调试。
查看开发板手册得知,ST—Link的虚拟串口,对应UART4(PD0、PD1)
我们新建一个空白的工程:
开启UART4(习惯用APPLI),配置好IO口,UART4默认端口不是PD0/PD1,需要在GPIO重新设置。
设置好波特率:9600
开启中断:
然后生成代码:
可以看到main.c中都设置好了参数。
UART串口收发数据,有4种方式:
1. 轮询:阻塞式,比较占用CPU资源
2. 中断:非阻塞式,需要CPU参与,解放CPU
3. DMA:非阻塞式,无需CPU参与
4. 基于RTOS嵌入式操作系统,高端玩法
本例将演示:轮询和中断方式
1. 轮询发送
添加头文件及定义字符串:
#include "stm32h7rsxx_hal_uart.h"
unsigned char UART_BUF[] = "大江东去,浪淘尽,千古风流人物。故垒西边,人道是:三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间、樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。";
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Update SystemCoreClock variable according to RCC registers values. */
SystemCoreClockUpdate();
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_UART4_Init();
/* USER CODE BEGIN 2 */
//HAL_UART_Receive_IT(&huart4, UART_BUF1,sizeof(UART_BUF1));
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(1000);
HAL_UART_Transmit(&huart4, UART_BUF, sizeof(UART_BUF),100);
}
/* USER CODE END 3 */
}
在while(1)函数中加入:
HAL_Delay(1000);
HAL_UART_Transmit(&huart4, UART_BUF, sizeof(UART_BUF),100);
运行结果:
2. 中断收发
添加头文件及定义字符串(接收到的数据放在这个数组中):
#include "stm32h7rsxx_hal_uart.h"
unsigned char UART_BUF1[45];
main.c函数添加接收中断,同时while(1)函数为空白。
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Update SystemCoreClock variable according to RCC registers values. */
SystemCoreClockUpdate();
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_UART4_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart4, UART_BUF1,sizeof(UART_BUF1));
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
}
核心是这句:
HAL_UART_Receive_IT(&huart4, UART_BUF1,sizeof(UART_BUF1));
stm32h7rsxx_it.c
中添加串口接收中断函数,并将收到的数据发送出去。
核心代码为:
extern uint8_t UART_BUF1[45];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit_IT(&huart4,UART_BUF1,sizeof(UART_BUF1)); //将接收到的数据发送出去
HAL_UART_Receive_IT(&huart4, UART_BUF1,sizeof(UART_BUF1)); //再次开启接收中断
}
运行结果为:
本次的分享就到这里。
题外话:看到有的坛友在分享STM32H7S78-DK的开发经验时,对每个模块(如GPIO、UART……),深钻寄存器,每个细节都仔仔细细,
深感佩服的同时,发表点不同的看法:
STM32H7S78-DK这么强大的开发板,拥有如此便利的图形化配置界面CubeMX,以及强大的HAL库。
个人认为要想快速学习,高效应用,最好适应CubeMX+HAL的方式,直接钻研寄存器感觉更适用于8位、16位单片机,硬件资源有限,直接操作寄存器效率更高。
而我们的STM32H7S78-DK,这么强大的硬件以及软件配套,必要性就不大了。
600MHz, 64KB Bootflash, 620KB SRAM, with DSP, cache, USB HS PHY, NeoChrom GPU, TFT-LCD.