STM32串口通信UART使用

uart使用的过程为:

  • 1. 使能GPIO口和UART对应的总线时钟
  • 2. 配置GPIO口的输出模式
  • 3. 配置uart口相关的基本信息
  • 4. 使能uart口的相关的中断,如接收中断、空闲中断等
  • 5. 编写中断接收函数

配置对应的GPIO口

对于STM32F4_Discovery开发板而言共有五个,选择UART5作为实验串口,其对应的IO口为PC12、PD2。

  • UART5_TX: PC12
  • UART5_RX: PD2

首先需要将对应的GPIO口配置为复用功能,如下所示:

	GPIO_InitTypeDef gpioInitStructure;
//
// 使能对应的GPIO口时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
//
// UART5 TX:PC12 RX:PD2
//
GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5);
//
// PC12
gpioInitStructure.GPIO_Pin = GPIO_Pin_12;
gpioInitStructure.GPIO_Mode = GPIO_Mode_AF;
gpioInitStructure.GPIO_OType = GPIO_OType_PP;
gpioInitStructure.GPIO_PuPd = GPIO_PuPd_UP;
gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &gpioInitStructure);
// PD2
gpioInitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &gpioInitStructure);

对于GPIO口的配置,实际上是对GPIO各个寄存器的配置。GPIO_PinAFConfig()函数作用是配置GPIOx_AFR寄存器,每个口的复用功能选择由四个位来配置(具体参考STM32F4XX参考手册),因此16个GPIO空需要两个32位寄存器,在STM32F4处理器中,分别是GPIOx_AFRL、GPIOx_AFRH。而在库函数中,将寄存器的地址对应到相应的结构体上,与这两个寄存器放在一个AFR[2]数组中,如下所示。

typedef struct
{
__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
__IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
__IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
__IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
__IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
__IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
__IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */
__IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */
__IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
__IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
} GPIO_TypeDef;

GPIO_Init()函数作用是配置GPIO口的输出输入功能,将GPIO_TypeDef结构体中的寄存器依次配置为相应的模式。

GPIO口配置完成之后,需要配置UART口。

UART口配置

配置UART口的同时,需要配置对应的接收中断,对应代码如下:

	NVIC_InitTypeDef nvicInitStructure;
USART_InitTypeDef uartInitStructure;
//使能uart5时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5 , ENABLE);
//
// 配置UART5
uartInitStructure.USART_BaudRate = 9600;
uartInitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
uartInitStructure.USART_WordLength = USART_WordLength_8b;
uartInitStructure.USART_StopBits = USART_StopBits_1;
uartInitStructure.USART_Parity = USART_Parity_No;
uartInitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(UART5, &uartInitStructure);
//
// 配置外设接受中断
nvicInitStructure.NVIC_IRQChannel = UART5_IRQn;
nvicInitStructure.NVIC_IRQChannelPreemptionPriority = 0;
nvicInitStructure.NVIC_IRQChannelSubPriority = 0;
nvicInitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvicInitStructure);
//
USART_Cmd(UART5, ENABLE);

配置UART5的过程主要由USART_Init()函数实现,该函数完成对UART寄存器的配置。在库函数中,UART寄存器如下所示:

typedef struct
{
__IO uint16_t SR; /*!< USART Status register, Address offset: 0x00 */
uint16_t RESERVED0; /*!< Reserved, 0x02 */
__IO uint16_t DR; /*!< USART Data register, Address offset: 0x04 */
uint16_t RESERVED1; /*!< Reserved, 0x06 */
__IO uint16_t BRR; /*!< USART Baud rate register, Address offset: 0x08 */
uint16_t RESERVED2; /*!< Reserved, 0x0A */
__IO uint16_t CR1; /*!< USART Control register 1, Address offset: 0x0C */
uint16_t RESERVED3; /*!< Reserved, 0x0E */
__IO uint16_t CR2; /*!< USART Control register 2, Address offset: 0x10 */
uint16_t RESERVED4; /*!< Reserved, 0x12 */
__IO uint16_t CR3; /*!< USART Control register 3, Address offset: 0x14 */
uint16_t RESERVED5; /*!< Reserved, 0x16 */
__IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x18 */
uint16_t RESERVED6; /*!< Reserved, 0x1A */
} USART_TypeDef;

UART寄存器详细内容可以参考STM32F4中文手册,这里简单介绍下以下几个寄存器:

  • SR寄存器:状态寄存器,包含了一些标志位,如TXE(发送数据寄存器为空)、TC(发送完成)、RXNE(读取数据寄存器不为空)
  • DR寄存器: 数据寄存器,只用其低9位(DR[8:0])。当发送数据时,将数据写入该寄存器,该寄存器将数据发送到TDR或者移位寄存器发送,当数据写到移位寄存器时,TXE标志置1(数据写入时置0)。TXE为1时可以继续写入数据,否则新写入的数据会把原有数据覆盖。读取数据时,也是从该寄存器读取数据。
  • BRR波特率寄存器:波特率寄存器,用来设置波特率的值。
  • CR1寄存器:包含使能位UE、字长M、过采样倍率、奇偶校验、接收使能、发送使能等控制信息。

数据收发

单字符发送

	//发送一个字符,USART_SendData函数实际就是将字符写入USART_DR寄存器
USART_SendData(pUSARTx,ch);
//
//等待发送寄存器为空,只有当USART_FLAG_TXE == 1 时才可以继续想DR寄存器写入数据,否则会将上一个数据覆盖掉。
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)

字符串发送

 /***************** 发送字符串 **********************/
// 发送字符串是每个字符依次发送,相当于循环执行单字符发送函数。
//
void uart_send_str( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
//
do {
uart_send_byte( pUSARTx, *(str + k) );
k++;
} while (*(str + k)!='\0');
//
/* 等待发送完成 */
while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) ;
}
//
// USART_FLAG_TC为1的条件是,DR寄存器为空并且以为寄存器也为空。相当于所有数据都发送完毕

字符接收

	uint8_t ucTemp;
if (USART_GetITStatus(UART5, USART_IT_RXNE)!=RESET){
ucTemp = USART_ReceiveData( UART5 );
// USART_SendData(UART5,ucTemp);
}
// USART_ReceiveData()函数是将DR寄存器读取并返回
// USART_IT_RXNE不为0表示数据寄存器中有数据,需要将其读出。
// 每次收一个字符,USART_IT_RXNE会被设置为1,直至数据被读出,USART_IT_RXNE再次被设置为0.
// 同时,USART_IT_RXNE也被设置为中断的标志,即接收到数据时,进入中断。

STM32串口通信UART使用的更多相关文章

  1. Stm32串口通信(USART)

    Stm32串口通信(UART) 串口通信的分类 串口通信三种传递方式 串口通信的通信方式 串行通信的方式: 异步通信:它用一个起始位表示字符的开始,用停止位表示字符的结束.其每帧的格式如下: 在一帧格 ...

  2. STM32 串口通信使用奇偶校验

    STM32串口通信如果使用奇偶校验,需要设置数据位长度为9bit USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USAR ...

  3. stm32串口通信实验,一点笔记

    第一次深入学习stm32,花了好长时间才看懂代码(主要是C语言学习不够深入),又花了段时间自己敲了一遍,然后比对教程,了解了利用中断来串口通信的设置方法. 板子是探索版f407,本实验工程把正点原子库 ...

  4. STM32串口通信配置(USART1+USART2+USART3+UART4) (转)

    一.串口一的配置(初始化+中断配置+中断接收函数) 1 /*====================================================================== ...

  5. STM32串口通信USART1转USART2问题解决

    使用的是STM32f103ZET6. 1.把文件main.c和usart.c中的所有usart1换成usart2 2.查看手册得知USART2的引脚是Tx->PA2,Rx->PA3,改变u ...

  6. STM32 串口通信

    1. 中断说明 TXE(Tansmit Data Register empty interrupt) - 发送数据寄存器空,产生中断.当使能TXE后,只要Tx DR空了,就会产生中断.---写寄存器D ...

  7. STM32串口通信配置(USART1+USART2+USART3+UART4)

    一.串口一的配置(初始化+中断配置+中断接收函数) 1 /*====================================================================== ...

  8. 嵌入式02 STM32 实验07 串口通信

    STM32串口通信(F1系列包含3个USART和2个UART) 一.单片机与PC机串行通信研究目的和意义: 单片机自诞生以来以其性能稳定,价格低廉.功能强大.在智能仪器.工业装备以及日用电子消费产品中 ...

  9. 电赛菜鸟营培训(三)——STM32F103CB之串口通信

    一.串口通信概念 1.缩写 USART:Universal Synchronous/Asynchronous Receiver/Transmitter 通用同步/异步接收和发送器 2.用处 (1)同步 ...

随机推荐

  1. WebAPI 实现前后端分离的示例

    转自:http://www.aspku.com/kaifa/net/298780.html 随着Web技术的发展,现在各种框架,前端的,后端的,数不胜数.全栈工程师的压力越来越大. 现在的前端的框架, ...

  2. 【Django笔记三】Django2.0配置mysql模型

    一.环境版本信息: 操作系统:windows10 Django版本:2.0.5 Python版本:3.6.4 Mysql版本: 5.5.53   安装mysql 二.安装Mysqlclient: 1. ...

  3. 怎么将oracle的sql文件转换成mysql的sql文件

    怎么将sql文件导入PowerDesigner中的方法(将oracle的sql文件转换成mysql的sql文件)呢? 怎么将xx.sql文件的数据库结构导入powerdesigner 的方法呢? 现讲 ...

  4. 【laravel】同一代码段内,先更新数据,后查询修改的数据,查询结果错误的问题

    如标题所言,是什么意思呢?举个栗子,需求如下: 你是一个电话销售人员,手头有一些待call电话单,每个电话单上有N个不同的电话号码,需要你每打一个电话就标记为”已打“.当一个电话单上的号码都标记为”已 ...

  5. transform Vs Udf

    在鞋厂的第一个任务,拆表.需要把订单表按照开始日期和结束日期拆分成多条记录,挺新鲜的~ transform方式,使用到了python. (1)把hive表的数据传入,通过python按照日期循环处理, ...

  6. 从python2.x到python3.x进阶突破

    1.p2是重复代码,语言不同,不支持中文;p3则相反,其中代码不重复,语言用的相同的,并且是支持中文的. 2.p2中input中输入数字输出数字,输入字符串必须自己手动加引号才行;p3中input输出 ...

  7. GeekOS课程设计-project1

    参考:https://blog.csdn.net/qq_35008279/article/details/78984561?tdsourcetag=s_pcqq_aiomsg 补充:如果按照参考博客还 ...

  8. Java 反射 (Class、ClassLoader、Constructor、Method、Field)

    反射是Java中一个非常重要.非常强大的机制.曾看到一句话“反射是框架的灵魂”,初学时不懂,等到学完框架之后才慢慢理解其意. 什么是反射?我们先通过几个类和示例来初步体会一下反射. 一.ClassLo ...

  9. Java设计模式(11)——结构型模式之享元模式(Flyweight)

    一.概述 概念 避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). UML简图 单纯享元模式 角色 抽象享元角色(Flyweight):定义享元子类公共接口 具体享元角色(Co ...

  10. 北京Uber优步司机奖励政策(3月27日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...