嵌入式铁头山羊stm32-串口之定义,USART,初始化IO引脚-Day7

该文章已生成可运行项目,

嵌入式铁头山羊STM32-各章节详细笔记-查阅传送门(点击传送)


目录

1.串口

2.USART模块(U ra te)

3.初始化串口的IO引脚

疑惑解答:


1.串口

(1)串口,其实就是个通信接口

        分为两类:Tx和Rx(传输引脚和接收引脚)

(2)串口组成

空闲状态,起始位,数据位(最后一位校验位可选),停止位,空闲状态(或者继续开始起始位)

注意:十进制转二进制可以直接使用加法得到,下图27;数据可以是数字(十转2)或者单词(ASCAII);中间的数据位可选8-9位,停止位选择也不唯一;特别注意:数据发送的时候从右往左,接收的时候从左往右接收(原因是下面讲到的移位寄存器的原理)

(3)数据位的22分类

数据位8-9,最后一位的有无校验位,所以最后分成4种

(4)校验位的分类

奇校验or偶校验:如果当前是奇校验,发送方如果数据位除了校验位有偶数个1,那么校验位就设置为1,总共就是奇数个1,传到接收方接收如果总共是奇数个1,就是正确的。

2.USART模块(U ra te)

(1)单片机的串口(这里有串口1,串口2,串口3)

(2)使用者只需发送的时候往发送寄存器写东西就行,他会自己给发送出前面学习的起始位,数据位等等格式的数据。接收的时候在接收寄存器接收数据就行。下图是usart模块的内部结构框图

(3)移位寄存器的发送(发送后低位在前,高位在后)和接收(接收后高位在后,低位在前)

串并转换:发送的时候并行写入发送寄存器,之后并且进入移位寄存器,然后移位寄存器串行的一个个移位输出串口数据帧格式的数据。同理接收的时候串行接收数据,等移位寄存器一个个移进来数据就直接并行写入接收数据寄存器。

(4)前面第一部分学习的串口的起始位,数据位等等总的来说是串口数据帧的格式的定义

(5)波特率的设置靠分频系数来得到,该分频系数存储在波特率寄存器(后面代码的时候直接写想要的波特率就行,因为底层会自动计算该系数)

(6)USART初始化编程

编程思路:很简单,首先就是片上外设开启必须要使用的时钟,之后就是初始化的两参数:类型名称和结构体,结构体从GPIO的老三样(G、P、IO代表输入输出,所以很好记就三个参数)变成了五大参数(很好记,你就即USART有几个单词不就有几个初始化配置)。

#include "stm32f10x.h"
#include "Delay.h"

int main(void)
{
	
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
//	GPIO_InitTypeDef GPIO_InitStruct={0};
//	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
//	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;
//	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_OD;
//	
//	GPIO_Init(GPIOC,&GPIO_InitStruct);//初始化引脚0
//	

//	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
//	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU; 
//	
//	GPIO_Init(GPIOC,&GPIO_InitStruct);//初始化引脚1
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	USART_InitTypeDef usart_initStruct={0};
	usart_initStruct.USART_BaudRate=115200;
	usart_initStruct.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;
	usart_initStruct.USART_WordLength=9;
	usart_initStruct.USART_StopBits=USART_StopBits_1;
	usart_initStruct.USART_Parity=USART_Parity_No;
	USART_Init(USART1,&usart_initStruct);
	

	
	
	
	while(1)
	{
	
	}
}

3.初始化串口的IO引脚

首先,前面学习了什么是串口,单片机上的串口USART以及怎么初始化编程,这里就是怎么在单片机上找到串口的引脚位置,以及找到了引脚,那么引脚的模式等参数又是怎么设置的。

(1)一般引脚就看标准的这两就行

(2)Tx,Rx位于哪个引脚就得去数据手册的引脚章节,找到当前使用的对应单片机上的引脚情况

答案就是位于复用模式(一般是cpu直接操作引脚,复用则CPU-外设(比如串口模块)-引脚发送串口数据帧格式的数据)下的

默认:PA9,PA10

重映射为:PB6,PB7

从前面知道了引脚的位置,那剩下的GPIO的两大参数怎么设置

就要看你选择的是串口的什么模式(普遍是全双工,以及Rx的全双工的浮空输入和上拉输入默认一般选择上拉输入,因为上拉默认高电压,等价于前面说的空闲状态,不像浮空输入会像天线一样高/低电压变化)

引脚分布表在数据手册的引脚部分;重映射表在参考手册的GPIO的重映射部分;参数的设置在参考手册的GPIO的外设配置部分。

(5)默认的Rx,Tx编程

(6)重映射的Rx,Tx

USART 模块的使能,其实就是让 MCU 内部的 USART 外设从“断电/停止”状态进入工作状态,让它开始响应你对串口的读写操作。

代码:

#include "stm32f10x.h"
#include "Delay.h"

int main(void)
{
	

		
		//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
        //	USART_InitTypeDef usart_initStruct={0};
        //	usart_initStruct.USART_BaudRate=115200;
        //	usart_initStruct.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;
        //	usart_initStruct.USART_WordLength=9;
        //	usart_initStruct.USART_StopBits=USART_StopBits_1;
        //	usart_initStruct.USART_WordLength=USART_Parity_No;
        //	USART_Init(USART1,&usart_initStruct);
        //	
        //		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        //		GPIO_InitTypeDef gpio_initStruct={0};
        //		gpio_initStruct.GPIO_Pin=GPIO_Pin_9;
        //		gpio_initStruct.GPIO_Mode=GPIO_Mode_AF_PP;
        //		gpio_initStruct.GPIO_Speed=GPIO_Speed_10MHz;
         		
        //		
        //		GPIO_Init(GPIOA,&gpio_initStruct);
        //		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        //		gpio_initStruct.GPIO_Pin=GPIO_Pin_10;
        //		gpio_initStruct.GPIO_Mode=GPIO_Mode_IPU;
        //		
        //		GPIO_Init(GPIOA,&gpio_initStruct);
        //	
		
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
		GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
		
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
		GPIO_InitTypeDef gpio_initStruct2={0};
		gpio_initStruct2.GPIO_Pin=GPIO_Pin_6;
		gpio_initStruct2.GPIO_Mode=GPIO_Mode_AF_PP;
		gpio_initStruct2.GPIO_Speed=GPIO_Speed_10MHz;
		
		
		GPIO_Init(GPIOA,&gpio_initStruct2);
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
		gpio_initStruct2.GPIO_Pin=GPIO_Pin_7;
		gpio_initStruct2.GPIO_Mode=GPIO_Mode_IPU;
		
		GPIO_Init(GPIOA,&gpio_initStruct2);

	while(1)
	{
	
	}
}

疑惑解答:

问:这段代码我的问题是:gpio_initStruct2.GPIO_Pin=GPIO_Pin_7; gpio_initStruct2.GPIO_Mode=GPIO_Mode_IPU;

这两句代码执行后,那原本的GPIO_InitTypeDef gpio_initStruct2={0}; gpio_initStruct2.GPIO_Pin=GPIO_Pin_6; gpio_initStruct2.GPIO_Mode=GPIO_Mode_AF_PP; gpio_initStruct2.GPIO_Speed=GPIO_Speed_10MHz; GPIO_Init(GPIOA,&gpio_initStruct2);这些呢?即原本的6引脚是不配置了吗还是继续是开启的?

结论先说

  • 第一次调用 GPIO_Init(GPIOA, &gpio_initStruct2); 时,PA6 已经按 AF_PP(复用推挽输出)模式成功配置。

  • 第二次你只是修改了 gpio_initStruct2 变量里的成员,然后再调用一次 GPIO_Init,这次配置只会影响你传进去的 引脚位(PA7)

  • 之前 PA6 的配置不会被清掉,它会一直保持第一次配置的状态,直到你再用 GPIO_Init 重新配置它,或者芯片复位。

更形象的理解

你可以把寄存器想象成一个房间里很多开关(每个引脚占一组开关):

  • 第一次配置 PA6 = 把 PA6 的那组开关拨好位置。

  • 第二次配置 PA7 = 只动 PA7 的那组开关,PA6 的保持原状。

注意

虽然 gpio_initStruct2 这个结构体变量被你覆盖了,但它只是一个传参数用的临时变量,跟硬件寄存器的状态没有直接绑定。
真正控制 GPIO 状态的是寄存器,不是这个结构体。所以变量值怎么改都不会“自动重置”之前的引脚,只有你再次调用 GPIO_Init() 并且包含那个引脚的 GPIO_Pin 时才会改变它。


本文章已经生成可运行项目
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

古译汉书

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

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

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

打赏作者

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

抵扣说明:

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

余额充值