【stm32】USART编码部分--详细步骤

USART编码部分(文章最后附上源码)

如果看不懂步骤可以根据源码参考此篇文章就能轻而易举学会USART通信啦!

编码步骤

第一步 开启时钟

把需要用到的USART和GPIO的时钟打开

第二部 GPIO初始化

把TX配置成复用输出,RX配置成输入(上拉输入、浮空输入)。

第三步 配置USART初始化

一个结构体配置所有参数

第四步 发送或接收

只需发送功能
  • 就直接开启USART,初始化就结束了
关于发送数据的类型
  1. 首先写发送一个字节数据的函数 SendByte函数

    1. 调用函数USART_SendData

    2. 等待发送寄存器空标志位

  2. 发送数组SendArray的函数

    1. 函数名形参一个字符指针,长度
    2. 函数体内调用SendByte,一位一位的发送数组数据
  3. 发送字符串 SendString 的函数

    1. 形参为一个字符指针

    2. 函数体内使用for循环或while一位一位的发送字符串的每个字节,直到遇到\0停止

  4. 发送数字SendNumber的函数

    1. 形参一个数字,类型给32位,然后还有一个长度

    2. 在函数里面需要把Number的十位个位百位等,以十进制拆分开,然后转换成字符数字对应的数据,一次发送出去

    3. 比如12345, 取万位就是12345/10000%10得到万位

    4. 需要先写一个次方函数, 形参是一个X,一个y,返回值是X的Y次方,都是32位

    5. 在这里插入图片描述

    6. 回到SendNumber,也是每次发送数据的每一位这个逻辑

    7. 在这里插入图片描述

需要接收功能
  • 首先配置PA10为上拉输入或者浮空输入

  • 接着在串口初始化里配置接收模式

  • 可以使用查询和中断两种方法

  • 如果使用查询,那初始化就结束了

    • 查询的流程是:

    • 在主函数里不断判断RXNE标志位,如果置1了(if成立),就说明收到数据了

    • 再调用ReceiveData,读取DR寄存器,就ok了

    • 最后还有清除标志位的问题,根据参考手册的寄存器描述进行相应的判断,是否需要清除标志位

    • 在这里插入图片描述

  • 如果使用中断,还需要在USART_cmd之前开去中断,配置NVIC,那就在开启USART之前,再加上ITConfig和NVIC的代码就行了

    • 接着写中断函数,在启动文件查找函数名

    • 中断函数里判断接收寄存器非空标志位

接收数据步骤(中断函数建立之后)
  1. 定义一个接收数据的变量和一个接受变量的标志位

    1. 在这里插入图片描述
  2. 建立一个接收数据标志位自动请0的函数,函数里清零标志位,返回1

  3. 建立一个返回数据的函数 GetRxData 的函数,把接收到了数据返回

    1. 上面两部也可以通过把两个变量声明为外部可调用的全局变量
  4. 中断函数里引用接收数据函数,赋给接收数据的变量,置标志位为1,证明接收到了数据

  5. 主函数里判断标志位,如果标志位为1,证明接收到了数据

  6. 可以在判断函数里使用OLED显示串口接收到的数据,然后把这个数据使用串口发送函数再发送到电脑串口助手进行显示

初始化之后

  • 初始化之后,如果要发送数据,调用一个发送函数就行了

  • 如果要接收数据,就调用接收的函数

  • 如果要获取发送和接收的状态,就调用获取标志位的函数

USART 函数介绍

  • USART_ClockInit 和 USART_ClockStrustInit 用来配置同步时钟输出的,包括时钟是不是要输出,时钟的极性相位等参数

  • USART_DMACmd 可以开启USART到DMA的触发通道

  • USART_SendData 发送数据

  • USART_ReceiveData 接收数据

      *发送和接收的时候用*
    

关于子函数

传递字符串

由于字符串自带一个结束标志为,所以就不需要传递长度参数;
for(i=0; String[i] != ‘\0’; i++)

换行:Serial_SendString(“\r\n”)

传递数字

  • 加一个偏移

  • 首先定义一个取数字模的函数Serial_Pow

  • Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + 0x30);//0x30可以写成’0’

Printf函数一直方法使用

  1. 使用Printf之前,打开工程选项,勾选Use MicroLIB(是Keil为嵌入式平台优化的一个精简库)

  2. 要用的Printf函数就可以用MicroLIB

  3. 对Printf进行重定向,将Printf打印的东西输出到串口,因为printf函数默认输出到屏幕,单片机没有屏幕,所以要进行重定向。

printf使用步骤

  1. 最开始加上,#include<stdio.h>

  2. 在最后重写fputc函数。 int fputc(int ch, FILE *F) 这是fputc函数的原型

  3. 然后在函数里面把fputc重定向到串口 (Serial_SendByte(ch));

  4. return ch;

  5. 这样printf函数就移植好了

  6. 最后在串口头文件中包含#include<stdio.h>,相当于main函数内也包含stdio.h

fputc 与 Printf的关系

  • 因为fputc是pritf函数的底层

  • pritf函数在打印的时候,就是不断调用fputc函数一个个打印的

  • 我们把fputc函数重定向到了串口,那printf自然就输出到了串口

printf函数在主函数中使用方法

printf(“Num=%d\r\n”,666);

如果多个串口都想用Printf的方法

这时就可以用Spritf

  • Spritf可以把格式化字符输出到,一个字符串里
  1. 先定义一个字符串(主函数里) char string[100]

  2. 然后sprintf第一个参数是打印输出的位置, sprintf(string, “Num=%d\r\n”,666);

  3. 目前这个格式化的字符在String里

  4. 接着Serial_SendString

  • sprintf可以设置打印位置,不涉及重定向

  • 所以每个串口都有可以使用Sprintf进行打印

封装Sprintf

  • 由于printf这类函数比较特殊,它支持可变的参数
  1. 在串口模块里添加头文件 #include <stdarg.h>

  2. 然后在最后对printf函数进行封装 void Serial_Printf(char *format, …) format这个参数用来接收格式化字符串 …三个点用来接收后面的可变参数列表

  3. 在函数里面

    1. 首先定义输出的字符串 char string[100]

    2. va_list arg 定义一个参数列表变量

    3. va_start(arg, format) 从format位置开始接收参数表,放在arg里面

    4. 之后 vsprintf(string, format, arg); 对于这种封装格式要用vsprintf

    5. va_end(arg) 释放参数表

    6. 最后是 Serial_SendString(String) 把String发送出去

    7. 在这里插入图片描述

关于乱码

在这里插入图片描述

Serial.c文件程序//也就是串口的.c文件

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>

uint8_t Serial_RxData;
uint8_t Serial_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;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	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);
	
	NVIC_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);
	
	USART_Cmd(USART1, ENABLE);
}

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}

uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}

void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}

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

void Serial_Printf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	Serial_SendString(String);
}

uint8_t Serial_GetRxFlag(void)
{
	if (Serial_RxFlag == 1)
	{
		Serial_RxFlag = 0;
		return 1;
	}
	return 0;
}

uint8_t Serial_GetRxData(void)
{
	return Serial_RxData;
}

void USART1_IRQHandler(void)
{
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		Serial_RxData = USART_ReceiveData(USART1);
		Serial_RxFlag = 1;
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

Serial.h文件程序//也就是串口的.h文件

#ifndef __SERIAL_H
#define __SERIAL_H

#include <stdio.h>

void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);

uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);

#endif

main.c文件程序

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

uint8_t RxData;

int main(void)
{
	OLED_Init();
	OLED_ShowString(1, 1, "RxData:");
	
	Serial_Init();
	
	while (1)
	{
		if (Serial_GetRxFlag() == 1)
		{
			RxData = Serial_GetRxData();
			Serial_SendByte(RxData);
			OLED_ShowHexNum(1, 8, RxData, 2);
		}
	}
}

感谢各位能坚持看到这里!

如果能有机会得到您的一个小赞那我就更有动力了!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CCIE-12-IPSec-VPN-RemoteAccess

目录 实验条件网络拓朴实验目的 开始配置1. R2 Ping R3确定基础网络是通的2. 配置R23. 配置R53. 验证 实验条件 网络拓朴 实验目的 为R2和R3建立IPSec VPN R4可以ping通R5 开始配置 R2&#xff1a;模拟需要远程访问网络的网关 R4&#xff1a;模拟需要远程访问网络内的目标主…

selenium 遮罩层

之前写智联自动投简历 和boss自动投简历的时候 发现操作到上限之后就有个遮罩层&#xff0c;会在当前页面有个顶层得div 没办法获取下面的内容 # 假设遮罩层元素有一个特定的ID或者其他属性 没有id xpath 或者class 都可以mask_element WebDriverWait(driver, 10).until(EC.…

农业信息管理(源码+文档)

农业信息管理系统&#xff08;小程序、ios、安卓都可部署&#xff09; 文件包含内容程序简要说明功能项目截图客户端首页我的今日动态动态详情登录修改资料今日价格今日报价注册页 后端管理文章管理用户管理分类管理 文件包含内容 1、搭建视频 2、流程图 3、开题报告 4、数据库…

Python:百度AI开放平台——OCR图像文字识别应用

一、注册百度AI开放平台 使用百度AI服务的步骤为&#xff1a; 注册&#xff1a;注册成为百度AI开放平台开发者&#xff1b;创建AI应用&#xff1a;在百度API开放平台上创建相关类型的的AI应用&#xff0c;获得AppID、API Key和Secret Key&#xff1b;调用API&#xff1a;调用…

AR和VR如何改变客户体验?

How AR and VR are transforming customer experiences&#xff1f; How AR and VR are transforming customer experiences AR和VR如何改变客户体验 AR and VR technology was largely expedited by the past pandemic with at least 93.3 million and 58.9 million users r…

基于Java+SpringBoot+Mybaties+layui+Vue+elememt 实习管理系统 的设计与实现

一.项目介绍 前台功能&#xff1a;用户进入系统可以实现首页&#xff0c;系统公告&#xff0c;个人中心&#xff0c;后台管理等功能进行操作 后台由管理员&#xff0c;实习单位&#xff0c;教师和学生&#xff0c;主要功能包括首页&#xff0c;个人中心&#xff0c;班级管理&am…

ETL工具-nifi干货系列 第六讲 处理器JoltTransformJSON

1、处理器作用 使用Jolt转换JSON数据为其他结构的JSON,成功的路由到success,失败的failure。处理JSON的实用程序不是基于流的&#xff0c;因此大型JSON文档转换可能会消耗大量内存。 Jolt&#xff1a;JSON 到 JSON 转换库&#xff0c;用 Java 编写&#xff0c;其中转换的 &qu…

【Jmeter+Influxdb+Grafana性能监控平台安装与部署】

JmeterInfluxdbGrafana性能监控平台安装与部署 前言Influxdb安装与连接Jmeternfluxdb下载&#xff08;winodws&#xff09;Grafana安装与配置 前言 我们在性能测试过程中&#xff0c;在需要较大并发时&#xff0c;为了尽量避免使用GUI界面来节省资源&#xff0c;通常使用命令行…

EfficientVMamba实战:使用EfficientVMamba实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构编译安装Vim环境环境安装过程安装库文件 计算mean和std生成数据集 摘要 论文&#xff1a;https://arxiv.org/pdf/2401.09417v1.pdf 作者研究了轻量级模型设计的新方法&#xff0c;通过引入视觉状态空间模型&…

Leetcode 4.1

LeetCode 热题 100 贪心算法1.买卖股票的最佳时机2.跳跃游戏3.跳跃游戏 II4.划分字母区间 区间合并1.合并区间 贪心算法 1.买卖股票的最佳时机 买卖股票的最佳时机 买的那天一定是卖的那天之前的最小值。 每到一天&#xff0c;维护那天之前的最小值即可。 在题目中&#xff0…

LAN和WAN, 调制解调器, 路由器,交换机 区别

LAN LAN&#xff08;Local Area Network&#xff09;是指在相对较小的地理范围内&#xff08;如办公室、学校、实验室、家庭等&#xff09;连接在一起的计算机和网络设备的集合。LAN通常由路由器、交换机、网线、无线路由器等设备组成&#xff0c;用于连接多台计算机、打印机、…

实验四 Spark Streaming编程初级实践

一、Flume简介 数据流 &#xff1a;数据流通常被视为一个随时间延续而无限增长的动态数据集合&#xff0c;是一组顺序、大量、快速、连续到达的数据序列。通过对流数据处理&#xff0c;可以进行卫星云图监测、股市走向分析、网络攻击判断、传感器实时信号分析。 二、Flume安装…

Mysql故障和优化

一、MySQL故障 二、MySQL优化 1.硬件优化&#xff1a; 2.数据库设计与规划 1.提前估计数据量&#xff0c;使用什么存储引擎 2.数据库服务器专机专用&#xff0c;避免额外的服务可能导致的性能下降和不稳定性 3.增加多台服务器&#xff0c;以达到稳定、高效的效果。主从同步、…

C++ 2024-4-1 作业

#include <iostream> using namespace std;class A { public:int a;A(int a):a(a){cout<<"A的有参构造"<<endl;} }; class B:virtual public A { public:int b;B(int a,int b):A(a),b(b){cout<<"B的有参构造"<<endl;} }; cl…

vscode通过ssh连接服务器(吐血总结)

一、通过ssh连接服务器 1、打开vscode&#xff0c;进入拓展&#xff08;CtrlShiftX&#xff09;&#xff0c;下载拓展Remote - SSH。 2、点击远程资源管理器选项卡&#xff0c;选择远程&#xff08;隧道/SSH&#xff09;类别。 3、点击SSH配置。 4、在中间上部分弹出的配置文件…

Mac反编译APK

文章目录 第一种方式: brew installapktool 使用说明dex2jar 使用说明 第二种方式: 下载安装包apktool 使用说明 (根据官方介绍没有操作成功,后续成功再更新这里)dex2jar 使用说明 安装 JD-GUI 查看jar包中的class文件JD-GUI 使用说明 第一种方式: brew install 安装过程可能很…

Excel 隔几行批量插入空白行

例如如下表格&#xff0c;每隔6行插入一行数据&#xff1a; 1&#xff09;第7个单元格输入1 2&#xff09;选中6个单元格&#xff0c;然后双击填充数据&#xff1a; 3&#xff09;F5 找到常量 Ctrlshift 复制插入的数据&#xff0c;然后选中数据 按F5&#xff0c;定位到空值

第21章-直连路由和静态路由

1. 直连路由 1&#xff09;定义&#xff1a;指路由器接口直接相连的网段的路由&#xff1b; 2&#xff09;特点&#xff1a; ① 不需要特别的配置&#xff0c;双UP(物理层数据链路层)&#xff1b; ② 在路由器的接口上配置IP地址即可&#xff1b; ③ 开机自动产生&#xff1b; …

如何做用户体验优化

本文是从用户体验优化角度谈用户体验&#xff0c;其实用户体验不是设计必须的步骤&#xff0c;而是分散在产品设计中的产品设计思想。 一、用户体验分类 用户体验是指用户在“使用”某个产品或服务过程中的全部感受&#xff0c;包括情感、信仰、喜好、认知印象、生理和心理反应…

789. 数的范围 (二分学习)

1.确定一个区间&#xff0c;使得目标值一定在区间中 2.找一个性质满足&#xff1a; &#xff08;1&#xff09;性质具有二段性 &#xff08;2&#xff09;答案是二段性的分界点 3.整数二分&#xff08;处理红色右端点和绿色左端点&#xff09; //代码1&#xff1a;右端点 int…