STM32-NUCLEO-F411RE-USART_串口
STM32-NUCLEO-F411RE-USART_串口
- 串口基本原理
- 异步串行通信的特点
- 异步串行通信的两个关键点
- 异步串行通信的数据接收过程
- 串行内部寄存器结构框图
- 串行状态标志位
- 串囗初始化过程
- 一、配置时钟
- 二、配置调试模式
- 三、串口参数配置
- 四、生成 Keil 工程
- 代码部分
- UART结构体定义
- UART函数
- 1、串口发送/接收函数
- 2、串口中断函数
- 3、串口查询函数
- 主程序
- 七、实验效果
- 八、重定向 printf
使用STM32CubeMX生产初始化代码,底板硬件使用NUCLEO-F411RE开发板
串口基本原理
异步串行通信的特点
特点:数据传输以单个字符为单位,字符和字符之间的间隙任意,字符内部每一位持续的时间相同。收发双方没有专门的时钟信号,而是依靠事先约定的字符格式和通信速率来完成通信。
常用字符格式:1位起始位 8位数据位 无奇偶校验 1位停止位
波特率:每秒钟传送二进制数码的位数,以bit/s(bps)为单位
常用的波特率有:9600、19200、38400、57600和115200;
波特率为115200,表示每秒传输115200位,且每一位数据在数,据线上持续时间为Tbit=1/115200=8.68us。 波特率为9600时起始位长度为104.2us。
异步串行通信的两个关键点
异步串行通信的数据接收过程
串行内部寄存器结构框图
串行状态标志位
串囗初始化过程
一、配置时钟
开发板焊接了外部晶振,所以我 RCC(Reset and Cock Control) 配置选择了 Crystal/Ceramic Resonator(石英/陶瓷谐振器),配置完成后,右边的 Pinout view 里相关引脚就会被标绿。
外部高速时钟配置完成后,进入 Clock Configuration 选项,根据实际情况,将系统时钟配置为 96 MHz,配置步骤如下,最后按下回车,软件会自动调整分频和倍频参数。
二、配置调试模式
ST-Link 就是 Serial Wire 调试模式,一定要设置!!!
以前使用 M0 的芯片,不配置这个模式没出现问题,但现在这个型号,如果不配置 Serial Wire 模式,程序一旦通过 ST-Link 烧录到芯片中,芯片就再也不能被ST-Link 识别了。(后来我是通过 STMISP 工具烧录程序/擦除后才恢复正常的)
三、串口参数配置
串口为 USART1,按照下面步骤配置 USART1,将其设置为异步模式(Asynchronous),波特率 115200(默认),字长 8 Bits(默认),无校验(默认),停止位 1(默认),使能发送和接收(默认):
使能中断
四、生成 Keil 工程
设置 IDE 和 工程目录及名称:
将每种外设的代码存放到不同的 .c /.h 文件中,便于管理(不然都会被放到 main.c 中)。
代码部分
UART结构体定义
typedef struct __UART_HandleTypeDef
{USART_TypeDef *Instance; /*!< 串口寄存器的基地址定义 */UART_InitTypeDef Init; /*!< 串口初始化数据类型 */uint8_t *pTxBuffPtr; /*!< 串口发送缓冲区首地址 */uint16_t TxXferSize; /*!< 串口待发送数据个数 */__IO uint16_t TxXferCount; /*!< 串口发送数据计数器 */uint8_t *pRxBuffPtr; /*!< 串口接收缓冲区首地址 */uint16_t RxXferSize; /*!< 串口待接收数据个数 */__IO uint16_t RxXferCount; /*!< 串口接收数据计数器 */__IO HAL_UART_RxTypeTypeDef ReceptionType; /*!< 持续接收类型 */DMA_HandleTypeDef *hdmatx; /*!< 串口发送的DMA通道句柄定义 */DMA_HandleTypeDef *hdmarx; /*!< 串口接收的DMA通道句柄定义 */HAL_LockTypeDef Lock; /*!< 保护锁类型定义 */__IO HAL_UART_StateTypeDef gState; /*!< 串口全局状态和发送状态信息*/__IO HAL_UART_StateTypeDef RxState; /*!< 串口接收状态信息*/__IO uint32_t ErrorCode; /*!< 串口错误代码 */
} UART_HandleTypeDef;
UART函数
1、串口发送/接收函数
HAL_UART_Transmit();串口发送数据,使用超时管理机制
HAL_UART_Receive();串口接收数据,使用超时管理机制
HAL_UART_Transmit_IT();串口中断模式发送
HAL_UART_Receive_IT();串口中断模式接收
HAL_UART_Transmit_DMA();串口DMA模式发送
HAL_UART_Transmit_DMA();串口DMA模式接收
这几个函数的参数基本都是一样的,我们挑两个讲解一下
串口发送数据:
HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
功能:串口发送指定长度的数据。如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT)。
参数:
UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
*pData 需要发送的数据
Size 发送的字节数
Timeout 最大发送时间,发送数据超过该时间退出发送
举例: HAL_UART_Transmit(&huart1, (uint8_t *)ZZX, 3, 0xffff); //串口发送三个字节数据,最大传输时间0xffff
中断接收数据:
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
功能:串口中断接收,以中断方式接收指定长度数据。
大致过程是,设置数据存放位置,接收数据长度,然后使能串口接收中断。接收到数据时,会触发串口中断。
再然后,串口中断函数处理,直到接收到指定长度数据,而后关闭中断,进入中断接收回调函数,不再触发接收中断。(只触发一次中断)
参数:
UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
*pData 接收到的数据存放地址
Size 接收的字节数
举例: HAL_UART_Receive_IT(&huart1,(uint8_t *)&value,1); //中断接收一个字符,存储到value中
2、串口中断函数
HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断处理函数
HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //串口发送中断回调函数
HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); //串口发送一半中断回调函数(用的较少)
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //串口接收中断回调函数
HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
HAL_UART_ErrorCallback();串口接收错误函数
串口接收中断回调函数:
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
功能:HAL库的中断进行完之后,并不会直接退出,而是会进入中断回调函数中,用户可以在其中设置代码。
串口中断接收完成之后,会进入该函数,该函数为空函数,用户需自行修改
参数:
UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
举例: HAL_UART_RxCpltCallback(&huart1){ //用户设定的代码 }
串口中断处理函数
HAL_UART_IRQHandler(UART_HandleTypeDef *huart);
功能:对接收到的数据进行判断和处理 判断是发送中断还是接收中断,然后进行数据的发送和接收,在中断服务函数中使用
如果接收数据,则会进行接收中断处理函数
/* UART in mode Receiver ---------------------------------------------------*/if((tmp_flag != RESET) && (tmp_it_source != RESET)){ UART_Receive_IT(huart);}
如果发送数据,则会进行发送中断处理函数
/* UART in mode Transmitter ------------------------------------------------*/if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)){UART_Transmit_IT(huart);return;}
3、串口查询函数
HAL_UART_GetState(); 判断UART的接收是否结束,或者发送数据是否忙碌
举例:
while(HAL_UART_GetState(&huart4) == HAL_UART_STATE_BUSY_TX) //检测UART发送结束
主程序
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2022 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"uint8_t RxBuffer;
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, 1, 10); // 把收到的字节发送出去,10ms超时时间HAL_UART_Receive_IT(&huart1, (uint8_t *)&RxBuffer, 1); // 开启下一次串口中断}
}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
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_USART1_UART_Init();MX_USART2_UART_Init();/* USER CODE BEGIN 2 */HAL_UART_Receive_IT(&huart1, (uint8_t *)&RxBuffer, 1); // 开启下一次串口中断HAL_UART_Transmit(&huart1, "HAL_UART_Transmit test\r\n", 24, 0xffff); //发送字符串/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */HAL_UART_Transmit(&huart1, "hello world\r\n", 13, 0xffff);HAL_Delay(500);/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 4;RCC_OscInitStruct.PLL.PLLN = 96;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 4;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
七、实验效果
八、重定向 printf
在工程中添加下面代码,重定义 fputc
#include "usart.h"
#include <stdio.h>/* USER CODE BEGIN 0 */
int fputc(int ch,FILE *f)
{HAL_UART_Transmit(&huart1,(uint8_t *)&ch, 1, 0xFFFF);return ch;
}
/* USER CODE END 0 */
需要使用C语言函数
将前文示例代码中的 HAL_UART_Transmit() 替换成 printf() 将实现同样的功能
STM32-NUCLEO-F411RE-USART_串口相关推荐
- 如何让Arduino IDE支持你手里的STM32 nucleo开发板
Arduino IDE开发环境在默认情况下不支持STM32 NUCLEO开发板,只有通过添加附加开发板管理包才能使用.目前为止,只有一部分板子支持使用Arduino IDE开发环境进行开发,分别是 N ...
- STM32 Nucleo开发板入门(一)——概述
在实验室找到一块 STM32 的开发板,型号是STM32 Nucleo-L031K6.趁着十一假期,入门一下,顺便随便记点东西. NUCLEO-L031K6 | Mbedhttps://os.mbed ...
- stm32学习笔记----双串口同时打开时的printf()问题
stm32学习笔记----双串口同时打开时的printf()问题 最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其 ...
- STM32使用DMA发送串口数据
1.概述 上一篇文章<STM32使用DMA接收串口数据>讲解了如何使用DMA接收数据,使用DMA外设和串口外设,使用的中断是串口空闲中断.本篇文章主要讲解使用DMA发送数据,不会讲解基础的 ...
- STM32工作笔记0017---ISP串口下载
技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 这个安装也是有教程的. 串口一般来说就是PA9,PA10 stm32,一般通过串口1下载ÿ
- STM32与中显串口屏的通信
STM32与中显串口屏的通信 本文将简要介绍STM32单片机和武汉中显串口屏之间的通信实现过程.不过使用大彩.迪文这些公司的串口屏的同学也能参考一下,它们的通信协议好像一样. 注意:我代码用的ardu ...
- K_A13_001 基于STM32驱动霍尔开关传感器 串口与OLED0.96双显示
K_A13_001 基于STM32驱动霍尔开关传感器 串口与OLED0.96双显示 一.资源说明 二.基本参数 参数 引脚说明 三.驱动说明 对应程序: 四.部分代码说明 1.接线引脚定义 STM32 ...
- STM32平台的USART串口通信
本文目的是编写stm32串口通信程序,实现stm32上电自动循环发送hello LYJ!!!,并可通过上位机控制stm32串口发送与否.通过亲自做一下USART串口通信实验,学习如何使用stm32平台 ...
- Matlab 与stm32单片机之间的串口通信
Matlab 与stm32单片机之间的串口通信 在我们用stm32做信号处理时,我时常需要用到Matlab对我们采集的数据进行分析,拟合.按照传统的方法,我们一般都会先将数据通过串口助手打印出来,再导 ...
- STM32 NUCLEO开发板通过Mini USB供电
STM32 NUCLEO开发板可以通过Mini USB(CN1)供电 但不能插上去就使用,需要用跳线帽短接JP1(红色方框位置) 资料原文: JP1 jumper can be set in case ...
最新文章
- 2018微信年度数据报告:00后最爱表情捂脸哭 80后呲牙笑
- 用Tcl定制Vivado设计实现流程
- 编译包含Google Play服务App的SDK版本问题
- mysql 开发进阶篇系列 22 磁盘I/O问题(从linux操作系统上优化)
- 幕课网产品总监:教你从0到1打造600W下载量的爆款APP
- Jupyter notebook Ipython 魔法函数 Magic 计算代码(函数)耗时 Timing(%%time %time %timeit)
- SAP 电商云 Spartacus UI SSR 单元测试里的 callFake
- 【One by One系列】IdentityServer4(三)使用用户名和密码
- FIFO队列 ADT接口 链表实现
- 剑指offer面试题[31]-连续数组的最大和
- html水平垂直居中
- python微信自动发朋友圈_Python自制微信机器人:群发消息、自动接收好友
- Java 调用阿里云小蜜示例代码
- Nvidia Tesla M40 装机保姆教程
- 计算机程序ppt,计算机和计算机程序.ppt
- Think Pad E570重装Win10系统没有外放喇叭声音
- 5-27 冒泡法排序 (20分)
- Performing Basic Amazon S3 Bucket Operations
- 烘焙门店 | 解锁公众号精准引流5W+的流量密码
- 异构计算, GPU和框架选型指南
热门文章
- 空间杜宾模型-多种权重矩阵制作、空间相关性检验、SDM、SEM、SAR模型的命令、相关检验及其结果分析
- centos下配置nagios监控主机及服务的总结
- java新手入门指南
- angularJs实现排序效果
- 新华三又获一奖“中国IT服务领军企业”,专业能力再受认可
- 新基建浪潮来袭 企业快速上云应一切从“简”
- (附源码)小程序 心理治愈 毕业设计041506
- PHP----下载断点后续传
- 计算机u盘 硬盘无法读取,解读:在Lenovo计算机U盘的启动PE中看不到硬盘的解决方案(无法识别)...
- 直击2023云南移动生态合作伙伴大会,聚焦云南移动的“价值裂变”