通信方式

1、串行通信和并行通信

串行通信

速度比并行通信慢,但是占用的硬件资源少,通常只需要时钟线,一到两根数据线和片选线即可。如图所示,发送端和接收端只需要一根时钟线和一根数据线即可通信

并行通信

速度快,但是需要较多硬件资源,负责数据线、地址线等。如下图所示,发送端要发送一个8bits的数据需要用到至少要8根数据线

2、全双工,半双工和单工通信

全双工

同一时刻通信双方可以同时发送、接收数据

半双工 

同一时刻只有一方可以发送数据,另一方只能接收数据

单工

 只能有发送端发送数据,接收端只负责接收数据

 3、同步通信和异步通信

同步异步都是针对串行通信而言

异步通信

1、数据以字符为单位组成字符帧传输

2、由发射端一帧一帧发送,每帧数据都是低位在前,高位在后

3、发送端和接收端可以有各自的独立时钟控制发送和接收,两个时钟各自独立,互不干扰

4、接收端依靠字符帧格式判断发送端从何时开始和结束发送

5、字符帧也叫数据帧,包括起始位,数据位,奇偶校验位,停止位等,属于异步通信的重要指标

6、异步通信的另一个重要指标是波特率。

同步通信

1、同步意为在约定的通信速率下,发送端和接收端时钟信号和相位始终保持一致,保证双方在发送和接收数据具有完全一致的定时关系

2、同步通信把许多字符组成信息帧,每帧开始用同步字符表示

3、多数情况下,同步通信的发送端和接收端采用同一个时钟信号。因此在传输数据时还要发送时钟信号,以便接收端和发送端可以使用用一个时钟信号确定每个信息位

4、同步通信每次通信只能传输一帧信息

4、通信速率

对于同步通信,通信速率由时钟信号决定,时钟信号越快,传输速率越快

对于异步通信,需要发送端和接收端提前统一通信速率,也就是为什么在调试过程中,波特率不同会显示乱码。

比特率:单位时间内传输的二进制bits(二进制0/1)个数,通常用Rb表示,单位是bit/s,缩写bps

波特率:单位时间内传输的码元个数,通常用RB表示,单位是Bd

码元有N个状态时,比特率和波特率之间的关系:RB=Rb X log2N

5、常见的通信协议

串口基础知识

1、电平特性

传输距离较短一般用TTL做通信信号

距离较长时,就需要转换成其他电平信号才能支持远距离传输

2、串口传输协议

设备串口连接示意图

TXD:数据发送端

RXD:数据接收端

GND:地。保证发送端与接收端有一个共同的参考电平

相关参数

波特率:一般波特率有9600,19200,115200等,意为每秒传输的比特数bits

起始位:先发出一个逻辑‘0’表示传输数据的开始

数据位:可以是5-8位逻辑‘0’或‘1’,先传输bit0,再传输bit1,以此类推,从低位开始传输

校验位:数据位加上校验位,使‘1’的位数应为奇数(奇校验)或偶数(偶校验),以此校验数据传输正确性,校验位可选可不选

停止位:字符数据的结束标志,数据线变回逻辑‘1’

3、STM32F103 USART资源

1、STM32F103有三个通用同步异步收发器USART,两个通用异步收发器UART。USART可以当做UART使用

2、常用的是UART,USART也会使用,通信方式取决于通信场合

3、可以通过电平转换芯片使TTL转化为RS232/RS485

STM32F103 USART框图

端口引脚

TX:数据发送端

RX:数据接收端

SW_RX:单线和智能卡模式下接收数据,属于内部端口,没有实际外部引脚

RTS:在硬件流控制下用于指示准备好接收数据,低电平表示可以接收数据

CTS:在硬件流控制下用于指示设备以及发送完数据,如果是高电平那么本次数据发送完后阻塞下一次传输,只有在低电平才允许下一次传输

SCLK:同步时钟端口,在同步通信模式下使用,用于输出同步时钟信号

数据寄存器

TDR:发送数据寄存器

RDR:接收数据寄存器

UART外设中还有一个双向寄存器YSART_DR,取决于CPU是读寄存器还是写寄存器

发送接收控制单元

CR1/CR2/CR3:控制寄存器,控制各种使能,如UART使能,收发中断使能

SR:状态寄存器,表明UART收发状态和错误状态

GTPR:Smartcard(智能卡)和IrDA(红外通信)模式庄勇寄存器

波特率发生器

fPCLK:外设时钟总线,USART1在APB2,最高可取72MHz,其余四个在APB1,最高可取36MHz

USARTDIV:USART/UART时钟分频器

DIV_Mantissa:BBR寄存器高12位,用于存放波特率设置整数部分

DIV_Fraction:BRR寄存器低4位,用于存放波特率设置小数部分,每一位对应精度是0.5的四次方=0.0625

波特率计算公式:波特率=fPCLK/USARTDIV*16

假设fPCLK = 72MHZ,baudrate = 115200,那么USARTDIV=72MHZ/16/115200 =39.0625,则DIV_Mantissa = 39<<4 = 0x270,DIV_Fraction=0.0625/0.0625=1,因此BRR= 0X271

UART配置步骤

1、选择需要使用的USART/UART

2、根据波特率配置BRR寄存器

3、配置控制寄存器停止位和校验位

4、配置同步时钟使能

5、使能USART发送端和接收端

6、使能发送和接收中断位

7,、使能RCC,选择USART/UART的时钟

8、使能USART/UART

9、写USART_DR寄存器发送数据,读USART_DR寄存器接收数据

程序代码

创建Usart文件夹,内部新建Usart.c和Usart.h

导入keil工程文件,创建void Usart_Init(void)函数

初始化GPIO

通过电路图可以知道,TXD连接PA9引脚,RXD连接PA10引脚,因此需要初始化两个GPIO引脚。与此同时,因为PA9和PA10是作为串口作用的,而不是简单的输出输入高低电平,还需要在中文手册里查看外设的GPIO配置。如下图所示

当使用串口时,输出数据TX时采用的是复用推挽输出模式,输入数据RX时采用的是浮空输入或者上拉输入。因此可以得出以下配置表格

GPIO 对应引脚 模式
GPIOA PA9 复用推挽输出
GPIOA PA10 浮空输入或上拉输入

 GPIO配置代码如下

    GPIO_InitTypeDef Usart_GPIO_Struct;

    //PA9 TXD
    Usart_GPIO_Struct.GPIO_Mode = GPIO_Mode_AF_PP;
    Usart_GPIO_Struct.GPIO_Pin = GPIO_Pin_9;
    Usart_GPIO_Struct.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_Init(GPIOA,&Usart_GPIO_Struct);
    
    //PA10 RXD
    Usart_GPIO_Struct.GPIO_Mode = GPIO_Mode_IPU;
    Usart_GPIO_Struct.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA,&Usart_GPIO_Struct);

同样还需要初始化GPIO和串口时钟信号

使用的是UASRT1串口,通过系统架构框图可以知道USART1同样依附在总线APB2,所以可以同步使能GPIOA和USART1时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); 

 然后是对串口USART1进行初始化

USART结构包括BaudRate 波特率、WordLength 数据长度、StopBits 停止位、Parity 校验位、Mode 模式、HardwareFlowControl 硬件流控制。

波特率设置为115200

数据长度设置为8位

停止位取1位

校验位不使用

模式选择发送数据Tx

硬件流控制设置为None

初始化完成后,同样需要进行应用配置

最后还需要启动串口通信

程序代码如下

USART_InitTypeDef Usart_USART_Struct;

Usart_USART_Struct.USART_BaudRate = 115200;

Usart_USART_Struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

Usart_USART_Struct.USART_Mode = USART_Mode_Tx;
Usart_USART_Struct.USART_Parity = USART_Parity_No;
Usart_USART_Struct.USART_StopBits = USART_StopBits_1;
Usart_USART_Struct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&Usart_USART_Struct);
USART_Cmd(USART1,ENABLE);

Usart.c整体代码如下

#include "stm32f10x.h"
#include "Usart.h"

void Usart_Init(void)
{
    GPIO_InitTypeDef Usart_GPIO_Struct;
    USART_InitTypeDef Usart_USART_Struct;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
    
    
    //PA9 TXD
    Usart_GPIO_Struct.GPIO_Mode = GPIO_Mode_AF_PP;
    Usart_GPIO_Struct.GPIO_Pin = GPIO_Pin_9;
    Usart_GPIO_Struct.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_Init(GPIOA,&Usart_GPIO_Struct);
    
    //PA10 RXD
    Usart_GPIO_Struct.GPIO_Mode = GPIO_Mode_IPU;
    Usart_GPIO_Struct.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA,&Usart_GPIO_Struct);
    
    
    Usart_USART_Struct.USART_BaudRate = 115200;
    Usart_USART_Struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    Usart_USART_Struct.USART_Mode = USART_Mode_Tx;
    Usart_USART_Struct.USART_Parity = USART_Parity_No;
    Usart_USART_Struct.USART_StopBits = USART_StopBits_1;
    Usart_USART_Struct.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART1,&Usart_USART_Struct);
    USART_Cmd(USART1,ENABLE);
    
    
}

main.c发送数据用到的函数为USART_SendData,从源文件可以发现函数包含两个参数:串口和数据。串口就选择使用的USART1,但是传输的数据仅限于uint_t 无符号16位整型,因此无法传输字符串。

代码如下

#include"stm32f10x.h"
#include"main.h"
#include"led.h"
#include"bear.h"
#include"button.h"
#include"Relay.h"
#include"Shake.h"
#include"433M.h"
#include"EXTI.h"
#include"Usart.h"


 

int main()
{
    
    Usart_Init();
    

    
    while(1)
    {
        
        
        USART_SendData(USART1,'A');
         
        
    }
    
    
    
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐