7.[STM32]USART(串口通信)

1.说点啥

🍌
🍌🍌
作者简介:大家好啊,我叫DW,小白一个,每天分享一些我新学到的知识,期待和大家一起进步
🍋
🍋🍋
系列专栏:STM32
🍎
🍎🍎
🍎🍎🍎
🌞小实验目标:实现串口打印数据🌞
🍊如有写得不好的地方欢迎大家指正🍊
创作时间:🍊🍊🍊2022年4月20日🍊🍊🍊

在这里插入图片描述

2 USART简介

STM32 的串口资源相当丰富的,功能也相当强劲。STM32F103 系列最多可提供 5 路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持 LIN、支持调制解调器操作、智能卡协议和 IrDA SIR ENDEC 规范、具有 DMA等。
在这里插入图片描述

2.1 端口复用功能

一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫做复用。例如串口1 的发送接收引脚是PA9,PA10,当我们把PA9,PA10不用作GPIO,而用做复用功能串口1的发送接收引脚的时候,叫端口复用。
串口一复用管脚
在这里插入图片描述

2.2 复用端口配置步骤

(1)GPIO 端口时钟使能

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

(2)复用的外设时钟使能。 PA9,PA10 复用为串口,故需要使能串口时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO, ENABLE);

(3)端口模式配置,本实验使用全双工模式,我们要配置全双工的串口 1,那么 TX 管脚需要配置为推挽复用输出RX 管脚配置为浮空输入或者带上拉输入都可以。
在这里插入图片描述

GPIO_InitTypeDef GPIO_InitStructure;//GPIOA 结构体定义

//TX 发送 PA9
	GPIO_InitStructure.GPIO_Pin = TX;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(USART_PROT,&GPIO_InitStructure);//初始化
	
	//RX 接收 PA10
	GPIO_InitStructure.GPIO_Pin = RX;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(USART_PROT,&GPIO_InitStructure);//初始化

2.3 串口配置步骤

(1) 串口时钟使能,GPIO 时钟使能。(2.2已经配置过
(2) 串口复位

USART_DeInit(USART1); //复位串口 1

(3) 串口参数初始化,查看串口助手,依次配置波特率、停止位、数据位、校验位。
在这里插入图片描述

//串口
	USART_DeInit(USART1);
	USART_InitStructure.USART_BaudRate = BaudRate;//波特率 115200
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位为1
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长 8
	USART_InitStructure.USART_Parity = USART_Parity_No;//无校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流 使用软件触发
	USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;//收发模式
	USART_Init(USART1,&USART_InitStructure);//初始化串口1

波特率通过形参传输
void USART_UserConfig(uint32_t BaudRate)

(4) 开启中断并且初始化 NVIC。

	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断
	USART_Cmd(USART1,ENABLE);//开启全局中断
	
	//中断配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//中断分组选择
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//中断入口 选择串口一
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子占优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断
	NVIC_Init(&NVIC_InitStructure);//初始化中断

(6) 编写中断处理函数。

//中断函数配置
void USART1_IRQHandler(void){

		if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){
	
		USART_SendData(USART1,USART_ReceiveData(USART1));
		
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
		
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);//用TXE换成TC会造成数据缺失
	}
}

2.4 重映射打印输出printf

fputc函数是printf函数内部的一个函数,功能是将字符dat写入文件指针BUF所指向文件的当前写指针位置,我们使用USART函数重新修改fputc函数内容,达到类似写入的功能。

int fputc(int dat,FILE *BUF){
	
	USART_SendData(USART1,dat);
	
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
	//while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);//数据丢失


	return dat;
}

🎵🎵 小提示
(1)使用前需要在文件中包含 stdio.h头文件。
(2)使用 fput和 fgetc函数达到重定向 C语言标准库输入输出函数必须在 MDK的工程选项把“Use MicroLIB”勾选

在这里插入图片描述

2.5 注意要点

🎵🎵 小提示

在这里插入图片描述

(1) 在接收到数据的时候(RXNE 读数据寄存器非空),我们要产生中断,那么我们开启中断的方法是

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断,接收到数据中断

(2)判断是否产生中断事件,如果其其值为‘1’则产生中断

if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)

🎵🎵 小提示
(3)获取中断标志位,判断中断是否完成;只要其值不等于0,退出这条语句,即可判别当前中断是否完成,以便进入下一个中断

while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);//第一句
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);//第二句

如果第一句的TXE换成第二句的TC会造成数据缺失
在这里插入图片描述

3.结语

今天的分享就到这里,从头到尾一个一个字码下来,重新回顾了今天的学习内容,收货满满,希望这个习惯能一直坚持下去,用博客记录自己学习的过程,谢谢大家的耐心阅读,如果觉得有用的话给个👍👍👍
在这里插入图片描述
🌜🌜🌜本章结束,我们下一章见🌜🌜🌜

源码已上传,需要自取
这是我今天学习链接:学习链接

附录

//main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"

 int main(void)
 {		
	 delay_init();
 	 USART_UserConfig(115200);
	 
	 while(1){
		  printf("adcdefg520520给个点赞吧\r\n");
		 delay_ms(200);
	 
	 }
 }
//usart.c
#include "usart.h"


void USART_UserConfig(uint32_t BaudRate){

	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO,ENABLE);//串口需要开启复用功能
	
	//TX 发送 PA9
	GPIO_InitStructure.GPIO_Pin = TX;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(USART_PROT,&GPIO_InitStructure);//初始化
	
	//RX 接收 PA10
	GPIO_InitStructure.GPIO_Pin = RX;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(USART_PROT,&GPIO_InitStructure);//初始化
	
	//串口
	USART_DeInit(USART1);
	USART_InitStructure.USART_BaudRate = BaudRate;//波特率
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位为一
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长 8
	USART_InitStructure.USART_Parity = USART_Parity_No;//无校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流 使用软件触发
	USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;//收发模式
	USART_Init(USART1,&USART_InitStructure);//初始化串口1
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断
	USART_Cmd(USART1,ENABLE);//开启全局中断
	
	//中断配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//中断分组选择
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//中断入口 选择串口一
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//子占优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断
	NVIC_Init(&NVIC_InitStructure);//初始化中断
}
//中断函数配置
void USART1_IRQHandler(void){

	if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){
	
		USART_SendData(USART1,USART_ReceiveData(USART1));
		
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
		
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
	}
}
int fputc(int dat,FILE *BUF){
	
	USART_SendData(USART1,dat);
	
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);

	return dat;
}

//usart.h
#ifndef __USART_H
#define __USART_H

#include "sys.h"
#include "stdio.h"

#define TX GPIO_Pin_9 	//PA9
#define RX GPIO_Pin_10	//PA10
#define USART_PROT GPIOA

void USART_UserConfig(uint32_t BaudRate);

#endif
  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
好的,下面是关于STM32 USART发送和接收使用DMA的回答: DMA (Direct Memory Access)是一种在不占用CPU的情况下直接进行数据传输的技术。对于STM32USART模块,使用DMA可以大大减轻CPU的负担,提高数据传输效率。 首先,需要配置USART和DMA。可以使用STM32的CubeMX工具来快速生成初始化代码。在配置USART时,需要设置USART的波特率、数据位、停止位和校验位等参数。在配置DMA时,需要设置DMA的传输方向、数据长度、传输模式、优先级和中断等参数。 接下来,可以使用HAL库提供的函数来启动DMA传输。在发送数据时,可以使用函数HAL_UART_Transmit_DMA()启动DMA传输,该函数会将数据存储在指定的缓冲区中,并将缓冲区的地址传递给DMA进行传输。在接收数据时,可以使用函数HAL_UART_Receive_DMA()启动DMA传输,该函数会将接收到的数据存储在指定的缓冲区中,并将缓冲区的地址传递给DMA进行传输。 在DMA传输完成后,可以使用HAL库提供的回调函数来进行处理。对于发送完成,可以使用函数HAL_UART_TxCpltCallback();对于接收完成,可以使用函数HAL_UART_RxCpltCallback()。 需要注意的是,在使用DMA进行数据传输时,需要确保缓冲区的大小足够大,以便存储需要传输的数据。 希望这个回答能够帮助你了解STM32 USART发送和接收使用DMA的相关知识。如果你有任何其他问题,可以随时提出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

依点_DW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值