【STM32F103】USART通用同步异步收发器

news2024/12/27 12:06:29

串行通信

通信分为串行通信和并行通信,区别如下,同样是发送0101的数据:

可以看的出来,串行通信的优点是消耗的数据线会小一些。

而并行通信的优点是传输的速度快。

通常我们会选择使用串行通信来进行设备间的通信,这样会节省单片机引脚资源,同时传输的速率也是我们可以接受的。

串行通信又分为异步通信和同步通信。

异步通信的数据传输按帧传输,每一帧需要包含起始位,数据位,校验位和停止位,通过起始位和校验位我们就可以确定每帧数据的范围,校验位用来检验传输的数据是否有误。

同步通信由1~2个同步字符和多位数据位组成.同步字符用于触发同步时钟开始发送或是接收数据。多字节数据之间不允许有空隙,每位占用的时间相同。

小总结一下,异步通信对硬件的要求较低,实现起来简单灵活,但由于传输每个字节都需要建立一次同步,所以工作速度较低,单片机系统中主要是用异步通信。同步通信对硬件要求高,但是传输速度快,适用于成批的数据传输。

STM32F103中的USART

STM32F103C8T6一共有三个USART外设资源,具体的功能引脚可以参考下图(来自b站江科大自化协)

接线的时候需要注意的是,两个设备之间通信,设备A的RX(接收端)需要接到设备B的TX(发送端),设备A的TX(发送端)需要接到设备B的RX(接收端)。所以两个设备之间使用串行通信只需要两根线即可,可以看出来确实是很节省引脚资源,甚至如果A不需要发送数据只需要接收的话,是连TX(发送端)都不用连的。

根据手册的参考,我们需要将TX的GPIO口设置为推挽复用输出,RX的GPIO口设置为浮空输入或是上拉输入(和传输有关的我们设置为浮空输入)。

以下是官方给的参考手册的介绍:

随便看看就好,不影响我们的编程,因为官方固件库都给我们封装好了。

固件库函数

 初始化USART

参数一选择USART资源,STM32F103C8T6可以选的有USART1,USART2,USART3,要看准对应的引脚,不要接错了。

参数二参数USART_InitStruct类型的变量,通过这个变量的成员来对USART进行配置。

USART_BandRate:波特率,常用的有9600,115200等,最主要的是发送端和接收端的配置要一样,这样才可以进行通信。

USART_WordLength:传输的字长,可选的参数有USART_WordLength_8b或是USART_WordLength_9b。一般是选择8b,如果有校验位的话也就是加一位选9b。

USART_StopBits:停止位长度,一般选择USART_StopBits_1。这个和波特率一样没有什么特定需求,只需要发送方和接收方配置一样就行。

USART_Parity:校验,可以选择奇校验,偶校验,或者是不校验。奇校验就是在传输的数据后面再加一位校验位,在接收方收到数据之后,把接收到的数据(包括校验位)集中起来统计一下1出现的次数,如果为奇数那么就表示数据无误(实际上还是有可能是有问题的),偶校验和奇校验差不多,区别在于偶校验要求1出现的次数为偶数。如果选择了校验,那么上面的字长需要选择9b的选项。

USART_Mode:USART传输的模式,可选的有USART_Mode_RX和USART_Mode_TX。分别表示选择接收模式和发送模式,如果都要的话,可以用|连接起来,填入参数为USART_Mode_Rx|USART_Mode_Tx。

USART_HardwareFlowControl:硬件控制流选择,一般情况下用不着,我们选择USART_HardwareFlowControl_None即可。

上电USART

参数一选择USART资源,参数二选择是否使能(ENABLE/DISABLE)。

初始化和上电之后就可以开始发送数据了。

发送数据

参数一选择USART资源,参数二选择要传输数据。

这个函数执行完我们还需要等待数据传输完毕,等待的方法就是不断访问对应的标志位,直到标志位显示发送完毕即可。

查看标志位

参数一选择USART资源,参数二选择要访问的标志位。

检测发送是否完毕我们选择USART_FLAG_TXE

检测是否有数据可以接收USART_FLAG_RXNE

发送数据完毕之后标志位会自动置回去,所以我们不需要管。如果是接收数据的话,在接收完毕之后我们还要把对应的标志位手动清除。

清除标志位

参数一选择USART资源,参数二选择要清除的参数。

如果是只需要发送数据的话那么上面的函数就够用了,但如果还要接收数据的话还需要配置一下中断。

配置USART中断

参数一选择USART资源,参数二选择因为什么而中断,我们选择USART_IT_RXNE,即接收到数据之后进入中断,进入中断之后要根据上面的函数来获取标志位,清除标志位,然后再用接收数据的函数来获取数据。参数三选择ENABLE。

除了这个函数配置完中断之后还需要配置一下NVIC中断优先级配置,本文主要是讲USART的,就不细说,可以参考下面给出的代码。有关中断的内容,我后续专门写中断配置的时候会补上。

配置中断完毕之后,使用的中断函数为void USART1_IRQHandler(void)

中断函数的函数名可以在文件“startup_stm32f10x_md.s”中找到。

接收数据

参数一选择USART资源,返回接收到的数据。

这个函数我们在中断里调用,在上一条配置完中断以后,收到数据之后进入中断,然后使用这条函数来获取数据。

接线

使用USB转TTL的模块将STM32F103C8T6连接到电脑上,然后电脑上使用串口助手来查看传输的结果。我使用的串口助手是b站江科大自化协提供的,大家随便上网搜一个串口助手都能用。

将USB转TTL模块的RX接到STM32F103C8T6的USART1_TX(GPIOA的10号口)上,TX接到USART1_RX(GPIOA的9号口)上。

代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"                      //延时函数
#include "OLED.h"                       //OLED显示屏驱动函数

//中断函数
void USART1_IRQHandler(void){
    //判断数据接收标志位
    if(SET==USART_GetFlagStatus(USART1,USART_FLAG_RXNE)){
        uint16_t data=USART_ReceiveData(USART1);            //读取出接收的数据
        OLED_ShowHexNum(2,1,data,4);                        //使用OLED显示接收的数据
        USART_ClearITPendingBit(USART1,USART_FLAG_RXNE);    //清除数据接收标志位
    }
}

void sendbyte(uint16_t Data){
    //发送数据
    USART_SendData(USART1,Data);
    //等待数据发送完毕
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}


int main(void){
    OLED_Init();
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef itd;
    itd.GPIO_Mode=GPIO_Mode_AF_PP;      //复用推挽输出
    itd.GPIO_Pin=GPIO_Pin_9;            //TX引脚
    itd.GPIO_Speed=GPIO_Speed_2MHz;     //这个随意
    GPIO_Init(GPIOA,&itd);
    itd.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
    itd.GPIO_Pin=GPIO_Pin_10;           //RX引脚
    GPIO_Init(GPIOA,&itd);
    
    USART_InitTypeDef uitd;
    uitd.USART_BaudRate=9600;                                       //波特率
    uitd.USART_HardwareFlowControl=USART_HardwareFlowControl_None;  //硬件流控制
    uitd.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;                    //串口模式
    uitd.USART_Parity=USART_Parity_No;                              //校验
    uitd.USART_StopBits=USART_StopBits_1;                           //停止位长度
    uitd.USART_WordLength=USART_WordLength_8b;                      //传输的字长
    USART_Init(USART1,&uitd);
    
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);                    //开启USART接收中断
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                 //NVIC中断配置
    NVIC_InitTypeDef nitd;
    nitd.NVIC_IRQChannel=USART1_IRQn;
    nitd.NVIC_IRQChannelCmd=ENABLE;
    nitd.NVIC_IRQChannelPreemptionPriority=2;
    nitd.NVIC_IRQChannelSubPriority=2;
    NVIC_Init(&nitd);
    
    USART_Cmd(USART1,ENABLE);                                       //上电USART
    
    uint16_t data=0x00;
    while(1){
        sendbyte(data);
        data++;
        Delay_ms(500);
    }
}

效果

使用USART将调试信息打印到电脑的串口助手上

第一步先对Keil进行设置

选中魔术棒再勾上Use MicroLIB。

第二步加入库文件

#include <stdio.h>

第三步重写fputs函数,可以参考下面的写法。因为printf函数的底层就是调用的fputs函数,所以我们只需改写fputs即可。

int fputc(int ch, FILE *f){
    //sendbyte为自己写的发送一个数据的函数
    sendbyte(ch);
    return ch;
}

接下来就可以在程序中使用printf这个函数了,打印的内容会通过USART传输到电脑上,可以通过串口助手来查看。

代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

#include <stdio.h>

//中断函数
void USART1_IRQHandler(void){
    //判断数据接收标志位
    if(SET==USART_GetFlagStatus(USART1,USART_FLAG_RXNE)){
        uint16_t data=USART_ReceiveData(USART1);            //读取出接收的数据
        OLED_ShowHexNum(2,1,data,4);                        //使用OLED显示接收的数据
        USART_ClearITPendingBit(USART1,USART_FLAG_RXNE);    //清除数据接收标志位
    }
}

void sendbyte(uint16_t Data){
    //发送数据
    USART_SendData(USART1,Data);
    //等待数据发送完毕
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

int fputc(int ch, FILE *f){
    sendbyte(ch);
    return ch;
}

int main(void){
    OLED_Init();
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef itd;
    itd.GPIO_Mode=GPIO_Mode_AF_PP;      //复用推挽输出
    itd.GPIO_Pin=GPIO_Pin_9;            //TX引脚
    itd.GPIO_Speed=GPIO_Speed_2MHz;     //这个随意
    GPIO_Init(GPIOA,&itd);
    itd.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
    itd.GPIO_Pin=GPIO_Pin_10;           //RX引脚
    GPIO_Init(GPIOA,&itd);
    
    USART_InitTypeDef uitd;
    uitd.USART_BaudRate=9600;                                       //波特率
    uitd.USART_HardwareFlowControl=USART_HardwareFlowControl_None;  //硬件流控制
    uitd.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;                    //串口模式
    uitd.USART_Parity=USART_Parity_No;                              //校验
    uitd.USART_StopBits=USART_StopBits_1;                           //停止位长度
    uitd.USART_WordLength=USART_WordLength_8b;                      //传输的字长
    USART_Init(USART1,&uitd);
    
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);                    //开启USART接收中断
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                 //NVIC中断配置
    NVIC_InitTypeDef nitd;
    nitd.NVIC_IRQChannel=USART1_IRQn;
    nitd.NVIC_IRQChannelCmd=ENABLE;
    nitd.NVIC_IRQChannelPreemptionPriority=2;
    nitd.NVIC_IRQChannelSubPriority=2;
    NVIC_Init(&nitd);
    
    USART_Cmd(USART1,ENABLE);                                       //上电USART
    
    uint16_t data=0;
    while(1){
        printf("Hello World! %d\r\n",data);
        data++;
        Delay_ms(500);
    }
}

效果

 串口助手需要改成接收文本模式。

参考

b站江科大自化协

《STM32F10xxx参考手册(中文)》

《ARM Cortex-M3 嵌入式原理及应用 基于STM32F103微控制器》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1292831.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

参考信号速度变化存在跳跃时容易发生不稳定的阻抗调节

问题描述 当参考信号速度存在跳跃变化时&#xff0c;阻抗调节系统容易发生不稳定。这是因为阻抗调节系统需要根据参考信号的速度来调整其输出阻抗&#xff0c;以匹配负载阻抗&#xff0c;从而保持系统的稳定性。 当参考信号速度突然变化时&#xff0c;阻抗调节系统可能无法及…

智能安防无人机——一种安防巡检新方案

在高新技术的推动下&#xff0c;安防无人机在监控、巡逻等领域的使用频率越来越高&#xff0c;逐渐成为安防救援的重要帮手。安防无人机作为城市安全应急保障体系的重要组成部分&#xff0c;在未来将变得不可或缺。 一、安防无人机的定义及构成 复亚智能无人机全自主巡飞系统由…

Redis——简单动态字符串(Simple Dynamic Strings,SDS)

简单动态字符串&#xff08;Simple Dynamic Strings,SDS&#xff09;是Redis的基本数据结构之一&#xff0c;用于存储字符串和整型数据。SDS兼容C语言标准字符串处理函数&#xff0c;且在此基础上保证了二进制安全。 1、数据结构 在了解SDS源码前&#xff0c;我们先思考一个问…

Android平板还能编程?Ubuntu本地安装code-server远程编程写代码

文章目录 1.ubuntu本地安装code-server2. 安装cpolar内网穿透3. 创建隧道映射本地端口4. 安卓平板测试访问5.固定域名公网地址6.结语 1.ubuntu本地安装code-server 准备一台虚拟机,Ubuntu或者centos都可以&#xff0c;这里以VMwhere ubuntu系统为例 下载code server服务,浏览器…

PMSM转速电流双闭环调速仿真simulink

威♥关注“电击小子程高兴的MATLAB小屋”获取专享优惠 PMSM永磁同步电机PI双闭环&#xff08;速度&#xff0c;电流调节&#xff09;SVPWM矢量matlab-simulink仿真 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2017Rb&#xff09;软件。建议采用matlab…

Large Language Models areVisual Reasoning Coordinators

目录 一、论文速读 1.1 摘要 1.2 论文概要总结 二、论文精度 2.1 论文试图解决什么问题&#xff1f; 2.2 论文中提到的解决方案之关键是什么&#xff1f; 2.3 用于定量评估的数据集是什么&#xff1f;代码有没有开源&#xff1f; 2.4 这篇论文到底有什么贡献&#xff1…

多路径传输(MPTCP MPQUIC)数据包调度研究总结

近些年来&#xff0c;以5G和Wifi6为代表的无线通信技术发展迅速&#xff0c;并已经在全世界实现了大规模部署。此外&#xff0c;智能手机等移动设备不断迭代更新&#xff0c;其网络通信能力也持续演进&#xff0c;使得应用同时利用多个不同网卡在多条不同物理链路上&#xff08…

从遍历到A星寻路算法

在游戏当中&#xff0c;经常需要找一个点到其它点的路径。在之前的一篇博文(地图编辑器开发&#xff08;三&#xff09;)中也有使用到到A*寻路算法。我们期望能找到最短的路径&#xff0c;同时也需要考虑到查找路径的时间消耗。游戏中的地图可以图的数据结构来表示&#xff0c;…

【科普】什么是电子印章? PS抠的印章能用吗?

各类扣章教程一搜一大堆&#xff0c;说明大家对于电子印章使用需求很高。不过要谨记&#xff0c;不要随便抠印章用于公文、证明书、合同协议、收据发票等电子文件&#xff0c;否则可能会吃牢饭。 单是一张电子化的图片是不具备合法性的。那有的人就要问了&#xff0c;我见到的…

采样率越高噪声越大?

ADC采样率指的是模拟到数字转换器&#xff08;ADC&#xff09;对模拟信号进行采样的速率。在数字信号处理系统中&#xff0c;模拟信号首先通过ADC转换为数字形式&#xff0c;以便计算机或其他数字设备能够处理它们。 ADC采样率通常以每秒采样的次数来表示&#xff0c;单位为赫…

【开源】基于Vue.js的新能源电池回收系统

文末获取源码&#xff0c;项目编号&#xff1a; S 075 。 \color{red}{文末获取源码&#xff0c;项目编号&#xff1a;S075。} 文末获取源码&#xff0c;项目编号&#xff1a;S075。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户档案模块2.2 电池品类模块2.3 回…

PXI总线测试模块6944F DC~40GHz 1选6微波开关

01 6944F DC~40GHz 1选6微波开关 产品综述&#xff1a; 6944F DC~40GHz 1选6微波开关集成2组SP6T开关&#xff0c;通道最高切换频率可 达40GHz&#xff0c;具有插入损耗小、通道驻波比小、开关承受功率大、软件驱动标准规范等特点。该产品可广泛应用于通信、半导体自动测…

Vue2脚手架搭建+项目基础依赖安装

文章目录 1. 安装 node.js2. 安装 vue-cli 脚手架3. 创建 vue2 项目4. 安装基础依赖 1. 安装 node.js 可以参考这篇文章 https://blog.csdn.net/weixin_43721000/article/details/134284418 2. 安装 vue-cli 脚手架 安装 vue-clinpm install -g vue/cli查看是否安装成功vue -…

【数据库】基于时间戳的并发访问控制,乐观模式,时间戳替代形式及存在的问题,与封锁模式的对比

使用时间戳的并发控制 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会…

添加新公司代码的配置步骤-Part3

原文地址&#xff1a;配置公司代码 概述 这是讨论创建新公司代码的基本标准配置步骤的第三篇博客。在第 1 部分中&#xff0c;我列出并讨论了企业结构中需要配置的项目。我随后提供了特定 FI 配置的详细信息。在本版本中&#xff0c;我将重点关注 SD 和 MM 模块。以下是这些博…

【C语言】函数递归--输出n的k次方

题目描述&#xff1a; 递归实现n的k次方 代码如下&#xff1a; #include<stdio.h> int nk(int n, int k) {if (k > 0)return n * nk(n, k - 1); } int main() {int ret 0;int n 0;int k 0;scanf("%d", &n);scanf("%d", &k);ret nk(n…

Redis哈希对象(listpack介绍)

哈希对象的编码可以是ziplist或者hashtable。再redis5.0版本之后出现listpack&#xff0c;为了是代替ziplist。 一. 使用ziplist编码 ziplist编码的哈希对象使用压缩列表作为底层实现&#xff0c;每当有新的键值对要加入到哈希对象时&#xff0c;程序都会先将保存了键值对的键…

深眸科技以机器视觉高性能优势,为消费电子行业提供优质解决方案

机器视觉技术近年来发展迅速&#xff0c;基于计算机对图像的处理与分析&#xff0c;能够识别和辨别目标物体&#xff0c;被广泛应用于人工智能、智能制造等领域。 机器视觉凭借着高精度、高效率、灵活性和可靠性等优势&#xff0c;不断推进工业企业生产自动化和智能化进程&…

9、web安全综述

文章目录 一、web核心组成二、web架构2.1 Web服务器2.2 Web容器2.3 Web服务端语言2.4 web开发框架2.6 软件系统 三、常见web安全漏洞3.1 信息泄露3.2 目录遍历3.3 跨站脚本攻击&#xff08;XSS&#xff09;3.4 SQL注入漏洞3.5 文件上传漏洞3.6 命令执行漏洞3.7 文件包含漏洞 一…

Halcon reduce_domain和scale_image的作用

在Halcon中&#xff0c;reduce_domain是用于缩小图像域&#xff08;Image Domain&#xff09;的操作。 它的作用是通过指定一个感兴趣区域&#xff08;ROI&#xff0c;Region of Interest&#xff09;&#xff0c;将图像数据限制在该区域内&#xff0c;从而实现对图像进行裁剪…