STM32——USART串口通信详解

串口通信协议简介

我们先来看一下RS-232与TTL电平的区别

请添加图片描述

我们通常说的TTL电平,就是直接从单片机或直接从芯片中出来的。

从图中可以看到,TTL电平里的1是由+5V来表示的,而RS232串口中的1是由-15V来表示的,于TTL电平表示的逻辑正好相反。

由于RS232协议中峰值相差30V,所以容错能力非常强,在工业设备通信中应用比较广泛。

RS232标准

下面我们来看一下RS232标准串口通讯结构图

请添加图片描述

控制器发出来的TTL电平需要经过一个电平转换芯片,才能使用RS232标准传输数据。

请添加图片描述

我们常使用DB9中的2针脚和3针脚,最多再接个5针脚

USB转串口

我们来看一下USB转串口的通讯结构图

请添加图片描述

USB转串口主要用于设备跟电脑通信

原生的串口到串口

原生的串口通信主要是控制器跟串口的设备或者传感器通信,不需要经过电平转换芯片来转换电平,直接就用TTL电平通信。

请添加图片描述

串口数据包的基本组成

**起始位:**由1个逻辑0的数据位表示

**结束位:**由0.5、1、1.5或2个逻辑1的数据位表示

**有效数据:**在起始位后紧接着的就是有效数据,有效数据的长度常被约定为5、6、7或8位长。

**校验位:**可选,为的是提高数据的抗干扰性

请添加图片描述

两个设备在进行通信前,双方需要先约定好起始位和结束位。

STM32 USART串口通信

我们先来看一下STM32串口功能框图。

请添加图片描述

我们先把串口的功能框图分为4部分来分析,

引脚

先来看串口通信的引脚,其中TX和RX是我们用得最多的两个引脚。
**TX:**数据发送
**RX:**数据接收

我们知道了每个引脚对应的功能了,接下来我们要查询串口对应的是哪一个GPIO

下面我们打开STM32F10x数据手册——Pinouts and pin description

请添加图片描述

从表中可以看到,串口1的时钟信号对应PA8引脚,发送端口对应PA9引脚,接收端口对应PA10引脚。

部分引脚具有复用功能,我们在配置时,可以通过查询这个表格来进行配置。

数据寄存器

下面我们讲第二部分,数据寄存器

**USART_DR:**9位有效,包含一个发送数据寄存器TDR和一个接收数据寄存器,一个地址对应了两个物理内存。
由于串口是全双工的,所以可以同时收发。

**数据位的长度(字长)**由USART1_CR1控制寄存器中的M位决定,如果M:0就是8bit,反之9bit

停止位由USART1_CR2控制寄存器中的STOP来决定

校验位由USART1_CR1控制寄存器中的PCE、PS、PEIE来决定,如果校验出错,由PEIE来进行中断使能。再由USART_SR状态寄存器中的PE来产生中断

我们接下来需要重点掌握数据的发送和数据的接收流程是怎么样的。

使能信号

首先,我们通过串口控制寄存器USART_CR1中的UE来给串口使能。

然后,我们需要通过串口控制寄存器中的TERE位,来进行发送使能和接收使能。

上面两个都打开以后,串口才能正常地发送和接收数据。

发送流程

请添加图片描述

数据从CPU或者DMA过来以后,先放到发送数据寄存器(TDR),然后再放到发送移位寄存器,再一位一位地通过TX端口发送出去。

这个过程中的状态改变会涉及到两个寄存器发生变换,一个是当数据从发送数据寄存器转移到发送移位寄存器时,TXE(Transmit empty)寄存器会置1,意味着发送寄存器为空,这个时候数据还在发送移位寄存器中,并没有发送出去,当发送移位寄存器把数据全部通过TX端口发送出去后,另外一个寄存器TC(Transmit complete)会置1。

请添加图片描述

接收流程

请添加图片描述

首先,数据从RX引脚过来,再放到接收移位寄存器,然后再放到接收数据寄存器(RDR),当数据放到接收数据寄存器以后,会有一个寄存器RXNE(Read data register not empty)置1,当我们检测到RXNE寄存器为1时,就可以读取数据了。

波特率——每秒钟要发送多少数据

USART_BRR:通过波特率寄存器来控制

波特率的计算需要结合外设挂载的时钟来看。在设置波特率时,我们常用的波特率有115200、9600等。

我们为了得到这个波特率,需要通过一个公式的计算

请添加图片描述

从上面公式可以看出,我们还需要算出USARTDIV的值并存到USART_BRR寄存器中去。整数部分存在整数的寄存器中,小数部分存在小数的寄存器中就行了。


那么,理论部分已经全部讲完了,下面我们来看看代码部分,其实就是把上面说的数据发送过程和数据接收过程用代码来描述出来就行了。

主要内容分为两个实验来讲解:

中断接收和发送

实现功能:

  1. 单片机给电脑发送数据,电脑上位机把数据打印出来。
  2. 电脑上位机给单片机发送数据,单片机接收到数据之后立马返回给电脑,并打印出来。

编程步骤:

  1. 初始化串口需要用到的GPIO

​ 本次实验使用USART1来做演示,通过查看图8,可以发现,USART1对应的发送引脚和接收引脚分别为PA9和PA10,所以我们先对这两个GPIO进行初始化。

void USART_GPIO_Config()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    // 打开GPIO的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 将USART Tx的GPIO配置为推挽复用模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 将USART Rx的GPIO配置为浮空输入模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}
  1. 初始化串口,USART_InitTypeDef
void USART_Config(void)
{
    
    USART_InitTypeDef USART_InitStructure;

    // 打开串口外设的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    // 配置串口的工作参数
    // 配置波特率
    USART_InitStructure.USART_BaudRate = 115200;

    // 配置针数据字长
    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);

    // 串口中断优先级配置
    NVIC_Configuration(); // 串口接收数据控制LED灯不需要用到中断。

    // 使能串口接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    // 使能串口
    USART_Cmd(USART1, ENABLE);
}
  1. 中断配置(接收中断,中断优先级)
static void NVIC_Configuration(void)
{

    NVIC_InitTypeDef NVIC_InitStructure;
    // 嵌套向量中断控制器组选择
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    // 配置USART为中断源
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

    // 抢断优先级
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

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

    // 使能中断
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    // 初始化配置NVIC
    NVIC_Init(&NVIC_InitStructure);
}
  1. 使能串口
  	// 使能串口
    USART_Cmd(USART1, ENABLE);
  1. 编写发送和接收函数
// 发送一个字节
void Usart_SendByte(USART_TypeDef *pUSARTx, u8 data)
{
    USART_SendData(pUSARTx, data);
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
        ;
}

// 发送两个字节
void Usart_SendHalfWord(USART_TypeDef *pUSARTx, u16 data)
{
    u8 temp_h, temp_l;
    temp_h = (data & 0xff00) >> 8;
    temp_l = (data & 0xff);
    USART_SendData(pUSARTx, temp_h);
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
        ;
    USART_SendData(pUSARTx, temp_l);
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
        ;
}

// 发送8位数据的数组
void Usart_SendArray(USART_TypeDef *pUSARTx, u8 *array, u8 num)
{
    u8 i;
    for (i = 0; i < num; i++)
    {

        Usart_SendByte(pUSARTx, array[i]);
    }
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
        ;
}

// 发送字符串
void Usart_SendStr(USART_TypeDef *pUSARTx, u8 *str)
{
    u8 i = 0;
    do
    {
        Usart_SendByte(pUSARTx, *(str + i));
        i++;
    } while (*(str + i) != '\0');
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
        ;
}
  1. 编写中断服务函数
void USART1_IRQHandler(void)
{
  u8 ucTemp;//定义一个临时变量,用来存储串口接收到的数据
  if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
    ucTemp = USART_ReceiveData(USART1);
    USART_SendData(USART1, ucTemp);//把接收到的数据通过串口再发回去
  }
}

串口控制RGB灯亮灭

实现功能:

  1. 电脑给单片机发命令,用于控制开发板上的RGB灯。

编程步骤

  1. 初始化串口需要用到的GPIO

​ 与上面的实验类似,我们需要先配置串口发送和接收引脚对应的GPIO,不同的是,我们还需要配置LED灯的GPIO,因为我们要通过LED灯的亮灭来展示实验现象。

​ 串口发送和接收引脚对应的GPIO我就不配置了,上面实验配置的代码一模一样,我只配置LED的GPIO。

void GPIO_Green_Config()
{
    GPIO_InitTypeDef GPIO_initStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_initStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_initStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_initStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_initStruct);
}
void GPIO_Red_Config()
{
    GPIO_InitTypeDef GPIO_initStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_initStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_initStruct.GPIO_Pin = GPIO_Pin_5;
    GPIO_initStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_initStruct);
}
void GPIO_Blue_Config()
{
    GPIO_InitTypeDef GPIO_initStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_initStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_initStruct.GPIO_Pin = GPIO_Pin_1;
    GPIO_initStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_initStruct);
}
  1. 初始化串口

初始化串口的代码与上面实验相同,仅仅去掉中断部分。

  1. 使能串口

上同。

  1. 编写发送函数

我们向串口发送1时,让LED亮绿灯,发送2时亮红灯,发送3时,亮蓝灯。

while (1)
    {
        ch = getchar();
        printf("ch=%c\n", ch);
        switch (ch)
        {
        case '1':
            GPIO_ResetBits(GPIOB, GPIO_Pin_0);
            GPIO_SetBits(GPIOB, GPIO_Pin_1);
            GPIO_SetBits(GPIOB, GPIO_Pin_5);
            break;

        case '2':
            GPIO_ResetBits(GPIOB, GPIO_Pin_1);
            GPIO_SetBits(GPIOB, GPIO_Pin_0);
            GPIO_SetBits(GPIOB, GPIO_Pin_5);
            break;
        case '3':
            GPIO_ResetBits(GPIOB, GPIO_Pin_5);
            GPIO_SetBits(GPIOB, GPIO_Pin_0);
            GPIO_SetBits(GPIOB, GPIO_Pin_1);
            break;

        default:
            break;
        }
    }

欢迎关注微信公众号:计算机达人

请添加图片描述

  • 20
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
首先,我们需要了解一下USART串口DMA的基本概念。 USART是一种通用异步收发传输器,常用于串行通信。USART可以通过DMA传输数据,通过DMA传输数据可以减轻CPU的负担,提高系统性能。 接下来,我们来详细介绍USART串口DMA的接收和发送流程。 1. 串口DMA发送流程: (1)配置USART:首先需要配置USART的工作模式、波特率、发送数据长度等参数,并使能USART发送功能。 (2)配置DMA:配置DMA通道,设置DMA传输模式、数据长度、传输方向等参数,并使能DMA传输功能。 (3)准备数据:将要发送的数据存放在发送缓冲区中。 (4)启动DMA传输:通过调用DMA传输函数启动DMA传输。 (5)等待传输完成:等待DMA传输完成,并检查传输是否成功。 2. 串口DMA接收流程: (1)配置USART:首先需要配置USART的工作模式、波特率、接收数据长度等参数,并使能USART接收功能。 (2)配置DMA:配置DMA通道,设置DMA传输模式、数据长度、传输方向等参数,并使能DMA传输功能。 (3)准备缓冲区:设置接收缓冲区,并开启接收中断。 (4)启动DMA传输:通过调用DMA传输函数启动DMA传输。 (5)等待传输完成:等待DMA传输完成,并检查传输是否成功。 (6)数据处理:当DMA传输完成后,处理接收到的数据。 以上就是USART串口DMA接收和发送流程的详细介绍。需要注意的是,在实际应用中,还需要根据具体的需求做相应的配置和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamerForLife

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值