一、usart串口

1.1 USART串口协议

        串口通讯(Serial Communication) 是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和片设;STM32 标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。

1.2 物理层信息

        在下面的通讯方式中,两个通讯设备的“DB9 接口”之间通过串口信号线建立起连接,串口信号线中使用“RS-232 标准”传输数据信号。由于 RS-232 电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的“TTL 标准”的电平信号,才能实现通讯。

1.3 电平标准

        我们知道常见的电子电路中常使用 TTL 的电平标准,理想状态下,使用 5V 表示二进制逻辑 1,使用 0V 表示逻辑 0;而为了增加串口通讯的远距离传输及抗干扰能力,它使用-15V 表示逻辑 1,+15V 表示逻辑 0。使用 RS232 与 TTL 电平校准表示同一个信号时的对比见下图。

        因为控制器一般使用 TTL 电平标准,所以常常会使用 MA3232 芯片对 TTL 及 RS-232电平的信号进行互相转换。 

 1.4 功能引脚

TX: 发送数据输出引脚。 RX: 接收数据输入引脚。 SW_RX:数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。 nRTS: 请求以发送(Request To Send),n 表示低电平有效。如果使能 RTS 流控制,当USART 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。 nCTS: 清除以发送(Clear To Send),n 表示低电平有效。如果使能 CTS 流控制,发送器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。 SCLK: 发送器时钟输出引脚。 这个引脚仅适用于同步模式。USART 引脚在 STM32F103ZET6 芯片具体分布见下表。

 二、usart基本结构

 三、电路接线图

四、代码编写思路

         此次工程代码可以在OLED工程文件的基础上进行编写。

        首先我们需要创建Serial.c和Serial.h两个文件,用来编写usart的驱动代码。至于两个文件的创建方法此处就不再讲了,不清楚的可以看我之前的文章,在最初几篇文章会讲到这个方法。

        首先还是老规矩,在Serial.h文件里面先编写固定的格式,如下:

#ifndef __SERIAL_H

#define __SERIAL_H

#endif

        在Serial.c文件里面,首先加上必备的头文件#include "stm32f10x.h" 。

        紧接着创建一个Serial_Init()函数,用于初始化usart功能。在此函数里面,首先开启USART1的时钟,因为USART1的收发信息的引脚是PA9和PA10,因此我们再开启GPIOA的时钟。

        下面需要对GPIOA进行初始化,因为需要接收信息,所以把PA9初始化为复用推挽模式。

        下面是对USART进行初始化。我们首先需要定义结构体变量,然后初始化波特率为9600,完善相应的结构体变量即可。

        最后加上代码USART_Cmd(USART1, ENABLE);使能USART1,这样一来USART就初始化好了,可以正常接受信息了。

        USART初始化完成之后,我们还需要编写一个串口发送的函数,命名为Serial_Sendbyte()。

选用USART_SendDate函数进行数据的发送,后面需要等待判断发送是否完成。然后把所有定义的函数在Serial.h文件里面声明一下,就可以直接在主函数里面使用了。

        在main.c主函数里面,我们包含了相应的头文件之后,只需要先初始化OLED和串口,然后直接使用我们封装好的Serial——SendByte()函数就行。

        代码如下:

Serial.c

#include "stm32f10x.h" // Device header

/**

* 函 数:串口初始化

* 参 数:无

* 返 回 值:无

*/

void Serial_Init(void)

{

/*开启时钟*/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启USART1的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟

/*GPIO初始化*/

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA9引脚初始化为复用推挽输出

/*USART初始化*/

USART_InitTypeDef USART_InitStructure; //定义结构体变量

USART_InitStructure.USART_BaudRate = 9600; //波特率

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制,不需要

USART_InitStructure.USART_Mode = USART_Mode_Tx; //模式,选择为发送模式

USART_InitStructure.USART_Parity = USART_Parity_No; //奇偶校验,不需要

USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位,选择1位

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长,选择8位

USART_Init(USART1, &USART_InitStructure); //将结构体变量交给USART_Init,配置USART1

/*USART使能*/

USART_Cmd(USART1, ENABLE); //使能USART1,串口开始运行

}

/**

* 函 数:串口发送一个字节

* 参 数:Byte 要发送的一个字节

* 返 回 值:无

*/

void Serial_SendByte(uint8_t Byte)

{

USART_SendData(USART1, Byte); //将字节数据写入数据寄存器,写入后USART自动生成时序波形

while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待发送完成

/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/

}

Serial.h

#ifndef __SERIAL_H

#define __SERIAL_H

void Serial_Init(void);

void Serial_SendByte(uint8_t Byte);

#endif

main.c

#include "stm32f10x.h" // Device header

#include "Delay.h"

#include "OLED.h"

#include "Serial.h"

int main(void)

{

/*模块初始化*/

OLED_Init(); //OLED初始化

Serial_Init(); //串口初始化

/*串口基本函数*/

Serial_SendByte(0x41); //串口发送一个字节数据0x41

while (1)

{

}

}

五、实操效果展示

精彩链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: