STM32F103mini教程学习总结与心得(二)---->串口通信

2023-05-16

关注同名微信公众号“混沌无形”,阅读更多有趣好文!

一、串口原理

1.处理器与外部设备通信的两种方式:并行通信(速度快,占用资源多)+串行通信(反之)

2.串行通信(按照数据传送方向分类):

(1)单工:数据传输只支持数据在一个方向上传输

   (2)半双工:允许数据在两个方向上传输,但在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信

   (3)全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立 的接收和发送能力。 

 

 

串行通信三种传送方式
3.串行通信的通信方式
(1)同步通信:带时钟同步信号传输--->SPI,IIC通信 【时钟线+数据线】
(2)异步通信:不带时钟通信信号------>UART(通用异步收发器),单总线 【约定波特率】
 
常见的串行通信接口

4.STM32的串口通信接口

 

(1)UART:通用异步收发器
(2)USART:通用同步异步收发器

 

 
UART异步通信方式引脚连接方法
 
STM32F10X的串口对应针脚
 
5.UART异步通信方式特点:
全双工异步通信。
分数波特率发生器系统,提供精确的波特率( 波特率决定数据传输速度)。
-发送和接受共用的可编程波特率,最高可达4.5Mbits/s
可编程的数据字长度(8位或者9位);
可配置的停止位(支持1或者2位停止位);
可配置的使用DMA多缓冲器通信。
单独的发送器和接收器使能位。
检测标志:① 接受缓冲器 ②发送缓冲器空 ③传输结束标志
多个带标志的中断源。触发中断。
其他:校验控制,四个错误检测标志。
 
 
串口通信过程
 
6.串口异步通信需要定义的参数:
起始位
数据位(8位或者9位)
奇偶校验位(第9位)--->偶校验:如果数据位8位中,1的个数为偶数,则校验位为0,反之为1;奇校验相反
停止位(1,15,2位)
波特率设置---->点击打开链接
 
通信位
7.常用的串口相关寄存器
(1)USART_SR状态寄存器
(2)USART_DR数据寄存器
(3)USART_BRR波特率寄存器
8.串口操作函数(省略入口参数)
void USART_Init(); //串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能
void USART_Cmd();//使能串口
void USART_ITConfig();//使能相关中断
DR寄存器操作
void USART_SendData();//发送数据到串口,DR
uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
SR寄存器操作:
FlagStatus USART_GetFlagStatus();//获取状态标志位
void USART_ClearFlag();//清除状态标志位
ITStatus USART_GetITStatus();//获取中断状态标志位
void USART_ClearITPendingBit();//清除中断状态标志位

 

 

 

二、实际串口寄存器操作

1.miniSTM32板载2个串口:

(1)USB串口(CH340:USB转串口芯片):与电脑通信

(2)RS232串口:异步传输标准接口---STM32内带的USB接口

(3)术语区分:1)串口、COM口是指的物理接口形式(硬件)【COM口即串行通讯端口,简称串口】,而TTL、RS-232、RS-485是指的电平标准(电信号--通信协议)

      2)TTL标准是低电平为0,高电平为1(+5V电平)。RS-232标准是正电平为0,负电平为1(±15V电平) 详见点击打开链接

2.串口设置步骤:

(1)串口时钟,GPIO时钟使能-->RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);

(2)串口复位--->void USART_DeInit(USART_TypeDef* USARTx);--USART_DeInit(USART1); //复位串口 1

(3)GPIO端口模式设置-->GPIO_Init(); 模式设置为GPIO_Mode_AF_PP----【端口复用和重映射很不一样-点击打开链接--------区别:点击打开链接

(4)串口参数初始化--->void USART_Init(USART_TypeDef* USARTx,USART_InitTypeDef*USART_InitStruct); 

1)USART_InitTypeDef 类型的结构体指针:  

USART_InitStructure.USART_BaudRate = bound; //波特率;
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; //无硬件数据流控制,用于两个uart模块之间传输数据
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口  

2)串口数据收发:

USART_DR寄存器发送数据函数:void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 

 

USART_DR寄存器读取串口接收到的数据函数:uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
3)串口状态读取:
*RXNE(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到。
*TC(发送完成),当该位被置位的时候,表示USART_DR内的数据已经被发送完成。如果设置了这个位的中 断,则会产生中断。
 
*读取串口状态的函数:FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
第二个入口参数很重要:RXNE(读数据寄存器非空)以及TC(发送完成)
判断读寄存器是否非空(RXNE),操作库函数:USART_GetFlagStatus(USART1, USART_FLAG_RXNE);
判断发送是否完成(TC),操作库函数:USART_GetFlagStatus(USART1, USART_FLAG_TC);
4)串口使能----->USART_Cmd(USART1, ENABLE);

 

 

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

1)使能串口中断函数:void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,FunctionalState NewState)

*****接收数据的时候产生中断:USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断,接收到数据中断【RXNE位被置位。它表明移位寄存器的内容被转移到RDR。换句话说,数据已经被接收并且可以被读出(包括与之有关的错误标志)------>*如果RXNE=1,上一个有效数据还在接收寄存器RDR上,可以被读出.;;如果RXNE=0,这意味着上一个有效数据已经被读走, RDR已经没有东西可读。当上一个有效数据在RDR中被读取的同时又接收到新的(也就是丢失的)数据时,此种情况可能发生。 】

发送数据结束时(TC,发送完成)产生中断:USART_ITConfig(USART1, USART_IT_TC, ENABLE);

******USART中断请求--标志说明

**TXE---->发送数据寄存器空

**CTS--->CTS标志

**TC--->发送完成

**TXNE--->接收数据就绪可读

**ORE--->检测到数据溢出

**IDLE--->检测到空闲线路

**PE--->奇偶检验错

**LBD--->断开标志

**NE或ORT或FE--->噪声标志,多缓冲通信中的溢出错误和帧错误

 

2)获取相应的中断状态(判断是哪个中断产生的):ITStatusUSART_GetITStatus(USART_TypeDef*USARTx, uint16_t USART_IT)

例:判断到底是否是串口发送完成中断 --->USART_GetITStatus(USART1, USART_IT_TC)

(6)编写中断处理函数--->USARTx_IRQHandler();

(7)串口数据收发:void USART_SendData();//发送数据到串口,DR
  uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据

(8)串口传输状态获取:FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

 

主函数中编写UART1串口通信:

 

#include "stm32f10x.h"//必须加上,不然不能识别时钟函数等宏定义
#include "LED.h"


void USART1_IRQHandler(void)//USART_IT_RXNE:接收到数据,就执行中断服务函数
{
	//在stm32f10x_usart.c文件中查找功能函数
	if(USART_GetITStatus(USART1,USART_IT_RXNE/*中断标志是什么,此处就应该写什么*/))
	{
		uint16_t res = USART_ReceiveData(USART1); //从串口接收到数据
		USART_SendData(USART1,res);//将数据从串口发出去
		LED0 = ~LED0;
	}
}
void my_uart_init(void)
{
	//参数结构定义--->应该写在函数开头处
	GPIO_InitTypeDef GPIO_InitStruct;
  USART_InitTypeDef USART1_para;
  NVIC_InitTypeDef NVIC_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);//PA9,PA10
	//端口重映射
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	//GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
	USART_DeInit(USART1);//串口复位
	
	//GPIO端口模式设置
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//推免输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;//USART1_TX
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);


	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;//USART1_RX
	//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//串口参数设置
	USART1_para.USART_BaudRate = 9600;
	USART1_para.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART1_para.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
	USART1_para.USART_Parity = USART_Parity_No;
	USART1_para.USART_StopBits = USART_StopBits_1;
	USART1_para.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1,&USART1_para);
	
	//使能串口
	USART_Cmd(USART1,ENABLE);
	
	//中断配置
	USART_ITConfig(USART1,USART_IT_RXNE/*接收到数据 就出发中断*/,ENABLE);//触发中断标志
	
	//开启中断并初始化
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;//串口中断函数
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;//子优先级
	NVIC_Init(&NVIC_InitStruct);
}


	
int main(void)
{
	LED_init();
	LED0 = 1;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组
	my_uart_init();
	while(1);
	
}	//在stm32f10x_usart.c文件中查找功能函数
	if(USART_GetITStatus(USART1,USART_IT_RXNE/*中断标志是什么,此处就应该写什么*/))
	{
		uint16_t res = USART_ReceiveData(USART1); //从串口接收到数据
		USART_SendData(USART1,res);//将数据从串口发出去
		LED0 = ~LED0;
	}
}
void my_uart_init(void)
{
	//参数结构定义--->应该写在函数开头处
	GPIO_InitTypeDef GPIO_InitStruct;
  USART_InitTypeDef USART1_para;
  NVIC_InitTypeDef NVIC_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);//PA9,PA10
	//端口重映射
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	//GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
	USART_DeInit(USART1);//串口复位
	
	//GPIO端口模式设置
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//推免输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;//USART1_TX
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);


	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;//USART1_RX
	//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//串口参数设置
	USART1_para.USART_BaudRate = 9600;
	USART1_para.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART1_para.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
	USART1_para.USART_Parity = USART_Parity_No;
	USART1_para.USART_StopBits = USART_StopBits_1;
	USART1_para.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1,&USART1_para);
	
	//使能串口
	USART_Cmd(USART1,ENABLE);
	
	//中断配置
	USART_ITConfig(USART1,USART_IT_RXNE/*接收到数据 就出发中断*/,ENABLE);//触发中断标志
	
	//开启中断并初始化
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;//串口中断函数
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;//子优先级
	NVIC_Init(&NVIC_InitStruct);
}


	
int main(void)
{
	LED_init();
	LED0 = 1;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组
	my_uart_init();
	while(1);
	
}


回车:0x0d;换行:0x0a

 

使用串口2源代码:点击打开链接

printf("\r\n\r\n");---->将内容发送到主串口-【可在usart.c中修改】

 

如果喜欢的话,可以关注同名微信公众号“混沌无形”,阅读更多有趣好文!

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F103mini教程学习总结与心得(二)---->串口通信 的相关文章

  • 51单片机串口通信(UART)

    项目描述 1 串口工作方式为1 8位UART 波特率可变 无校验位 2 通信数据格式为 1位起始位 8位数据位 1位停止位 3 上电后MCU给上位机发送问候语 之后等待上位机的信息 MCU和上位机的通信为收发交替进行 MCU接收到的信息会实
  • 51单片机——串口通信

    51单片机 串口通信 串口通信 串口通信的原理 串口的配置 定时器的配置 c源代码 netty源代码 结果 本篇博客的最终效果是实现51单片机用串口发送Hello World netty监听串口读到Hello World后回发给51单片机
  • CSerialPort教程4.3.x (2) - CSerialPort源码简介

    CSerialPort教程4 3 x 2 CSerialPort源码简介 前言 CSerialPort项目是一个基于C C 的轻量级开源跨平台串口类库 可以轻松实现跨平台多操作系统的串口读写 同时还支持C Java Python Node
  • 关于ESP8266自动下载和CH340的几件事

    最近在玩ESP8266 做了些东西 比如考研倒计时器 网络闹钟 网络灯 用手机控制亮度 气象站等等 ESP8266本身挺简单的 倒是这个自动下载电路 我还是第一次玩 以前玩51也用过串口下载 都是自己冷启动 玩STM32用的ST LINK
  • 身份证读取设备开发解决方案:3、单片机读取身份证信息的demo

    身份证读取设备开发解决方案 3 单片机读取身份证信息的demo 文章目录 身份证读取设备开发解决方案 3 单片机读取身份证信息的demo 一 前言 二 部分代码及结果展示 1 准备 2 部分代码 3 结果展示 三 常见错误 错误1 错误2
  • Qt 串口发送0x00

    应用场景 大恒光电的平移台 GCD 040101M 先看看要发什么东西 这是串口监听软件截取的结果 绿色的字 串口协议主要包括三个部分 前面是固定的 后面是key 后面是 0x00 最后面是数据 错误版本1 bool MoveStage w
  • 可靠传输的基本概念

    可靠传输的基本概念 使用差错检错技术 接受方的数据链路层就可以检测出真在传输过程中是否出现误码 这取决于数据链路层向上层提供的服务类型 不可靠传输 仅仅丢弃有误码的帧 其他的什么也不做 可靠传输 想方法实现发送端发送什么 接收端就收到什么
  • 一、利用AT指令配置esp8266——esp8266WIFI模块初探&STM32串口通信再探

    文章目录 一 esp8266初探 1 esp8266简介 2 esp8266使用方式 什么是AT指令 通过何种方式发送AT指令 二 STM32串口通信再探 1 printf 函数与串口中断函数 2 例子 小试牛刀 3 例子 再进一步 三 局
  • USB转RS485串口电路设计

    USB转串口芯片的串口信号一般为 TTL CMOS电平 在实现半双工 RS485 串口时需要外接485电平转换芯片 设计中需要有信号来控制 485 转接芯片的发送和接收使能端 建议选择自带485控制引脚的转接芯片 如 CH340 CH342
  • STM32双串口

    STM32双串口的使用 最近老是需要stm32通过串口去跟WiFi模块 蓝牙模块 openmv进行数据交互 然后需要用到stm32的串口调试 就把这个程序整理成一个工程 方便调试 实验目的 外设模块 WiFi模块 蓝牙模块 openmv 发
  • USART_FLAG_TC与 USART_FLAG_TXE之间的区别,各自的用途 - 附举例代码及说明

    USART FLAG TC与 USART FLAG TXE之间的联系 各自的用途 名词解释 STM32固件库使用手册 USART FLAG TXE 发送数据寄存器空标志位 USART FLAG TC 发送移位寄存器发送完成标志位 串口发送数
  • verilog_串口实现

    verilog 串口实现 概述 先了解串口的基础知识 串口是怎样传数据的 什么是波特率 波特率怎么计算 说明 通过Verilog编写串口 通过逻辑分析仪与串口模块的对接来进一步了解串口的应用 文章目录 1 什么是波特率 波特率怎么计算 1
  • QT开发之串口通信(四)

    VS2015 QtPackage版本1 3 11插件 QT5 13 1 最近使用串口遇到一些问题 1 问题 在上述编译环境下发生数据会出现发送一次数据后无法重复发送数据 返回值也没有问题 查询得知 QByteArray SendBytes
  • C#串口通信三步走

    第一步 实例化串口通讯类 SerialPort sp new SerialPort 第二步 设置串口信息并打开串口 串口设置 public void SetSP string PortName string BaudRate string
  • Arduino基础篇(五)-- 如何快速上手串口通信(Serial)

    文章目录 1 基础篇 1 1 通信基础 2 串口通信 2 1 Arduino串口的硬件结构 2 2 串口工作原理 2 3 硬件串口通信 2 4 软件模拟串口通信 1 基础篇 1 1 通信基础 1 并行通信 通过输入 输出端口在 Arduin
  • STM32F031串口(RS485)中断+DMA发送(预备知识)

    STM32F031串口 RS485 中断 DMA发送 前言 GPIO移植过程 与F1系列的一些区别 串口 DMA 前言 最近在搞STM32F031的项目 F0系列与常用的F1系列有一定区别 在开发过程中遇到一些问题 而且花了好长花间在搜寻解
  • 蓝桥杯51单片机之数码管从点亮到动态时钟的实现【单片机开发初学者必掌握】

    文章目录 一 点亮数码管 二 八位数码管同时从0到F 三 显示学号 指定数字 四 中断机制的引入 五 利用中断实现动态时钟 一 点亮数码管 首先看一下案例源码 include
  • STM32串口配置实验

    STM32 串口简介 串口作为 MCU 的重要外部接口 同时也是软件开发重要的调试手段 其重要性不言而喻 现在基本上所有的 MCU 都会带有串口 STM32 自然也不例外 STM32 的串口资源相当丰富的 功能也相当强劲 ALIENTEK
  • 51单片机之串口通讯应用实例(逻辑分析仪调试)

    硬件 STC89C52RC 开发工具 Keil uVision4 前言 8051是一款很经典的 历史悠久的单片机 作为一款入门级的单片机8051受到很多初学者的欢迎 89c52是8051系列的成员之一 拥有8K字节程序存储空间 512字节随
  • STM32串口中断接收方式详细比较

    本例程通过PC机的串口调试助手将数据发送至STM32 接收数据后将所接收的数据又发送至PC机 具体下面详谈 实例一 void USART1 IRQHandler u8 GetData u8 BackData if USART GetITSt

随机推荐