admin管理员组文章数量:1558877
00. 目录
文章目录
- 00. 目录
- 01. STM32概述
- 02. STM32的USART简介
- 03. 串口发送示例一
- 04. 串口发送示例二
- 05. 串口接收示例(中断方式)
- 06. 串口接收示例(中断方式)
- 07. 附录
01. STM32概述
STM32是一款由意法半导体(STMicroelectronics,简称ST)公司制造的微控制器(MCU),它基于ARM Cortex-M内核设计,专为要求高性能、低成本、低功耗的嵌入式应用而设计。以下是对STM32的详细介绍:
产品概述
- 内核:STM32采用了ARM Cortex-M系列内核,包括M0、M0+、M3、M4和M7等多种系列,能够满足不同应用场景的需求。
- 特点:高性能、低成本、低功耗、可裁剪,这些特点使得STM32在嵌入式开发领域具有广泛的应用前景。
- 应用领域:STM32微控制器广泛应用于工业自动化、汽车电子、消费电子、物联网、无人机、嵌入式设备等多个领域。
产品系列
STM32系列微控制器按照内核架构和性能特点可以分为多个系列,主要包括:
- 主流产品:如STM32F0、STM32F1、STM32F3等,适用于一般的嵌入式应用。
- 超低功耗产品:如STM32L0、STM32L1、STM32L4等,专为低功耗设计,适用于对功耗要求较高的应用。
- 高性能产品:如STM32F2、STM32F4、STM32F7、STM32H7等,具有更高的处理速度和更强的外设功能,适用于需要高性能的应用场景。
技术特点
- 高性能:STM32微控制器的主频可达72MHz以上,能够满足各种高速数据处理需求。
- 丰富的外设资源:STM32集成了GPIO、USART、SPI、I2C等多种外设资源,可满足各种通信和控制需求。
- 低功耗:STM32采用了先进的低功耗技术,如休眠模式、待机模式等,可大幅降低功耗。
- 易用的开发工具:STM32提供了丰富的开发工具,如Keil、IAR等,支持多种编程语言(如C、C++、汇编等),方便开发人员进行开发和调试。
02. STM32的USART简介
通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于USART还有一个UART(Universal Asynchronous Receiver and Transmitter),它是在USART基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是UART。
串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数据信息、停止信息,可能还有校验信息。USART就是对这些传输参数有具体规定,当然也不是只有唯一一个参数值,很多参数值都可以自定义设置,只是增强它的兼容性。
USART满足外部设备对工业标准NRZ异步串行数据格式的要求,并且使用了小数波特率发生器,可以提供多种波特率,使得它的应用更加广泛。USART支持同步单向通信和半双工单线通信;还支持局域互连网络LIN、智能卡(SmartCard)协议与lrDA(红外线数据协会) SIR ENDEC规范。
USART支持使用DMA,可实现高速数据通信,有关DMA具体应用将在DMA章节作具体讲解。
USART在STM32应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一个USART通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。
03. 串口发送示例一
uart1.h
#ifndef __UART1_H__
#define __UART1_H__
#include "stm32f1xx.h"
#include "sys.h"
//串口初始化
void uart1_init(u32 bound);
//发送字符
void uart1_send_byte(uint8_t ch);
//发送字符串
void uart1_send_str(uint8_t *str);
#endif /*__UART1_H__*/
uart1.c
#include "uart1.h"
static UART_HandleTypeDef UART1_Handler; //UART句柄
//串口初始化
void uart1_init(u32 bound)
{
//UART 初始化设置
UART1_Handler.Instance = USART1; //USART1
UART1_Handler.Init.BaudRate = bound; //波特率
UART1_Handler.Init.WordLength = UART_WORDLENGTH_8B; //字长为8位数据格式
UART1_Handler.Init.StopBits = UART_STOPBITS_1; //一个停止位
UART1_Handler.Init.Parity = UART_PARITY_NONE; //无奇偶校验位
UART1_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; //无硬件流控
UART1_Handler.Init.Mode = UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能UART1
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
{
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_USART1_CLK_ENABLE(); //使能USART1时钟
__HAL_RCC_AFIO_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_9; //PA9
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA9
GPIO_Initure.Pin=GPIO_PIN_10; //PA10
GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式!
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA10
}
}
//发送字符
void uart1_send_byte(uint8_t ch)
{
HAL_UART_Transmit(&UART1_Handler, &ch, 1, 1000);
}
//发送字符串
void uart1_send_str(uint8_t *str)
{
unsigned int i = 0;
do{
HAL_UART_Transmit(&UART1_Handler, str + i, 1, 1000);
i++;
}while(*(str + i) != '\0');
}
main.c
#include "stm32f1xx.h"
#include "sys.h"
#include "led.h"
#include "uart1.h"
#include "delay.h"
int main(void)
{
HAL_Init();
Stm32_Clock_Init(RCC_PLL_MUL9);
delay_init(72);
uart1_init(115200);
while(1)
{
uart1_send_byte('A');
delay_ms(1000);
}
return 0;
}
程序下载:05-UART发送字符.rar
测试结果
04. 串口发送示例二
uart1.h
#ifndef __UART1_H__
#define __UART1_H__
#include "stm32f1xx.h"
#include "sys.h"
//串口初始化
void uart1_init(u32 bound);
//发送字符
void uart1_send_byte(uint8_t ch);
//发送字符串
void uart1_send_str(uint8_t *str);
#endif /*__UART1_H__*/
uart1.c
#include "uart1.h"
static UART_HandleTypeDef UART1_Handler; //UART句柄
//串口初始化
void uart1_init(u32 bound)
{
//UART 初始化设置
UART1_Handler.Instance = USART1; //USART1
UART1_Handler.Init.BaudRate = bound; //波特率
UART1_Handler.Init.WordLength = UART_WORDLENGTH_8B; //字长为8位数据格式
UART1_Handler.Init.StopBits = UART_STOPBITS_1; //一个停止位
UART1_Handler.Init.Parity = UART_PARITY_NONE; //无奇偶校验位
UART1_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; //无硬件流控
UART1_Handler.Init.Mode = UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能UART1
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
{
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_USART1_CLK_ENABLE(); //使能USART1时钟
__HAL_RCC_AFIO_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_9; //PA9
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA9
GPIO_Initure.Pin=GPIO_PIN_10; //PA10
GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式!
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA10
}
}
//发送字符
void uart1_send_byte(uint8_t ch)
{
HAL_UART_Transmit(&UART1_Handler, &ch, 1, 1000);
}
//发送字符串
void uart1_send_str(uint8_t *str)
{
unsigned int i = 0;
do{
HAL_UART_Transmit(&UART1_Handler, str + i, 1, 1000);
i++;
}while(*(str + i) != '\0');
}
main.c
#include "stm32f1xx.h"
#include "sys.h"
#include "led.h"
#include "uart1.h"
#include "delay.h"
int main(void)
{
HAL_Init();
Stm32_Clock_Init(RCC_PLL_MUL9);
delay_init(72);
uart1_init(115200);
while(1)
{
uart1_send_str((uint8_t*)"hello stm32");
delay_ms(1000);
}
return 0;
}
程序下载:06-UART发送字符串.rar
测试结果
05. 串口接收示例(中断方式)
uart1.h
#ifndef __UART1_H__
#define __UART1_H__
#include "stm32f1xx.h"
#include "sys.h"
#define RXBUFFERSIZE 1
extern u8 aRxBuffer[RXBUFFERSIZE]; //HAL库USART接收Buffer
extern u8 uart_rx_flag; //串口1接收标志
extern UART_HandleTypeDef UART1_Handler; //UART句柄
//串口初始化
void uart1_init(u32 bound);
//发送字符
void uart1_send_byte(uint8_t ch);
//发送字符串
void uart1_send_str(uint8_t *str);
#endif /*__UART1_H__*/
uart1.c
#include "uart1.h"
UART_HandleTypeDef UART1_Handler; //UART句柄
u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
u8 uart_rx_flag = 0; //串口1接收标志
//串口初始化
void uart1_init(u32 bound)
{
//UART 初始化设置
UART1_Handler.Instance = USART1; //USART1
UART1_Handler.Init.BaudRate = bound; //波特率
UART1_Handler.Init.WordLength = UART_WORDLENGTH_8B; //字长为8位数据格式
UART1_Handler.Init.StopBits = UART_STOPBITS_1; //一个停止位
UART1_Handler.Init.Parity = UART_PARITY_NONE; //无奇偶校验位
UART1_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; //无硬件流控
UART1_Handler.Init.Mode = UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能UART1
//使能串口接收中断
HAL_UART_Receive_IT(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
{
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_USART1_CLK_ENABLE(); //使能USART1时钟
__HAL_RCC_AFIO_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_9; //PA9
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA9
GPIO_Initure.Pin=GPIO_PIN_10; //PA10
GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式!
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA10
/*抢占优先级0,子优先级1*/
HAL_NVIC_SetPriority(USART1_IRQn ,0,1);
HAL_NVIC_EnableIRQ(USART1_IRQn); /*使能USART1中断通道*/
}
}
//发送字符
void uart1_send_byte(uint8_t ch)
{
HAL_UART_Transmit(&UART1_Handler, &ch, 1, 1000);
}
//发送字符串
void uart1_send_str(uint8_t *str)
{
unsigned int i = 0;
do{
HAL_UART_Transmit(&UART1_Handler, str + i, 1, 1000);
i++;
}while(*(str + i) != '\0');
}
//串口1中断服务函数
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&UART1_Handler);
//使能串口接收中断
HAL_UART_Receive_IT(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);
}
//接收完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
uart_rx_flag = 1;
}
main.c
#include "stm32f1xx.h"
#include "sys.h"
#include "led.h"
#include "uart1.h"
#include "delay.h"
int main(void)
{
HAL_Init();
Stm32_Clock_Init(RCC_PLL_MUL9);
delay_init(72);
uart1_init(115200);
while(1)
{
if (uart_rx_flag == 1)
{
uart1_send_byte(aRxBuffer[0]);
//等待发送完成
while(__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_TC) != SET)
;
uart_rx_flag = 0;
}
else
{
delay_ms(10);
}
}
return 0;
}
程序下载:06-UART中断方式接收.rar
程序运行结果
06. 串口接收示例(中断方式)
uart.h
#ifndef __UART1_H__
#define __UART1_H__
#include "stm32f1xx.h"
#include "sys.h"
#define RXBUFFERSIZE 1
#define USART_REC_LEN 200 //定义最大接收字节数 200
#define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART_RX_STA; //接收状态标记
extern u8 aRxBuffer[RXBUFFERSIZE]; //HAL库USART接收Buffer
extern u8 uart_rx_flag; //串口1接收标志
extern UART_HandleTypeDef UART1_Handler; //UART句柄
//串口初始化
void uart1_init(u32 bound);
//发送字符
void uart1_send_byte(uint8_t ch);
//发送字符串
void uart1_send_str(uint8_t *str);
#endif /*__UART1_H__*/
uart.c
#include "uart1.h"
UART_HandleTypeDef UART1_Handler; //UART句柄
u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
u8 uart_rx_flag = 0; //串口1接收标志
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA = 0; //接收状态标记
//串口初始化
void uart1_init(u32 bound)
{
//UART 初始化设置
UART1_Handler.Instance = USART1; //USART1
UART1_Handler.Init.BaudRate = bound; //波特率
UART1_Handler.Init.WordLength = UART_WORDLENGTH_8B; //字长为8位数据格式
UART1_Handler.Init.StopBits = UART_STOPBITS_1; //一个停止位
UART1_Handler.Init.Parity = UART_PARITY_NONE; //无奇偶校验位
UART1_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; //无硬件流控
UART1_Handler.Init.Mode = UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能UART1
//使能串口接收中断
HAL_UART_Receive_IT(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
{
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_USART1_CLK_ENABLE(); //使能USART1时钟
__HAL_RCC_AFIO_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_9; //PA9
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA9
GPIO_Initure.Pin=GPIO_PIN_10; //PA10
GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式!
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA10
/*抢占优先级0,子优先级1*/
HAL_NVIC_SetPriority(USART1_IRQn ,0,1);
HAL_NVIC_EnableIRQ(USART1_IRQn); /*使能USART1中断通道*/
}
}
//发送字符
void uart1_send_byte(uint8_t ch)
{
HAL_UART_Transmit(&UART1_Handler, &ch, 1, 1000);
}
//发送字符串
void uart1_send_str(uint8_t *str)
{
unsigned int i = 0;
do{
HAL_UART_Transmit(&UART1_Handler, str + i, 1, 1000);
i++;
}while(*(str + i) != '\0');
}
//串口1中断服务函数
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&UART1_Handler);
//使能串口接收中断
HAL_UART_Receive_IT(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);
}
//接收完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//判断是否为串口1
if (huart->Instance == USART1)
{
//接收未完成
if ((USART_RX_STA & 0x8000) == 0)
{
//接收到了0x0D
if ((USART_RX_STA & 0x4000) )
{
if (aRxBuffer[0] != 0xA)
{
USART_RX_STA = 0;
}
else
{
USART_RX_STA |= 0x8000;
}
}
else
{
//没有收到0x0D
if (aRxBuffer[0] == 0x0D)
{
USART_RX_STA |= 0x4000;
}
else
{
USART_RX_BUF[USART_RX_STA & 0x3FFF] = aRxBuffer[0];
USART_RX_STA++;
if (USART_RX_STA > (USART_REC_LEN - 1))
{
USART_RX_STA = 0;
}
}
}
}
}
}
main.c
#include "stm32f1xx.h"
#include "sys.h"
#include "led.h"
#include "uart1.h"
#include "delay.h"
int main(void)
{
u8 len = 0;
HAL_Init();
Stm32_Clock_Init(RCC_PLL_MUL9);
delay_init(72);
uart1_init(115200);
while(1)
{
if (USART_RX_STA & 0x08000)
{
len = USART_RX_STA & 0x3fff;
HAL_UART_Transmit(&UART1_Handler, (uint8_t *)USART_RX_BUF, len, 1000);
while(__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_TC) != SET)
;
USART_RX_STA = 0;
}
else
{
delay_ms(10);
}
}
return 0;
}
程序下载:07-UART-STR.rar
测试结果
07. 附录
网址:【STM32】STM32系列教程汇总
版权声明:本文标题:【STM32】STM32F1串口示例(HAL库) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1727405208a1113296.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论