1.串口的基本概念

在STM32的参考手册中,串口被描述成通用同步异步收发器(USART),它提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互联网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。还可以使用DMA方式,实现高速数据通信。

USART通过3个引脚与其他设备连接在一起,任何USART双向通信至少需要2个引脚:接受数据输入(RX)和发送数据输出(TX)。

RX:接受数据串行输入。通过过采样技术来区别数据和噪音,从而恢复数据。

TX:发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,并且不发送数据时,TX引脚处处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据的发送和接收。

2.串口的如何工作的

一般有两种方式:查询和中断。

(1)查询:串口程序不断地循环查询,看看当前有没有数据要它传送。如果有,就帮助传送(可以从PC到STM32板子,也可以从STM32板子到PC)。

(2)中断:平时串口只要打开中断即可。如果发现有一个中断来,则意味着要它帮助传输数据——它就马上进行数据的传送。同样,可以从PC到STM3板子,也可以从STM32板子到PC。

3.串口的硬件连接

我用的奋斗STM32 V3开发板拥有二路RS-232接口,CPU的PA9-US1-TX(P68)、PA10-US1-RX(P69)、PA9-US2-TX(P25)、PA10-US2-RX(P26)通过MAX3232实现两路RS-232接口,分别连接在XS5和XS17接口上。 USART1在系统存储区启动模式下,将通过该口通过PC对板上的CPU进行ISP,该口也可作为普通串口功能使用,JP3,JP4的短路冒拔去,将断开第二路的RS232通信,仅作为TTL通信通道。

4.编程实例

我们要对串口进行操作,首先要将STM32的串口和CPU进行连接。在Windows操作系统中,有一个自带的系统软件叫“超级终端”。VISTA以上的操作系统去掉了这个软件,不过可以从XP的系统中,复制“hypertrm.dll”和“hypertrm.exe”到“windows/system32”文件夹下,然后双击运行hypertrm.exe,就可以看见超级终端的运行界面了。

运行超级终端以后,会弹出“连接描述”,输入名称和选择图标,这个地方随便写个什么名称都可以。然后弹出“连接到”设置,在“连接时使用”选择你自己PC和STM32连接的COMx,如果不知道是哪个COM口的话,可以在PC的设备管理器中找到。在选择好COM口之后,会弹出一个“属性”对话框,在“位/秒”选择和你STM32中设置的波特率一致就好,数据位也是按照STM32的设置来选择,奇偶校验选择无,停止位选择1,数据流控制选择无。注意,以上的选项都必须和STM32中的串口设置相匹配,要不然可能会出现一些未知错误。

配置好超级终端之后,我们便可以开始对STM32进行编程了。编程一般按照如下步骤进行:

(1)RCC配置;

(2)GPIO配置;

(3)USART配置;

(4)NVIC配置;

(5)发送/接收数据。

在RCC配置中,我们除了常规的时钟设置以外,要记得打开USART相对应的IO口时钟,USART时钟,还有管脚功能复用时钟。

在GPIO配置中,将发送端的管脚配置为复用推挽输出,将接收端的管脚配置为浮空输入。

在USART的配置中,通过USART_InitTypeDef结构体对USART进行初始化操作,按照自己所需的功能配置好就可以了。注意,在超级终端的设置中,需要和这个里面的配置相对应。由于我是采用中断接收数据的方式,所以记得在USART的配置中药打开串口的中断,同时最后还要打开串口。

在NVIC的配置中,主要是USART1_IRQChannel的配置,和以前的笔记中讲述的中断配置类似,不会配置的可以参考以前的笔记。

全部配置好之后就可以开始发送/接收数据了。发送数据用USART_SendData()函数,接收数据用USART_ReceiveData()函数。具体的函数功能可以参考固件库的参考文件。根据USART的配置,在发送和接收时,都是采用的8bits一帧来进行的,因此,在发送的时候,先开辟一个缓存区,将需要发送的数据送入缓存区,然后再将缓存区中的数据发送出去,在接收的时候,同样也是先接收到缓存区中,然后再进行相应的操作。

注意在对数据进行发送和接收的时候,要检查USART的状态,只有等到数据发送或接收完毕之后才能进行下一帧数据的发送或接收。采用USART_GetFlagStatus()函数。

同时还要注意的是,在发送数据的最开始,需要清除一下USART的标志位,否则,第1位数据会丢失。因为在硬件复位之后,USART的状态位TC是置位的。当包含有数据的一帧发送完成之后,由硬件将该位置位。只要当USART的状态位TC是置位的时候,就可以进行数据的发送。然后TC位的置零则是通过软件序列来清除的,具体的步骤是“先读USART_SR,然后写入USART_DR”,只有这样才能够清除标志位TC,但是在发送第一帧数据的时候,并没有进行读USART_SR的操作,而是直接进行写操作,因此TC标志位并没有清空,那么,当发送第一帧数据,然后用USART_GetFlagStatus()检测状态时返回的是已经发送完毕(因为TC位是置1的),所以程序会马上发送下一帧数据,那么这样,第一帧数据就被第二帧数据给覆盖了,所以看不到第一帧数据的发送。

按照上面的方法编程后,我们便可以在超级终端上查看串口通信的具体状态了。我的这个例程,在硬件复位以后,可以马上在超级终端上看见“Welcome to my STM32! Please press any key!”字样,然后如果在超级终端中通过PC机键盘按下相应的键,则这个键会发送到STM32中,并且马上返回到PC机的超级终端上,因此可以马上从超级终端的页面中看到按下的相应的键。

5.程序源代码

#include "stm32f10x_lib.h"

FlagStatus RX_status;

void RCC_cfg();

void GPIO_cfg();

void USART_cfg();

void NVIC_cfg();

int main()

{

int i;

unsigned char TxBuf1[] = "Welcome to my STM32! Please press any key!";

RCC_cfg();

GPIO_cfg();

NVIC_cfg();

USART_cfg();

//清除标志位,否则第1位数据会丢失

USART_ClearFlag(USART1,USART_FLAG_TC);

//发送数据

//PB5的作用是显示正在发送数据

//当有数据在发送的时候,PB5会亮

for( i=0;TxBuf1[i]!='\0';i++)

{

USART_SendData(USART1,TxBuf1[i]);

GPIO_SetBits(GPIOB,GPIO_Pin_5);

//等待数据发送完毕

while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);

GPIO_ResetBits(GPIOB,GPIO_Pin_5);

}

while(1);

}

//RCC时钟配置

void RCC_cfg()

{

//定义错误状态变量

ErrorStatus HSEStartUpStatus;

//将RCC寄存器重新设置为默认值

RCC_DeInit();

//打开外部高速时钟晶振

RCC_HSEConfig(RCC_HSE_ON);

//等待外部高速时钟晶振工作

HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus == SUCCESS)

{

//设置AHB时钟(HCLK)为系统时钟

RCC_HCLKConfig(RCC_SYSCLK_Div1);

//设置高速AHB时钟(APB2)为HCLK时钟

RCC_PCLK2Config(RCC_HCLK_Div1);

//设置低速AHB时钟(APB1)为HCLK的2分频

RCC_PCLK1Config(RCC_HCLK_Div2);

//设置FLASH代码延时

FLASH_SetLatency(FLASH_Latency_2);

//使能预取指缓存

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

//设置PLL时钟,为HSE的9倍频8MHz * 9 = 72MHz

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

//使能PLL

RCC_PLLCmd(ENABLE);

//等待PLL准备就绪

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

//设置PLL为系统时钟源

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

//判断PLL是否是系统时钟

while(RCC_GetSYSCLKSource() != 0x08);

}

//打开GPIO时钟,复用功能,串口1的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE);

}

//IO口配置

void GPIO_cfg()

{

GPIO_InitTypeDef GPIO_InitStructure;

//PA9作为US1的TX端,打开复用,负责发送数据

GPIO_StructInit(&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA , &GPIO_InitStructure);

//PA10作为US1的RX端,负责接收数据

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

//LED显示串口正在发送/接收数据

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOB, &GPIO_InitStructure);

}

//串口初始化

void USART_cfg()

{

USART_InitTypeDef USART_InitStructure;

//将结构体设置为缺省状态

USART_StructInit(&USART_InitStructure);

//波特率设置为115200

USART_InitStructure.USART_BaudRate = 115200;

//一帧数据的宽度设置为8bits

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

//在帧结尾传输1个停止位

USART_InitStructure.USART_StopBits = USART_StopBits_1;

//奇偶失能模式,无奇偶校验

USART_InitStructure.USART_Parity = USART_Parity_No;

//发送/接收使能

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

//硬件流控制失能

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

//设置串口1

USART_Init(USART1, &USART_InitStructure);

//打开串口1的中断响应函数

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

//打开串口1

USART_Cmd(USART1, ENABLE);

}

//配置中断

void NVIC_cfg()

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择中断分组2

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel; //选择串口1中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占式中断优先级设置为0

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为0

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

NVIC_Init(&NVIC_InitStructure);

}

然后在stm32f10x_it.c文件中找到相应的中断处理函数,并填入一下内容。注意在stm32f10x_it.c中,要声明一下外部变量RX_status

extern FlagStatus RX_status;

void USART1_IRQHandler(void)

{

GPIO_SetBits(GPIOB, GPIO_Pin_5);

//确认是否接收到数据

RX_status = USART_GetFlagStatus(USART1, USART_FLAG_RXNE);

//接收到数据

if(RX_status == SET)

{

//将数据回送至超级终端

USART_SendData(USART1, USART_ReceiveData(USART1));

//等待数据发送完毕

while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

GPIO_ResetBits(GPIOB, GPIO_Pin_5);

}

}

转载于:https://blog.51cto.com/7090376/1243973

STM32学习笔记(7):USART串口的使用相关推荐

  1. stm32学习笔记-9 USART串口

    9 USART串口 文章目录 9 USART串口 9.1 串口通信协议 9.2 stm32的片上外设-USART 9.3 USART收发相关实验 9.3.1 实验1:串口发送 9.3.2 实验2:移植 ...

  2. STM32学习之旅④ USART串口和上位机通信

    STM32系列博客: STM32学习之旅① 开发环境搭建 STM32学习之旅② 固件库的使用及工程模板的建立 STM32学习之旅③ 从点灯到代码移植 STM32学习之旅④ USART串口和上位机通信 ...

  3. 【STM32入门100步--学习笔记】USART串口接收程序(含教学视频)

    STM32串口接收的程序和8051单片机一样,有2种接收方式:中断处理和查询方式. 试过两种方式之后发现,中断处理方式更方便,可以扩展多个数据的接收.推荐中断方式. 我已经将本资料内容整理后录制了视频 ...

  4. dma接收双缓存 stm32_「STM32学习笔记」USART 新特性

    之前的学习笔记"SPI不够用?USART来帮忙"一文中介绍了用如何把USART当做SPI来用的方法.此外,ST的USART还有很多新特性,没准有你不知道的. 在此,我们整理出来以下 ...

  5. STM32学习笔记7(串口通信)

    一.简介 1.电平标准 2.串口参数及时序 串口通讯的数据包由发送设备通过自身的 TXD 接口传输到接收设备的 RXD 接口.它由起始位.数据位.校验位以及停止位组成,通讯双方的数据包格式要约定一致才 ...

  6. STM32学习笔记(四 串口通信 3 串口寄存器库函数配置)

    一.常用的串口寄存器 USART_SR状态寄存器 作用: 状态寄存器适用于检测串口此时所处的状态. 主要关注两个位:RXNE和TC(第5.6两位). RXNE(读数据寄存器非空): 当该位被置1的时候 ...

  7. stm32学习笔记----双串口同时打开时的printf()问题

    stm32学习笔记----双串口同时打开时的printf()问题 最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其 ...

  8. 《STM32学习笔记》4——核心功能电路与编程(下)

    接上文,文中的图片,大多数来自视频的截图(来自洋桃电子). 欢迎大家批评指正! STM32学习笔记-专栏 文章目录 一.蜂鸣器驱动 1.蜂鸣器介绍 2.蜂鸣器电路 3.蜂鸣器程序 二. MIDI 音乐 ...

  9. STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)

    本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...

  10. 学习记录:USART—串口通讯

    目录 1.串口通讯协议简介 1.1物理层 1.2 电平标准 2.协议层 3.printf函数的支持代码 4.usart.h程序 5.main.c主函数 6.实验现象 1.串口通讯协议简介 对于通讯协议 ...

最新文章

  1. c++ 11 多线程处理(1)
  2. BZOJ 3240([Noi2013]矩阵游戏-费马小定理【矩阵推论】-%*s-快速读入)
  3. Linux学习:shell命令
  4. 洛谷P3066 [USACO12DEC]逃跑的BarnRunning Away From…
  5. OGEngine教程:声音载入
  6. 设计模式系列 - 原型模式
  7. 企业级实战02_SpringMVC整合ActiveMQ 实战需求
  8. 数据结构(一)——二叉树的性质与两种遍历方法
  9. c java http通讯,c语言经过http请求javaee项目
  10. @RequestParam接收解析不到 POST 提交的 数据
  11. cocos2d-x 在vs2010下的环境配置
  12. 野火指南者(STM32F103)移植LVGL
  13. 后台将图片以base64形式传给前台,前台展示
  14. 点击扫一扫二维码返回文本内容
  15. 水星路由器wan口ip显示0_路由器wan口ip地址显示0.0.0.0怎么办(2)
  16. (读论文)启体书法字的矢量化-曹芳
  17. python数学建模--线性规划问题案例及求解
  18. windows11 + linux 蓝牙连接问题
  19. mmm monitor mysql_MySQL(MMM架构使用)
  20. 好书推荐:《黑客秘笈:渗透测试实用指南》

热门文章

  1. 【bzoj2060】[Usaco2010 Nov]Visiting Cows拜访奶牛 树形dp
  2. async await 的前世今生
  3. bootstrapTable表格格式化日期后,IE浏览器显示不正常,为NaN-NaN-NaN
  4. C++ 字符串流stringstream(附蓝桥杯2018年第九届真题缩位求和题解)
  5. 全面改革:解读 Vue 3.0 的变化
  6. 基础 | numpy ndarray 之内功心法,理解高维操作!
  7. ORACLE不完全恢复的几种情况
  8. 妙趣横生的算法--二叉树
  9. 江湖不再平静---51CTO学院停服公告
  10. Android--JNI编程详解