STM32串口通信(发送与接收数据)

文章目录

  • 前言
  • 一、介绍部分
    • 通信接口
      • 术语解释
    • 串口通信简介
    • 硬件电路
    • 电平标准
    • 串口参数
    • 串口时序
    • USART简介
      • USART框图
      • USRAT基本结构
      • 数据帧
      • 起始位检测
      • 波特率发生器
      • CH340G
  • 二、实例部分
    • 使用串口发送数据
    • 接线图
      • 代码实现
      • 重定向printf需要勾上Use MicroLIB
      • 中文不乱码方法
    • 串口的发送与接收数据
      • 线路连接与上面一致
      • 代码实现


前言

串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。本文主要接收使用串口发送接收数据,波特率设置,串口的基本时序等。


一、介绍部分

通信接口

在这里插入图片描述

术语解释

在这里插入图片描述

串口通信简介

在这里插入图片描述

硬件电路

在这里插入图片描述

电平标准

在这里插入图片描述

串口参数

在这里插入图片描述

串口时序

在这里插入图片描述

USART简介

在这里插入图片描述

USART框图

在这里插入图片描述

USRAT基本结构

在这里插入图片描述

数据帧

在这里插入图片描述
在这里插入图片描述

起始位检测

在受到噪声影响后,采用2:1策略,选择更多的作为所接收到的数据,并使噪声标志位NE置1

在这里插入图片描述
在这里插入图片描述

波特率发生器

在这里插入图片描述
在这里插入图片描述

CH340G

在这里插入图片描述

二、实例部分

使用USART1来作为例子,根据引脚定义,选择正确的接口
在这里插入图片描述

使用串口发送数据

接线图

在这里插入图片描述

代码实现

配置串口Serial.c

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>void Serial_Init(void){// 开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);// 初始化引脚,发送数据引脚GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		// 复用推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;	// A9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		// 50Hz翻转速度GPIO_Init(GPIOA, &GPIO_InitStructure);// 初始化串口配置USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600; // 串口波特率USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用流控USART_InitStructure.USART_Mode = USART_Mode_Tx; // 串口模式,发送USART_InitStructure.USART_Parity = USART_Parity_No; // 无校验USART_InitStructure.USART_StopBits = USART_StopBits_1; // 选择一位停止位USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 不需要校验位,八位字长USART_Init(USART1,&USART_InitStructure);// USART1使能USART_Cmd(USART1,ENABLE);
}// 发送函数
void USART_SendByte(uint8_t Byte){USART_SendData(USART1,Byte);// 等待写入完成,写入完成之后会将标志位自动清0while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}// 发送数组函数
void USART_SendArray(uint8_t *Array,uint16_t Length){uint8_t i = 0;for(i=0;i<Length;i++){USART_SendData(USART1,Array[i]);// 等待写入完成,写入完成之后会将标志位自动清0while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);}
}// 发送字符串函数
void USART_SendString(uint8_t *String){uint8_t i = 0;for(i=0;String[i]!='\0';i++){USART_SendData(USART1,String[i]);// 等待写入完成,写入完成之后会将标志位自动清0while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);}
}// 返回X的Y次方
uint32_t Serial_Pow(uint32_t X,uint32_t Y){uint32_t Result = 1;while(Y--){Result *= X;}return Result;
}
// 发送数字函数
void USART_SendNum(uint32_t Num,uint16_t Length){uint8_t i = 0;for(i=0;i<Length;i++){USART_SendByte(Num / Serial_Pow(10,Length-i-1) % 10 + 0x30);// 等待写入完成,写入完成之后会将标志位自动清0while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);}
}//重定向fputc函数,fputc是printf函数的底层,printf通过不停的调用fputc来达到输出的效果
//重定向到串口
int fputc(int ch,FILE *f){USART_SendByte(ch);return ch;
}// 封装使用sprintf输出到串口
void Serial_Printf(char *format, ...)
{char String[100];va_list arg;							// 可变参数列表va_start(arg, format);		// 从format开始接收可变参数vsprintf(String, format, arg);va_end(arg);USART_SendString((uint8_t*)String);
}

主函数main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"int main(void)
{OLED_Init();Serial_Init();//USART_SendByte();
//	uint8_t Array[] = {0x41,0x42,0x43,0x44};
//	USART_SendArray(Array,4);
//	uint8_t String[] = {"hello world"};
//	USART_SendString(String);
//	USART_SendNum((uint32_t)12345,5);
//	printf("Num = %d\r\n",666);
//	char String[100];
//	sprintf(String,"Num = %d\r\n",666);
//	USART_SendString((uint8_t*)String);Serial_Printf("一程山水");while (1){}
}

重定向printf需要勾上Use MicroLIB

在这里插入图片描述

中文不乱码方法

  1. 代码与串口都使用utf8格式,并在如下图位置加上–no-multibyte-chars
  2. 使用GB2312支持中文编码格式,串口使用GBK编码格式接收即可。

串口的发送与接收数据

线路连接与上面一致

代码实现

串口配置Serial.c

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>uint8_t RxData;
uint8_t RxFlag;void Serial_Init(void){// 开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);// 初始化引脚GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		// 复用推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;	// A9 发送数据GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		// 50Hz翻转速度GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		// 上拉输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;	// A10 接收数据GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		// 50Hz翻转速度GPIO_Init(GPIOA, &GPIO_InitStructure);// 初始化串口配置USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600; // 串口波特率USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用流控USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 串口模式,发送+接收USART_InitStructure.USART_Parity = USART_Parity_No; // 无校验USART_InitStructure.USART_StopBits = USART_StopBits_1; // 选择一位停止位USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 不需要校验位,八位字长USART_Init(USART1,&USART_InitStructure);// 开启中断USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//初始化NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	// 分组NVIC_InitTypeDef NVIC_InitStructure;// 中断通道NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;// 中断通道使能NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;// 抢占优先级NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;// 响应优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);// USART1使能USART_Cmd(USART1,ENABLE);
}// 发送函数
void USART_SendByte(uint8_t Byte){USART_SendData(USART1,Byte);// 等待写入完成,写入完成之后会将标志位自动清0while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}// 发送数组函数
void USART_SendArray(uint8_t *Array,uint16_t Length){uint8_t i = 0;for(i=0;i<Length;i++){USART_SendData(USART1,Array[i]);// 等待写入完成,写入完成之后会将标志位自动清0while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);}
}// 发送字符串函数
void USART_SendString(uint8_t *String){uint8_t i = 0;for(i=0;String[i]!='\0';i++){USART_SendData(USART1,String[i]);// 等待写入完成,写入完成之后会将标志位自动清0while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);}
}// 返回X的Y次方
uint32_t Serial_Pow(uint32_t X,uint32_t Y){uint32_t Result = 1;while(Y--){Result *= X;}return Result;
}
// 发送数字函数
void USART_SendNum(uint32_t Num,uint16_t Length){uint8_t i = 0;for(i=0;i<Length;i++){USART_SendByte(Num / Serial_Pow(10,Length-i-1) % 10 + 0x30);// 等待写入完成,写入完成之后会将标志位自动清0while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);}
}//重定向fputc函数,fputc是printf函数的底层,printf通过不停的调用fputc来达到输出的效果
//重定向到串口
int fputc(int ch,FILE *f){USART_SendByte(ch);return ch;
}// 封装使用sprintf输出到串口
void Serial_Printf(char *format, ...)
{char String[100];va_list arg;							// 可变参数列表va_start(arg, format);		// 从format开始接收可变参数vsprintf(String, format, arg);va_end(arg);USART_SendString((uint8_t*)String);
}// 获取RxFlag
uint8_t USART_GetRxFlag(void){if(RxFlag == 1){RxFlag = 0;return 1;}return 0;
}// 获取RxData
uint8_t USART_GetRxData(void){return RxData;
}//中断函数
void USART1_IRQHandler(void){if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET){RxData = USART_ReceiveData(USART1);RxFlag = 1;USART_ClearITPendingBit(USART1,USART_IT_RXNE);}
}

主函数main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"uint8_t Serial_RxData;int main(void)
{OLED_Init();OLED_ShowString(1, 1, "RxData:");Serial_Init();while (1){if (USART_GetRxFlag() == 1){Serial_RxData = USART_GetRxData();USART_SendByte(Serial_RxData);OLED_ShowHexNum(1, 8, Serial_RxData, 2);}}
}

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

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

相关文章

C++ 之LeetCode刷题记录(三十六)

&#x1f604;&#x1f60a;&#x1f606;&#x1f603;&#x1f604;&#x1f60a;&#x1f606;&#x1f603; 开始cpp刷题之旅。 目标&#xff1a;执行用时击败90%以上使用 C 的用户。 16. 最接近的三数之和 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你…

Python 从文件中读取JSON 数据并解析转存

文章目录 文章开篇Json简介Json数据类型Json硬性规则Json数据转化网站Json和Dict类型转换json模块的使用Python数据和Json数据的类型映射json.dumps1.字典数据中含有**存在中文**2.json数据通过缩进符**美观输出**3.对Python数据类型中键进行**排序输出**4.json数据**分隔符的控…

【软件测试】接口调不通排查分析+常遇面试题总结

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、接口调不通&am…

【论文阅读】深度学习在过冷沸腾气泡动力学分割中的应用

Application of deep learning for segmentation of bubble dynamics in subcooled boiling 深度学习在过冷沸腾气泡动力学分割中的应用 期刊信息&#xff1a;International Journal of Multiphase Flow 2023 级别&#xff1a;EI检索 SCI升级版工程技术2区 SCI基础版工程技术3区…

(libusb) usb口自动刷新

文章目录 libusb自动刷新程序Code目录结构Code项目文件usb包code包 效果描述重置reset热拔插使用 END libusb 在操作USB相关内容时&#xff0c;有一个比较著名的库就是libusb。 官方网址&#xff1a;libusb 下载&#xff1a; 下载源码官方编好的库github&#xff1a;Release…

新的一年,如何优化企业库存管理?

随着社会的发展和经济的不断增长&#xff0c;库存管理成为了企业运营中非常重要的一环。库存作为企业的资产之一&#xff0c;直接影响着企业的盈利能力和竞争优势。因此&#xff0c;对企业库存进行科学的分析和管理&#xff0c;成为了确保企业持续稳定发展的必要手段之一。企业…

比亚迪领航新能源时代:汉唐传承,品牌力量

比亚迪&#xff0c;以中国文化的深度与自信&#xff0c;为新能源汽车领域注入强大动力。汉唐车型&#xff0c;不仅承载着中国古代文明的辉煌&#xff0c;更以其创新技术和环保理念&#xff0c;终结油电之争&#xff0c;让燃油车再次破防。作为销量冠军&#xff0c;比亚迪品牌的…

android开发与实战,那些年Android面试官常问的知识点

前言 在做android项目开发时&#xff0c;大家都知道如果程序出错了&#xff0c;会弹出来一个强制退出的弹 出框&#xff0c;这个本身没什么问题&#xff0c;但是这个UI实在是太丑了&#xff0c;别说用户接受不了&#xff0c;就连 我们自己本身可能都接受不了。虽然我们在发布程…

1.2 debug的六种指令的使用,四个通用寄存器

汇编语言 首先进入环境 mount c d:masm //把c挂载在d盘中的masm当中 c: //进入c&#xff0c;进入到编译环境 dir //查看文件&#xff0c;可有可无Debug是DOS、Windows都提供的实模式&#xff08;8086 方式&#xff09;程序的调试工具。使用它可以查看CPU各种寄存器中的内容…

C语言基础18 循环

们可能需要多次执行同一块代码。一般情况下&#xff0c;语句是按顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着是第二个语句&#xff0c;依此类推。 编程语言提供了更为复杂执行路径的多种控制结构。 循环语句允许我们多次执行一个语句或语句组&#xff0…

leetcode刷题(剑指offer) 46.全排列

46.全排列 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a; 输入&#…

OpenAI Triton 入门教程

文章目录 Triton 简介背景Triton 与 CUDA 的关系 Triton 开发样例样例一&#xff1a;Triton vector addition 算子Triton kernel 实现kernel 函数封装函数调用性能测试 样例二&#xff1a;融合 Softmax 算子动机Triton kernel 实现kernel 封装单元测试性能测试 样例三&#xff…

苍穹外卖Day03——解决总结3中存在的问题

解决Day03中存在的问题 1. ResponseBody 与 RequestBody2. RequestParam 与 PathVariable3. 字段填充技术&#xff08;注解、AOP、反射&#xff09;3.1. AOP3.2. 注解3.3. 反射3.5 字段填充在项目应用 4. 阿里云云存储OOS 1. ResponseBody 与 RequestBody ResponseBody&…

面试经典150题——矩阵置零

​"Dream it. Wish it. Do it." - Unknown 1. 题目描述 2. 题目分析与解析 2.1 思路一——暴力求解 思路一很简单&#xff0c;就是尝试遍历矩阵的所有元素&#xff0c;如果发现值等于0&#xff0c;就把当前行与当前列的值分别置为0。同时我们需要注意&#xff0c;…

【Java】基本数据类型、包装类与字符串间的转换 例题

写在前面&#xff1a; 关于这道题&#xff0c;初见感觉有点cpu烧坏了&#xff0c;准确来说是看了网上的一些讲解都感觉不尽人意。自己整理了一下&#xff0c;希望能帮助到大家。 题目&#xff1a; 如下两个题目输出结果相同吗&#xff1f;各是什么。 Object o1 true ? new…

java演唱会网上订票购票系统springboot+vue

随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的交换和信息流通显得特别重要。因此&#xff0c;开发合适的基于springboot的演唱会购票系统的设计与实现成为企业必然要走…

基于uniapp开发小程序,代码上线发布教程【抖音、微信】

本系列文章适合三类同学&#xff1a;1.希望学习小程序开发&#xff1b;2.希望无代码、低代码拥有自己的小程序&#xff1b;3.快速搭建小程序交作业、交毕设的大学生 本系列文章将推出配套桌面端软件&#xff0c;配合软件&#xff0c;可实现傻瓜式开发小程序&#xff0c;请有需求…

@Slf4j 变量log找不到符号,可能是 Gradle 配置文件写得有问题

Slf4j 变量log找不到符号 鄙人在学习 Java 的 spring boot 项目时, 常常因为 maven 配置文件使用 xml 格式过于复杂, 所以更倾向于使用 gradle 作为构建工具. 然而, 在使用 gradle 作为构建工具时, 又需要引用 Lombok 依赖. 有时忘记在初始化项目时添加上 Lombok 依赖, 所以经…

C++ deque详解以及容器适配器

目录 1.容器适配器 2.deque的使用 2.1deque的介绍 2.2deque的缺陷 2.3deque作为stack和queue的可行性 2.4 deque类的使用 2.4.1deque的构造函数 2.4.2deque容量操作 2.4.3deque赋值&#xff0c;插入 1.容器适配器 适配器是一种设计模式&#xff08;设计模式是一套被人…

idea创建一个简单的maven项目

个人学习笔记&#xff08;整理不易&#xff0c;有帮助点个赞&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 添加-DarchetypeCataloginternal 运行参数 (ps:不填的话&#xff0c;maven 骨架生成速度缓慢) 其实我没…