STM32(8):USART串口应用

通信方式背景知识

处理器与外部设备通信的两种方式:
并行通信
-传输原理:数据各个位同时传输。
-优点:速度快
-缺点:占用引脚资源多

串行通信
-传输原理:数据按位顺序传输。
-优点:占用引脚资源少
-缺点:速度相对较慢
对于大部分的芯片,在通信方面节省IO,所以串口作为 MCU 的重要外部接口, 同时也是软件开发重要的调试手段, 其重要性不言而喻。
现在基本上所有的 MCU 都会带有串口。而STM32F407ZGT6 最多可提供 6 路串口。
串行通信按传送方向分:
a.单工:
数据传输只支持数据在一个方向上传输(收音机、遥控器)
b.半双工:
允许数据在两个方向上传输,但是,在某一时刻,只允许数
据在一个方向上传输,它实际上是一种切换方向的单工通信;(对讲机)
c.全双工:
允许数据同时在两个方向上传输,因此,全双工通信是两个
单工通信方式的结合,它要求发送设备和接收设备都有独立
的接收和发送能力。(电话机)
STM32(8):USART串口应用
串行通信的通信方式
同步通信:带时钟同步信号传输。
-SPI,IIC通信接口
异步通信:不带时钟同步信号。
-UART(通用异步收发器),单总线
STM32(8):USART串口应用

UART异步通信方式特点:
全双工异步通信。
小数波特率发生器系统,提供精确的波特率。
可配置的16倍过采样或8倍过采样,因而为速度容差与时钟容差的灵活配置提供了可能。
可编程的数据字长度(8位或者9位);
可配置的停止位(支持1或者2位停止位);
可配置的使用DMA多缓冲器通信。
单独的发送器和接收器使能位。
检测标志:① 接收缓冲器 ②发送缓冲器空 ③传输结束标志
多个带标志的中断源。触发中断。
其他:校验控制,四个错误检测标志。

STM32串口通信

STM32串口通信过程:
STM32(8):USART串口应用

STM32串口通信–帧格式

STM32串口异步通信定义的参数传送格式:
起始位
数据位(8位或者9位)
奇偶校验位(第9位)
停止位(1,1.5,2位)
波特率设置
STM32(8):USART串口应用

STM32(8):USART串口应用
起始位:发送器是通过发送起始位而开始一个字符的传送。起始位使数据线处于“space”状态
数据位:起始位之后就传送数据位。在数据位中,低位在前(左),高位在后(右)。由于字符编码方式的不同,数据位可以是5、6、7或8位。
奇偶校验位:用于对字符传送作正确性检查,因
此奇偶校验位是可选择的,共有3种可能,即奇校验、偶校验和无校验,由用户根据需要选定。
停止位:停止位在最后,用以标志一个字符传送的结束,它对应于mark状态。停止位可能是1、1.5或2位,在实际应用中根据需要确定

串行通信的传送速率:在串行通信中,数据是按位进行传送的,因此传送速率用每秒钟传送格式位的数目来表示,称之为波特率(band rate)。每秒传送一个格式位就是1波特。
1波特=1bps(位/秒)
RS-232-C标准规定的数据传输速率为每秒 50、75、100、150、300、600、1200、2400、4800、9600、19200、115200等波特率。

STM32串口通信之RS-232

开发板利用RS-232实现上位机与下位机的通信:
RS-232是美国电子工业协会EIA(Electronic Industry Association)制定的一种串行物理接口标准
RS-232C 对电器特性、逻辑电平和各种信号线功能都作了规定。
在TxD和RxD上:
逻辑1 = -3V~-15V
逻辑0 = +3~+15V
STM32(8):USART串口应用

RS-232
CH340G实现的USB转RS232串口
硬件接线图:
STM32(8):USART串口应用

串口通信的配置步骤

串口设置的一般步骤可以总结为如下几个步骤:

  1. 串口时钟使能,GPIO 时钟使能。
  2. 设置引脚复用器映射:调用 GPIO_PinAFConfig 函数。
  3. GPIO 初始化设置:要设置模式为复用功能。
  4. 串口参数初始化:设置波特率,字长,奇偶校验等参数。
  5. 开启中断并且初始化 NVIC,使能中断(如果需要开启串口中断才需要这个步骤)。
  6. 使能串口。
  7. 编写中断处理函数:函数名格式为 USARTx_IRQHandler(x 对应串口号)

串口通信的使用1

以开发板的串口1为例:

  1. 串口时钟和GPIO时钟使能
    A. 串口是挂载在 APB2 下面的外设,所以使能函数为
    //使能 USART1 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    B. 使用的是串口 1,串口 1 对应着芯片引脚 PA9,PA10 需要使能PA的时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
  2. 设置引脚复用器映射
    引脚复用器映射配置,需要配置PA9,PA10 的引脚,调用函数为:
    //PA9 复用为 USART1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
    //PA10 复用为 USART1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
  3. GPIO 端口模式设置:PA9 和 和 PA10 要设置为复用功能
    GPIO_InitTypeDef GPIO_InitStructure;
    //GPIOA9 与 GPIOA10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    //配置IO口复用功能
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    //速度 50MHz
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    //推挽复用输出
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    //上拉
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    //初始化 PA9,PA10
    GPIO_Init(GPIOA,&GPIO_InitStructure);
  4. 串口参数初始化:设置波特率,字长,奇偶校验等参数
    USART_InitTypeDef USART_InitStructure;
    //一般设置为 9600;
    USART_InitStructure.USART_BaudRate = bound;
    //字长为 8 位数据格式
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    //一个停止位
    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);
  5. 使能串口
    使能串口调用函数 USART_Cmd 来实现,具体使能串口 1 方法如下:
    //使能串口
    USART_Cmd(USART1, ENABLE);
  6. 串口数据发送与接收(程序中调用函数)。
    STM32F4 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存在该寄存器内。
    A. STM32 库函数操作 USART_DR 寄存器发送数据的函数是:
    通过该函数向串口寄存器 USART_DR 写入一个数据。
    void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
    B.STM32 库函数操作 USART_DR 寄存器读取串口接收到的数据的函数是:
    通过该函数可以读取串口接受到的数据。
    uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
  7. 串口状态读取相关
    串口的状态可以通过状态寄存器 USART_SR 读取。在固件库函数里面,读取串口状态的函数是:
    FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);

这个函数的第二个入口参数非常关键,标示串口的状态,
这些状态的标示符在 MDK 里面是通过宏定义定义的:
#define USART_IT_PE ((uint16_t)0x0028) //
#define USART_IT_TC ((uint16_t)0x0626) //判断是否发送完成
#define USART_IT_RXNE ((uint16_t)0x0525) //读数据操作时,判断寄存器是否非空
#define USART_IT_NE ((uint16_t)0x0260)
#define USART_IT_FE ((uint16_t)0x0160)

例如我们要判断读寄存器是否非空(RXNE),操作库函数的方法是:
USART_GetFlagStatus(USART1, USART_FLAG_RXNE);
我们要判断发送是否完成(TC),操作库函数的方法是:
USART_GetFlagStatus(USART1, USART_FLAG_TC);
函数会返回值,值为1时,则为真。
8) 若需要中断,则开启中断并且初始化 NVIC ,使能相应中断
这一步如果我们要开启串口中断才需要配置 NVIC 中断优先级分组。通过调用函数NVIC_Init 来设置。
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
//抢占优先级 3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
//响应优先级 3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;
//IRQ 通道使能
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//根据指定的参数初始化 VIC 寄存器
NVIC_Init(&NVIC_InitStructure);
//同时,需要使能相应中断,使能串口中断的函数是:
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,
FunctionalState NewState)
第二个入口参数是标示使能串口的类型,中断类型,比如在接收到数据的时候(RXNE 读数据寄存器非空) ,产生中断:
//开启中断,接收到数据中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
发送数据结束的时候(TC,发送完成)要产生中断,则为:
USART_ITConfig(USART1,USART_IT_TC,ENABLE);

  1. 获取相应中断状态
    当我们使能了中断的时候,当该中断发生了,就会设置状态寄存器中的某个标志位。
    经常我们在中断处理函数中,要判断该中断是哪种中断,使用的函数是:
    ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)
    比如使能了串口发送完成中断, 那么当中断发生了, 可以在中断处理函数中调用这个函数来判断到底是否是串口发送完成中断,方法是:
    USART_GetITStatus(USART1, USART_IT_TC)
    返回值是 1,说明是串口发送完成中断发生。
  2. 中断服务函数
    串口 1 中断服务函数(可以在.s启动文件找到,而且不能任意起名)为:
    void USART1_IRQHandler(void) ;
    当发生中断的时候,程序就会执行中断服务函数。然后在中断服务函数中编写相应的处理的逻辑代码即可。

STM32(8):USART串口应用利用串口中断应用举例:

USART中断接收
void USART1_IRQHandler(void)
{
//若是非空,则返回值为1,与RESET(0)判断,不相等则判断为真
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
//判断为真后,为下次中断做准备,则需要对中断的标志清零
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
/* DR读取接受到的数据*/
Usart_Data = USART_ReceiveData(USART1);
//然后把接收到的数据返回送到发送端
USART_SendData(USART1, Usart_Data);
}
}

串口通信初始化

1、数据长度
USART_WordLength_8b USART_WordLength_9b

2、停止位
USART_StopBits_1 USART_StopBits_0_5 USART_StopBits_2 USART_StopBits_1_5

3、奇偶校验位
USART_Parity_No USART_Parity_Even
USART_Parity_Odd

4、硬件流控
USART_HardwareFlowControl_None
USART_HardwareFlowControl_RTS
USART_HardwareFlowControl_CTS
USART_HardwareFlowControl_RTS_CTS

串口通信的库函数总结

串口操作相关库函数:
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(); //清除串口中断状态标志位
中断入口函数有:
void USARTx_IRQHandler();
x = 1~6