10 通用同步异步收发器(USART)(下)

本文涉及的产品
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
数据传输服务 DTS,数据同步 1个月
简介: 10 通用同步异步收发器(USART)(下)

10.2.4 DMA控制

接收缓冲区和发送缓冲区的DMA请求是独立的,它们分别对应于独立的DMA通道。

1.使用DMA进行发送

将USART控制寄存器3(USART_CR3)中的DMAT位置1可以使能DMA模式进行发送。
一旦使能了USART的DMA功能,当TXE 位置1时,
控制器会将数据自动从SRAM区加载到USART_DR,启动发送过程。
所有数据的发送不需要通过程序干涉。

2.使用DMA进行接收

将USART_CR3中的DMAR位置1可以使能DMA模式进行接收。一旦使能了USART的DMA功能,当接收数据时,RXNE
位置1时,控制器会将数据会从USART_DR自动加载到SRAM区域中。整个数据的接受过程不需要程序的干涉。

10.3 USART典型应用步骤及常用库函数

10.3.1 串口配置一般步骤


10.3.2 常用库函数说明




10.4 应用实例

10.4.1 通过串口向计算机传输100个字节

使用串口线把计算机和电路板的USART1连接在一起,如图11-15所示。编写程序,通过USART1向计算机发送100个字节,这一功能可以通过查询方式、中断方式或中断方式实现。这里以常用的查询方式实现这一功能。

USART1配置参数:
波特率=115 200、
有效数据位=8位、
停止位=1位、
不使用校验方式、
收发模式、
不使用硬件流控。
USART1的TXD和RXD分别使用PA9和PA10。

1.编程要点

(1)使能USART1和复用引脚GPIO的工作时钟。
(2)初始化USART1 相关GPIO引脚,并将引脚复用给USART1。

(3)根据要求,初始化USART1。使用查询方式发送数据。
(4)使能USART1。
(5)循环发送100个字节。

2.主程序


    int main(void){               uint16_t  i;               /*初始化USART 配置模式为 115200 8-N-1,中断接收*/    USART1_Config();    for(i=0;i<100;i++)//循环发送100个x   {      /*发送一个字符x*/      USART_SendData(USART1, ‘x’);      /*等待发送数据寄存器为空 ,只有在发送数据寄存器为空的情况下,才能发送下一个字符*/      while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);              }      while(1);           }


    3. 串口配置函数


      void USART_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; /*-------------------第1步--------------------*/ /*使能 GPIOA时钟*/ RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA,ENABLE); /*使能 UART1 时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  /*-------------------第2步--------------------*/ /*复用PA9到USART1*/ GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); /*复用PA10到USART1*/ GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); /*配置TX引脚为复用功能*/ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用模式 GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure);   /*配置RX引脚为复用功能*/ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF ;            //复用模式 GPIO_Init(GPIOA,&GPIO_InitStructure); /*-------------------第3步--------------------*/ /*配置USART1模式*/ USART_InitStructure.USART_BaudRate = 115200; //波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;            //8位有效数据位 USART_InitStructure.USART_StopBits = USART_StopBits_1; //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);            //初始化USART1  /*因为使用查询方式发送数据,没有用到中断,因此没有中断相关配置,缺少第4步*/ /*-------------------第5步--------------------*/ USART_Cmd(USART1, ENABLE);//使能USART1}


      10.4.2 串口与计算机回显功能实现

      回显功能就是把计算机发送给电路板上微控制器的数据通过串口原样返回给计算机,并显示在串口显示软件中。
      USART1配置参数:
      波特率=115 200、
      有效数据位=8位、
      停止位=1位、
      不使用校验方式、
      收发模式、
      不使用硬件流控。

      USART1的TXD和RXD分别使用PA9和PA10。

      1.编程要点

      (1)使能USART1和复用引脚GPIO的时钟。
      (2)初始化USART1 相关GPIO引脚,并将引脚复用给USART1。
      (3)根据要求初始化USART1。
      (4)初始化NVIC的USART1串口中断通道,并使能USART1的读取数据寄存器不为空中断(RXNE)。
      (5)使能USART1。
      (6)编写中断服务程序。

      2.主程序


        int main(void){ USART_Config(); //初始化USART1 printf("这是一个串口中断接收回显实验\n");//注意只有对printf函数进行重定向才能使用 while(1);}


        3. 串口配置函数


          void USART_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; /*-------------------第1步--------------------*/ /*使能 GPIOA时钟*/ RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA,ENABLE); /*使能 UART1 时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  /*-------------------第2步--------------------*/ /*复用PA9到USART1*/ GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); /*复用PA10到USART1*/ GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); /*配置TX引脚为复用功能*/ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用模式 GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure);   /*配置RX引脚为复用功能*/ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF ;            //复用模式 GPIO_Init(GPIOA,&GPIO_InitStructure); /*-------------------第3步--------------------*/ /*配置USART1模式*/ USART_InitStructure.USART_BaudRate = 115200; //波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位有效数据位 USART_InitStructure.USART_StopBits = USART_StopBits_1; //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);            //初始化USART1 /*-------------------第4步--------------------*/ //初始化NVIC中的USART1中断通道 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择NVIC组2 NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn; //配置USART为中断源 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;           //响应优先级为1 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;            //使能中断  NVIC_Init(&NVIC_InitStructure); //初始化配置NVIC  //使能串口的RXNE中断 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //使能串口的RXNE中断  /*-------------------第5步--------------------*/ USART_Cmd(USART1,ENABLE);                      //使能USART1}


          4.串口中断服务函数


            void USART1_IRQHandler(void){    uint8_t ucTemp;    if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) //检测RXNE标志位    {                            ucTemp = USART_ReceiveData( USART1 ); //读取接收数据      USART_SendData(USART1,ucTemp);  //把数据发送给计算机,实现回显功能      }            }


            5. printf函数重定向

            使用printf函数通过USART1向计算机的串口调试助手打印数据,需要将printf函数内部实现功能重定向到微控制器的USART1。
            (1)设置Keil MDK软件中的Use MicroLIB选项。
            (2)重定向fputc函数。

            2)重定向fputc函数。

              int fputc(int ch, FILE* stream){//通过串级发送数据chUSART_SendData(USART1, (uint8_t) ch);      
              while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待发送完毕 
              return ch;}


              10.4.3 利用DMA通过串口向计算机1000个字节

              利用DMA通过USART1向计算机传输1000个字节,一旦配置好USART1和DMA数据流,在启动DMA传输之后,不需要程序的干预,即可完成数据传输

              USART1配置参数:波特率=115 200、有效数据位=8位、停止位=1位、不使用校验方式、收发模式、不使用硬件流控。

              1.编程要点

              (1)使能USART1、复用引脚GPIO及DMA2的时钟。
              (2)初始化USART1相关GPIO引脚,并将引脚复用给USART1。
              (3)根据要求,初始化并使能USART1。
              (4)初始化DMA2数据流7的通道4,并使能DMA2数据流7。
              (5)使能USART1的DMA发送功能,启动DMA数据传输。

              2、主程序


                uint8_t Send_Buff[1000]; //DMA传输数据源存储区int main(void){  uint16_t i;  USART_Config();                                   //初始化USART1  DMA_Config();                                                         //初始化DMA  for(i=0;i<SENDBUFF_SIZE;i++)            //初始化DMA传输数据源存储区  {    Send_Buff [i]            = 'Z';  }  /*使能USART1的DMA发送,启动DMA数据传输*/  USART_DMACmd(USART1, USART_DMAReq_Tx,ENABLE);           //关键  while(1);                                   //无须CPU干涉,实现数据传输}


                3. 串口配置函数

                同10.4.1串口配置函数。

                4. DMA配置函数


                  extern uint8_t Send_Buff[1000]; //DMA传输数据源存储区void DMA_Config(void){ DMA_InitTypeDef  DMA_InitStructure; /*-------------------第1步--------------------*/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE); //使能DMA2时钟   /*-------------------第2步--------------------*/ DMA_DeInit(DMA2_Stream7);            //复位,禁止DMA2数据流7  while (DMA_GetCmdStatus(DMA2_Stream7)!= DISABLE); //确保DMA数据流禁止成功  /*-------------------第3步--------------------*/ /*初始化DMA2数据流7*/  DMA_InitStructure.DMA_Channel=DMA_Channel_7; //选择通道  DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t) SRC_Buffer;//目标地址  DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t) Send_Buff; //源数据地址  DMA_InitStructure.DMA_DIR=DMA_DIR_MemoryToPeripheral; //存储器到外设模式  DMA_InitStructure.DMA_BufferSize=1000;            //DMA传输数据数目  //禁止自动递增功能  DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;            DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; //使能自动递增功能  //8位数据宽度  DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;  DMA_InitStructure.DMA_MemoryDataSize=DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_Mode=DMA_Mode_Normal; //正常模式,不循环,只传输一次 DMA_InitStructure.DMA_Priority=DMA_Priority_High;//设置DMA2数据流7优先级为高DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable; //禁用FIFO模式 //此时这一参数无用DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;            //单次模式DMA_InitStructure.DMA_PeripheralBurst=DMA_MemoryBurst_Single; //单次模式DMA_Init(DMA2_Stream7,&DMA_InitStructure); //完成DMA2数据流7配置 /*-------------------第4步--------------------*/ DMA_Cmd(DMA2_Stream7,ENABLE);            //使能DMA2数据流7,启动DMA数据传输   /*-------------------第5步--------------------*/ while (DMA_GetCmdStatus(DMA2_Stream7)!=ENABLE);   //检测DMA数据流是否有效}


                  相关实践学习
                  如何在云端创建MySQL数据库
                  开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
                  Sqoop 企业级大数据迁移方案实战
                  Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
                  相关文章
                  ZYNQ-AXI总线的信号接口要求以及时序关系
                  ZYNQ-AXI总线的信号接口要求以及时序关系
                  619 0
                  ZYNQ-AXI总线的信号接口要求以及时序关系
                  |
                  存储 固态存储 芯片
                  【文末送书】典型IO接口与总线 | SPI、IIC、UART、GPIO
                  【文末送书】典型IO接口与总线 | SPI、IIC、UART、GPIO
                  299 0
                  |
                  存储 网络性能优化 vr&ar
                  深入理解AMBA总线(十七)AXI是如何提高性能的
                  深入理解AMBA总线(十七)AXI是如何提高性能的
                  2084 1
                  |
                  vr&ar SoC 内存技术
                  深入理解AMBA总线(十二)AXI突发传输和AXI控制信号
                  深入理解AMBA总线(十二)AXI突发传输和AXI控制信号
                  1616 0
                  |
                  测试技术
                  STM32异步通讯点灯
                  通过使用STM32的异步通讯配合上位机自己制作的串口通讯助手实现点灯
                  112 0
                  |
                  存储
                  深入理解AMBA总线(六)AHB-lite Slave响应和其它控制信号
                  深入理解AMBA总线(六)AHB-lite Slave响应和其它控制信号
                  836 0
                  |
                  网络性能优化
                  深入理解AMBA总线(十九)AXI4新增信号以及AXI4-lite
                  深入理解AMBA总线(十九)AXI4新增信号以及AXI4-lite
                  734 0
                  |
                  监控 Scala 虚拟化
                  深入理解AMBA总线(十三)AXI原子访问机制和AXI响应
                  深入理解AMBA总线(十三)AXI原子访问机制和AXI响应
                  743 0
                  |
                  缓存 SoC
                  深入理解AMBA总线(八)AHB2APB同步桥设计
                  深入理解AMBA总线(八)AHB2APB同步桥设计
                  772 0