STM32教程第十课:串口发送数据详解

一、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)
	{
		
	}
}

五、实操效果展示

作者:与君共勉დ

物联沃分享整理
物联沃-IOTWORD物联网 » STM32教程第十课:串口发送数据详解

发表评论