【STM32】STM32F1串口示例(HAL库)

00. 目录

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系列教程汇总

  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值