#本文有参考官方文档,连接就放在最后了,大家可以去看看,写的比较好,同时在此声明,本系列笔记是用来,记录学习过程中产生的问题,以及查询结果逐渐理解的过程。
#USART
笔者理解:一种常用的通信方式,分为:同步通信、异步通信,两种二者差别在于,连接双方是不是有着相同的时钟频率,也就是是否有 CLK时钟数据线相连接。笔者所使用的最多的一种方式也就是异步通信,通信双方有着不同的时钟频率,对此需要我们配置 波特率,使其双方,通信发送、接收频率保持一致,保持收发数据正常。
简单解释一下工作模式,众所周知串口的工作模式分为:
单工:晚上广场舞大妈的音响,只能从A(音箱)到B(个人),B只能接受信息不能发送信息
半双工:枪战片里面的,对讲机可以相互通信,但不能同时进行通信交互。
全双工:就像是vx或者QQ,通信双方可以同时收发信息。
笔者写USART.C的驱动流程是 :
1 project文档下的Hardware文档下新建USART.C驱动,KEIL5添加.c文件和头文件
.h头文件添加防止重复引用代码 usart.c源文件中,引入启动文件,和usart.h文件
2配置USART使用GPIO引脚,封装函数
3配置USART基本配置,封装相关函数,头文件声明
4main.c文件中引入usart.c驱动,调用驱动函数
到此笔者带着大家看一下,官方文档提供的,学习代码
开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启串口1的时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); // 开启端口时钟
开启片上外设AFIO也就是复用模式,#AFIO 相关理解 芯片为了有更多的功能,减少更多的体积,对应上的芯片应该是更多的片上外设 更少的引脚,那么更少的引脚如何对应更多的片上外设功能呢? AFIO复用 这个片上外设模块,它可以使同一个引脚有着不同的功能,具体对应代码,就是调用函数,查询数据手册,映射表,进行映射切换,引脚功能。
//IO口用作串口引脚要配置复用模式
GPIO_PinAFConfig(GPIOA, GPIO_Pin_9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_Pin_9, GPIO_AF_USART1);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BSP_USART_TX_PIN; //TX引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //IO口用作串口引脚要配置复用模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BSP_USART_RX_PIN; //RX引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //IO口用作串口引脚要配置复用模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//这里产生,笔者第一个,不理解的地方,引脚上拉配置,为什么上拉配置?
首先在这里,不要疑惑,为啥RX引脚设置为,AFPP,也就是推挽输出,不应改是上拉输入嘛,在官方提供的,演示文档里面,只用到了,单片机对PC端传输,信息,没有全工,所以这个RX怎么配置是都可以的,但是在这里还是建议软件上拉,接高电平。
疑问点1:TX为什么要进行上拉,接高电平
在代码,里面TX RX引脚都是通过软件进行上拉的,这里引入pcb设计的理念,在pcb设计中,信号输入引脚,如果不同,是要进行接电阻,下拉接地处理的?为什么,如果没有下拉接地,进行处理,这个引脚就会产生噪声,对应到电路上就是,电压不稳定,不是理想电压,有毛刺,那我们回来,RX可以上拉接高电平,也就是空闲时,这个引脚是高电平。那为什么TX引脚也上拉接高电平了。
上面一点,是别人的文章,下面是笔者个人看法:
tx------------rx
rx-------------tx
接线方式对不对,RX应该是软件上拉高电平,为了方式有电路上的噪声对不对,rx 跟 tx 连接的对不对,如果USART闲置的时候 那么RX应该是高电平对不对,如果TX是进行下拉,二者相连,对RX电压会不会有影响,所以统一上拉,避免不必要的麻烦,已上个人理解,初次之外,笔者,自己用电压表,测了USB转TTl这个 TX RX电压都是4.9V上下浮动,近似5V,所以至此,应该对TX在软件中进行上拉。
然后进行串口配置
USART_InitStructure.USART_BaudRate = 9600;//设置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字节长度为8bit
USART_InitStructure.USART_StopBits = USART_StopBits_1;//1个停止位
USART_InitStructure.USART_Parity = USART_Parity_No ;//没有校验位
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//将串口配置为收发模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不提供流控
USART_Init(BSP_USART,&USART_InitStructure);//将相关参数初始化给串口1
USART_ClearFlag(BSP_USART,USART_FLAG_RXNE);//初始配置时清除接受置位
疑问点2:硬件流控也就是HardwareFlowControl是什么?为什么常见串口配置都不会对这个选型进行配置。
USART硬件流控制概念以及原理(硬件控制流以及软件控制流)-CSDN博客
这个是搬运的原文连接,个人理解,硬件流,这个选型,是用于防止TX给RX发数据时,方式RX寄存器有数据,而TX依旧发送数据,导致数据溢出,所用的,那这个选型是为了防止溢出,为什么不用的,笔者常见的一般为,封装函数中,while循环条件查询TXNE RXNE 寄存器标志位,进行防止溢出
void usart_send_data(uint8_t ucch)
{
USART_SendData(BSP_USART, (uint8_t)ucch);
// 等待发送数据缓冲区标志置位
while( RESET == USART_GetFlagStatus(BSP_USART, USART_FLAG_TXE) ){}
}
void Data_send(void)
{
while(SET == USART_GetFlagStatus(BSP_USART, USART_FLAG_RXNE)){};//RXNE标志位有数据时为1,
usart_send_data();
}
只要在封装函数中,while循环等待,就会防止出现寄存器溢出现象
TXNE 发送寄存器 :
1 寄存器为空可以进行发送
0 寄存器有数据不能进行发送
RXNE 接受数据寄存器:
0 无数据可以接受数据
1 有数据不能接受
这两个标记,是相反的,ST为啥不搞的一样,好记一点,至此,第二个疑问解决,为什么不用硬件流控这个功能,选型。
【立创·天空星STM32F407VET6】入门手册 - 飞书云文档 (feishu.cn)
最后希望对你有所帮助,如有失误,欢迎指出,查实立改正。希望对你有所帮助!!!
标签:TX,USART,引脚,RX,InitStructure,GPIO,立创,STMF4 From: https://blog.csdn.net/weixin_62292999/article/details/139352735