×
单片机 > 单片机程序设计 > 详情

STM32F103学习笔记三 串口通信

发布时间:2020-06-09 发布时间:
|

1、串口通信背景知识

1.1、 设备之间的通信方式

并行通信 串行通信

传输原理 数据各个位同时传输 数据按位顺序传输

优点 速度快 占用引脚资源少

缺点 占用引脚资源多 速度相对较慢

1.2、 串行通信分类

1.2.1、按照通信方式,分为:

同步通信:带时钟同步信号传输。比如:SPI,I²C通信接口

异步通信:不带时钟同步信号。比如:UART(通用异步收发器),单总线


1.2.2、按照数据传送方向,分为:

单工:数据传输只支持数据在一个方向上传输;

半双工:允许数据在两个方向上传输。但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;它不需要独立的接收端和发送端,两者可以合并一起使用一个端口。

全双工:允许数据同时在两个方向上传输。因此,全双工通信是两个单工通信方式的结合,需要独立的接收端和发送端。


1.3、常见的串行通信接口


2、STM32的串口通信基础

2.1、STM32的串口通信接口有两种,分别是:

UART(通用异步收发器)、

USART(通用同步异步收发器)、

对于大容量STM32F10x系列芯片,分别有3个USART和2个UART。


2.2、UART引脚连接方法

① 单片机连接单片机


RXD:数据输入引脚,数据接受

TXD"数据发送引脚,数据发送


对于两个芯片之间的连接,两个芯片GND共地,同时TXD和RXD交叉连接。这里的交叉连接的意思就是,芯片1的RxD连接芯片2的TXD,芯片2的RXD连接芯片1的TXD。这样,两个芯片之间就可以进行TTL电平通信了

② 单片机连接PC


若是芯片与PC机(或上位机)相连,除了共地之外,就不能这样直接交叉连接了。尽管PC机和芯片都有TXD和RXD引脚,但是通常PC机(或上位机)通常使用的都是RS232接口,因此不能直接交叉连接。RS232接口是9针(或引脚),通常是TxD和RxD经过电平转换得到的。而单片机采用的是 TTL电平,所以需要 连接一个RS232转换器 将TTL电平转换成 PC可以识别的RS232电平,再交叉连接。

经过电平转换后,芯片串口和rs232的电平标准是不一样的:


单片机的电平标准(TTL电平):+5V表示1,0V表示0;

Rs232的电平标准:+15/+13 V表示1,-15/-13表示0。


RS-232通讯协议标准串口的设备间通讯结构图如下:

所以单片机串口与PC串口通信就应该遵循下面的连接方式:

在单片机串口与上位机给出的rs232口之间,通过电平转换电路(如下面图中的Max232芯片) 实现TTL电平与RS232电平之间的转换。


2.3、UART异步通信特点

全双工异步通信;

分数波特率发生器系统,提供精确的波特率。发送和接受共用的可编程波特率,最高可达4.5Mbits/s;

可编程的数据字长度(8位或者9位);

可配置的停止位(支持1或者2位停止位);

可配置的使用DMA多缓冲器通信;

单独的发送器和接收器使能位;

检测标志:① 接受缓冲器 ②发送缓冲器空 ③传输结束标志;

多个带标志的中断源,触发中断;

其他:校验控制,四个错误检测标志。

2.4、STM32串口异步通信需要定义的参数

STM32异步通信参数:

①起始位

②数据位(8位或者9位)

③奇偶校验位(第9位)

④停止位(1,15,2位)

⑤波特率设置

(奇偶校验位分为奇校验和偶校验两种,是一种简单的数据误码校验方法。奇校验是指每帧数据中,包括数据位和奇偶校验位的全部9个位中1的个数必须为奇数;偶校验是指每帧数据中,包括数据位和奇偶校验位的全部9个位中1的个数必须为偶数。

校验方法除了奇校验(odd)、偶校验(even)之外,还可以有:0 校验(space)、1 校验(mark)以及无校验(noparity)。 0/1校验:不管有效数据中的内容是什么,校验位总为0或者1)

UART串口通信的数据包以帧为单位,常用的帧结构为:1位起始位+8位数据位+1位奇偶校验位(可选)+1位停止位。如下图所示


2.5、 UART(USART)框图

任何USART双向通信至少需要两个脚:接收数据输入(RX)和发送数据输出(TX)。

RX:接收数据串行输。通过过采样技术来区别数据和噪音,从而恢复数据。

TX:发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,并且不发送数据时,TX引脚处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据的发送和接收。

● 总线在发送或接收前应处于空闲状态

● 一个起始位

● 一个数据字(8或9位),最低有效位在前

● 0.5,1.5,2个的停止位,由此表明数据帧的结束

● 使用分数波特率发生器 —— 12位整数和4位小数的表示方法。

● 一个状态寄存器(USART_SR)

● 数据寄存器(USART_DR)

● 一个波特率寄存器(USART_BRR),12位的整数和4位小数

● 一个智能卡模式下的保护时间寄存器(USART_GTPR)


2.6、 串口通信过程

① 数据接收过程

外部设备将数据发送到 串行输入移位寄存器,串行输入移位寄存器在将数据传送到输入数据缓冲器,MCU在从输入数据缓冲器中读出数据

② 数据发送过程

MCU将要发送的数据写入输出数据缓冲器,输出数据缓冲器在将数据写入串行输出移位寄存器,串行移位寄存器在将数据输出到外部设备


3、 串行通信的编程

3.1、串口通信的相关寄存器

3.1.1、 USART_SR状态寄存器

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);


3.1.2、 USART_DR数据寄存器

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

uint16_t USART_ReceiveData(USART_TypeDef* USARTx);


3.1.3、 USART_BRR波特率寄存器

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);


波特率计算方法:



3.2、 串口操作相关库函数(省略入口函数):

**void USART_Init();** //串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能

**void USART_Cmd();**//使能串口

**void USART_ITConfig();**//使能相关中断


**void USART_SendData();**//发送数据到串口,DR

**uint16_t USART_ReceiveData();**//接受数据,从DR读取接受到的数据


**FlagStatus USART_GetFlagStatus();**//获取状态标志位

**void USART_ClearFlag();**//清除状态标志位

**ITStatus USART_GetITStatus();**//获取中断状态标志位

**void USART_ClearITPendingBit();**//清除中断状态标志位


3.3、 串口配置一般步骤:

串口时钟使能,GPIO时钟使能:RCC_APB2PeriphClockCmd();

串口复位:USART_DeInit(); 这一步不是必须的

GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF_PP

串口参数初始化:USART_Init();

开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤) NVIC_Init();

USART_ITConfig();

使能串口:USART_Cmd();

编写中断处理函数:USARTx_IRQHandler();

串口数据收发:

void USART_SendData();//发送数据到串口,DR

uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据

串口传输状态获取:

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);

void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

4、 串口编程

(参照3.2、3.3的章节,其中有关于代码配置的步骤)

usart.c


//串口1中断服务程序

u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.

//接收状态

//bit15, 接收完成标志

//bit14, 接收到0x0d

//bit13~0, 接收到的有效字节数目

u16 USART_RX_STA=0;       //接收状态标记   

  

void uart_init(u32 bound)

{

  //GPIO端口设置

  GPIO_InitTypeDef GPIO_InitStructure;

  USART_InitTypeDef USART_InitStructure;

  NVIC_InitTypeDef NVIC_InitStructure;

 

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟

 

//USART1_TX   GPIOA.9

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出

  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9

   

  //USART1_RX   GPIOA.10初始化

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入

  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  


  //Usart1 NVIC 配置

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

  

   //USART 初始化设置


USART_InitStructure.USART_BaudRate = bound;//串口波特率

USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式

USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位

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);                    //使能串口1 


}


void USART1_IRQHandler(void)                //串口1中断服务程序

{

u8 Res;

    #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.

OSIntEnter();


关键字:STM32F103  串口通信 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机中高阻态的实质及意义