Stm32学习—USART1收发数据

lichongyang
lichongyang
lichongyang
94
文章
0
评论
2019年8月28日17:57:47 评论 173 次浏览

1、USART简介

   通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。
   STM32 的串口资源相当丰富的,功能也相当强劲。比如STM32F103ZET6 最多可提供 5 路串口,有分数波特率发生器,支持同步单向通信和半双工单线通信,支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。使用多缓冲器配置的DMA方式,可以实现高速数据通信。

2、USART功能概述

接口通过三个引脚与其他设备连接在一起。任何USART双向通信至少需要两个脚:接收数据
 输入(RX)和发送数据输出(TX)。
 RX:接收数据串行输。通过过采样技术来区别数据和噪音,从而恢复数据。 TX:发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,
 并且不发送数据时,TX引脚处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据的发送
 和接收。
 串口外设主要由三个部分组成,分别是波特率的控制部分、收发控制部分及数据存储转移部分。
   1、波特率控制
    波特率,即每秒传输的二进制位数,用 b/s (bps)表示,通过对时钟的控制可以改变波特率。
 在配置波特率时,我们向波特比率寄存器 USART_BRR 写入参数,修改了串口时钟的分频值 
 USARTDIV。USART_BRR 寄存器包括两部分,分别是 DIV_Mantissa(USARTDIV 的整数部分)和
 DIVFraction(USARTDIV的小数)部分,最终,计算公式为:
             USARTDIV=DIV_Mantissa+(DIVFraction/16)。
   2、分数波特率的产生
     接收器和发送器的波特率在USARTDIV的整数和小数寄存器中的值应设置成相同。
             Tx / Rx 波特率 =fCK/(16*USARTDIV)
   这里的fCK是给外设的时钟(PCLK1用于USART2、3、4、5,PCLK2用于USART1) USARTDIV是
 一个无符号的定点数。这12位的值设置在USART_BRR寄存器。
     注: 在写入USART_BRR之后,波特率计数器会被波特率寄存器的新值替换。因此,不要在通信
 进行中改变波特率寄存器的数值。
     USARTDIV 是对串口外设的时钟源进行分频的,对于 USART1,由于它是挂载在 APB2 总线上    
 的,所以它的时钟源为 fPCLK2;而 USART2、3 挂载在APB1 上,时钟源则为 fPCLK1,串口的
 时钟源经过 USARTDIV 分频后分别输出作为发送器时钟及接收器时钟,控制发送和接收的时序。 
 3、收发控制 围绕着发送器和接收器控制部分,有好多个寄存器:CR1、CR2、CR3、SR,即 USART 的
 三个控制寄存器(Control Register)及一个状态寄存器(Status Register)。通过向寄存器
 写入各种控制参数,来控制发送和接收,如奇偶校验位,停止位等,还包括对 USART 中断的
 控制;串口的状态在任何时候都可以从状态寄存器中查询得到。具体的控制和状态检查,我们
 都是使用库函数来实现的,在此就不具体分析这些寄存器位了。
 4、数据存储转移部分
   收发控制器根据我们的寄存器配置,对数据存储转移部分的移位寄存器进行控制。
     当我们需要发送数据时,内核或 DMA 外设(一种数据传输方式,在下一章介绍)把数据从内存
 (变量)写入到发送数据寄存器 TDR 后,发送控制器将适时地自动把数据从 TDR 加载到发送移位寄
 存器,然后通过串口线 Tx,把数据一位一位地发送出去,在数据从 TDR 转移到移位寄存器时,会
 产生发送寄存器TDR 已空事件 TXE,当数据从移位寄存器全部发送出去时,会产生数据发送完成事
 件 TC,这些事件可以在状态寄存器中查询到。
   而接收数据则是一个逆过程,数据从串口线 Rx 一位一位地输入到接收移位寄存器,然后自动
 地转移到接收数据寄存器 RDR,最后用内核指令或 DMA读取到内存(变量)中。

3、创建工程项目,勾选相应的固件库

CMSIS>CORE;Device>Startup;>StdPeriphDrivers>Flash;>Framework;>GPIO; >RCC;>USART等.

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

1)串口时钟使能,GPIO时钟使能;

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);

2)串口复位;

    当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。复位的是在函数 USART_DeInit()中完成:
    void USART_DeInit(USART_TypeDef* USARTx);//串口复位
比如要复位串口 1,方法为:
    USART_DeInit(USART1); //复位串口 1

3) GPIO端口模式设置;

<code>//PA9     //声明结构体   GPIO_InitTypeDef GPIO_InitStructure;      </code>
<code>//设置选择引脚  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;  </code>
<code>//设置引脚最大输出频率 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;  </code>
<code>//设置引脚输出模式——复用推挽输出 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;  </code>
<code>//根据设置的InitStructure初始化GPIO口     GPIO_Init(GPIOA,&GPIO_InitStructure); </code>
<code>//PA10 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;  </code>
<code>//设置引脚输出模式——浮空输入 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;  </code>
<code>//根据设置的InitStructure初始化GPIO口     GPIO_Init(GPIOA,&GPIO_InitStructure);</code>

4)串口参数初始化;

USART_InitTypeDef USART_InitStructure; 
USART_InitStructure.USART_BaudRate = Baudrate; //设置波特率     
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_Tx | USART_Mode_Rx;  //收发模式
USART_Init(USART1,&USART_InitStructure); //初始化串口1

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

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init (&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //开启串口接受完成中断
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); //开启串口空闲中断

6)使能串口;

USART_Cmd(USART1,ENABLE); //使能串口1

7)编写中断处理函数;

void USART1_IRQHandler(void)
{
  if((USART_GetITStatus(USART1,USART_IT_RXNE))!=RESET) //判断是否有中断
  {
    aRxbuffer[counter++] = USART_ReceiveData(USART1); //接收字符存入数组
    USART_ClearFlag(USART1,USART_IT_RXNE);	//清除中断标志位
  }
  else if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET)
  {
    USART1->SR;
    USART1->DR;
    counter = 0;
    if(memcmp((uint8_t*)aRxbuffer,(uint8_t *)aRxbuffCompare,BUFFERSIZE)==0)
    {
      Usart_SendString(USART1,(char *)aTxbuffer);
    }
    else
    {
      Usart_SendString(USART1,"Error");//(char *)aRxbuffer
    }
}
USART_ClearFlag(USART1,USART_IT_RXNE);	//清除中断标志位
}

5、参考链接

字符串清空方法
https://blog.csdn.net/caoshunxin01/article/details/79355064

STM32库函数USART配置
https://blog.csdn.net/cow825/article/details/51232154
https://blog.csdn.net/u012075442/article/details/50865644
https://blog.csdn.net/Ele_Dd/article/details/78162109
https://blog.csdn.net/dragon12345666/article/details/24883111
https://blog.csdn.net/T_zty_Y/article/details/79974470
https://www.cnblogs.com/microxiami/p/3752715.html
https://www.cnblogs.com/pertor/p/9488446.html
https://blog.csdn.net/u013002186/article/details/81429456

USART讲解:
https://blog.csdn.net/dragon12345666/article/details/24484185
https://blog.csdn.net/zxh1592000/article/details/78656609

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信小程序
  • 我的微信小程序扫一扫
  • weinxin
lichongyang
  • 本文由 发表于 2019年8月28日17:57:47
  • 转载请务必保留本文链接:https://www.chongyangli.com/archives/45
物联网的嵌入式编程 操作系统

物联网的嵌入式编程

嵌入式编程在使设备满足人们的需求方面具有悠久的历史。但是,它在很大程度上仍然被应用程序编程所掩盖。当应用程序程序员采用相对高级的面向对象的语言(如C ++或Java)或图形化应用程序开发环境(如MAT...
大家来说说自己对GPIO 浮空输入的理解 单片机

大家来说说自己对GPIO 浮空输入的理解

原子哥:顾名思义,浮空就是 浮在空中.也就是没有什么把他拉下来,也没有什么把它拉上去. 浮空最大的特点就是电压的不确定性,它可能是0V,也可能是VCC,还可能是介于两者之间的某个值...
FreeRTOS 系统时钟节拍和时间管理 操作系统

FreeRTOS 系统时钟节拍和时间管理

FreeRTOS 的时钟节拍 任何操作系统都需要提供一个时钟节拍,以供系统处理诸如延时、 超时等与时间相关的事件。时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳。 中断之间的时间间隔取决于不同...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: