[其他] 【分享帖】基于处理器为STM32F4xx Family系列的USART

[复制链接]
英雄南华大学MA战队
2019-4-8 21:01:33 显示全部楼层

马上注册,玩转Robomaster!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

USART
(Universal synchronous asynchronous receiver transmitter)
通用同步异步收发器

微信图片_20190329193108.png


首先先介绍下关于USART

         USART 能够灵活地与外部设备进行全双工数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求。USART 通过小数波特率发生器提供了多种波特率。
        它支持同步单向通信和半双工单线通信;还支持 LIN(局域互连网络)、智能卡协议与 IrDA(红外线数据协会)SIR ENDEC 规范,以及调制解调器操作 (CTS/RTS)。而且,它还支持多处理器通信。通过配置多个缓冲区使用 DMA 可实现高速数据通信。
        STM32F4xx系列USART有很多特性,它是全双工异步通信, 数据字长度可编程(8 位或 9 位), 停止位可配置 - 支持 1 或 2 个停止位,还有奇偶校验错误等等。


微信图片_20190329193121.jpg

接下来是软件配置


在配置相应串口时,一般有这么几步:
(1)玩过32位微处理器的同学应该清楚,在32位的微处理器中,时钟是至关重要的,分为多种,目的是为了实现第功耗,在配置串口时,第一步是串口时钟使能,GPIO时钟使能;
(2)第二是调用引脚映射函数,不懂映射知识大家查阅相关知识,设置GPIO初始化模式为复用功能,且初始化引脚;
(3)第三步是关键,对串口参数初始化:设置波特率、字长、串口模式等参数;
(4)如果需要串口接收中断需要开启串口中断且初始化NVIC;
(5)在写完前面相关代码之后,之后要开启使能串口,即操作USART_CR1寄存器进行相关操作;
(6)之后编写中断处理函数,可以是串口中断也可以为串口空闲中断,具体是通过USART_GetFlagStatus获取串口状态函数;
(7)如果还需要DMA配合,则需要配置DMA相关参数,如传输数据量,传输方向等等。


下面在实际应用中就按照上述方法进行操作
微信图片_20190329193118.jpg
图2 USART结构图


接下来将讲讲在比赛应用中串口的相关配置及串口处理函数


        因为实际应用中是基于STM32F427的微控制器,因此是选择串口6(PG9-RX、PG14-TX),选择好之后,先把裁判系统与板子进行物理连接,一定要确保电源、地、RX及TX对应起来,避免地和电源短接,烧毁串口。在配置好之后,下面进行软件设计。

1开启串口6的时钟使能GPIOG管脚时钟

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE); //使能GPIOG时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);//使能USART6时钟

2

调用引脚映射函数

不懂映射知识大家查阅相关知识

设置GPIO初始化模式为复用功能,且初始化引脚


GPIO_PinAFConfig(GPIOG,GPIO_PinSource9,GPIO_AF_USART6); //GPIOG9复用为USART6
GPIO_PinAFConfig(GPIOG,GPIO_PinSource14,GPIO_AF_USART6); //GPIOG14复用为USART6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_14; //GPIOG9与GPIOG14
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOG,&GPIO_InitStructure); //初始化PG9,PG14


3
第三步是关键

对串口参数初始化

设置波特率、字长、串口模式等参数


  //USART1 初始化设置
USART_InitStructure.USART_BaudRate = 115200;//波特率设置
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_Rx | USART_Mode_Tx;  //收发模式

4

此处我们需要串口接收空闲中断

因此开启串口中断且初始化NVIC


NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;//串口6中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3    需改为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;          //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
USART_ITConfig(USART6, USART_IT_IDLE, ENABLE);//开启相关中断

5

在写完前面相关代码之后

之后要开启使能串口

即操作USART_CR1寄存器进行相关操作


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

6

之后编写串口空闲中断处理函数

因为串口空闲中断是:

等接收到一定字节数据之后才产生中断

避免时时刻刻产生中断

导致主程序无法正常运行


//空闲中断
void USART6_IRQHandler(void)
{
  u16 data=data;
  if(USART_GetITStatus(USART6,USART_IT_IDLE) != RESET)
  {
       DMA_Cmd(DMA2_Stream1, DISABLE); //关闭DMA,防止处理其间有数据
       data = USART6->SR;
       data = USART6->DR;
       memcpy(HandlerBuff,ReceiveBuff,200);
       for(i=0;i<=sizeof(HandlerBuff);i++)
       {
            JudgeData(HandlerBuff);
       }
       DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1 | DMA_FLAG_FEIF1 | DMA_FLAG_DMEIF1 | DMA_FLAG_TEIF1 | DMA_FLAG_HTIF1);//清除DMA2_Steam2传输完成标志
       DMA_SetCurrDataCounter(DMA2_Stream1, RECEIVE_BUF_SIZE);
       DMA_Cmd(DMA2_Stream1, ENABLE);     //打开DMA,防止处理其间有数据
       MYDMA_Enable(DMA2_Stream7,RECEIVE_BUF_SIZE);     //开始一次DMA传输!
  }
}
当产生空闲中断之后,关闭DMA数据传输,之后把DMA存储的数据进行处理,把有效信息提取出来,如上文说的底盘功率值、枪口热量值,之后在把数据通过其他函数进行处理来达到所需功能,如限制步兵底盘功率从而避免步兵扣血


7
因为使用到了串口-DMA模式
即还需要配置DMA

微信图片_20190329193132.jpg
图3 DMA2请求映射

根据表格可以看到USART6可以使用通道5的数据流1或者数据流2进行DMA2数据传输,之后在对DMA进行配置,打开DMA2使能通道即完成USART串口DMA数据传输:

DMA_InitStructure.DMA_Channel = chx;  //通道选择
     DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址
     DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器0地址
     DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
     DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量
     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式
     DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
     DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;        
     DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
     DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
     DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
     DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
经过一系列的配置,最终实现了串口空闲中断-DMA数据传输,更多关于串口的知识需要自己多实践操作才能更好领悟串口相关知识。


QQ图片20190408204318.jpg
End!
谢谢!





跳转到指定楼层

[其他] 【分享帖】基于处理器为STM32F4xx Family系列的USART

[复制链接]
梯队队员虎-工
2019-4-8 21:45:47 显示全部楼层
牛逼,好好好
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

触屏版 | 电脑版

Copyright © 2024 RoboMasters 版权所有 备案号 粤ICP备2022092332号

快速回复 返回顶部 返回列表