[嵌入式软件][启蒙篇][仿真平台] STM32F103实现串口输出输入、ADC采集

news2024/11/22 16:45:11

上一篇:[嵌入式软件][启蒙篇][仿真平台] STM32F103实现LED、按键
本文章使用的电路,见上一篇。

文章目录

  • 一、串口输出
    • (1) 简介
    • (2) 示例代码
    • (3) 仿真效果
  • 二、串口输入
    • (1) 简介
    • (2) 示例代码
    • (3) 仿真效果
  • 三、ADC采集
    • (1) 简介
    • (2) 采集电压
    • (3) 示例代码(电压)
    • (4) 仿真效果 (电压)
    • (5) 采集光敏
    • (6) 示例代码(光敏)
    • (6) 仿真效果 (光敏)
    • (7) 内部温度
    • (8) 示例代码(内部温度)
    • (9) 仿真效果 (内部温度)

一、串口输出

(1) 简介

  1. 学C语言时,使用的printf()函数,就是通过串口打印出来的。
  2. 跟外部器件通信,比如GPS模块、蓝牙模块、wifi模块;
  3. 两个开发板之间通信,制定私有协议。
  4. PC电脑通信,使用上位机显示数据或控制下位机。

(2) 示例代码

#include <stdint.h>
#include <stdio.h>
#include "sys.h"
#include "stm32f10x_conf.h"

#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"

int main() {
    // LED初始化
    LED_Init();
    // 按键初始化
    KEY_Init();
    //串口初始化
    uart_init(115200);
    // 由于LED接了VCC, 引脚高电平,无法导通电路,所以低电平点亮,即VCC(火线)-->GND(地线/零线)
    while(1) {
        if (Key_Scan(GPIOA, GPIO_Pin_1)) { // 检测按键整个过程。按下->松开
            LED = !LED;  // 每次按下,切换开关。低电平点亮 高电平熄灭
            printf("key pressed. led state:%u\n", LED);
        }
    }
}

(3) 仿真效果

  1. 操作:打开串口–按下按键

在这里插入图片描述



二、串口输入

(1) 简介

  1. 跟外部器件通信,比如GPS模块、蓝牙模块、wifi模块;
  2. 两个开发板之间通信,制定私有协议。
  3. PC电脑通信,使用上位机输入参数或控制下位机。

(2) 示例代码

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "stm32f10x_conf.h"

#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"

int main() {
    // LED初始化
    LED_Init();
    // 按键初始化
    KEY_Init();
    //串口初始化
    uart_init(115200);
    // 由于LED接了VCC, 引脚高电平,无法导通电路,所以低电平点亮,即VCC(火线)-->GND(地线/零线)
    while(1) {
        if (Key_Scan(GPIOA, GPIO_Pin_1)) { // 检测按键整个过程。按下->松开
            LED = !LED;  // 每次按下,切换开关。低电平点亮 高电平熄灭
            printf("key pressed. led state:%u\n", LED);
        }
        if ((USART_RX_STA & 0x8000) == 0x8000) { // 接收完成
            printf("rx:%s\r\n", USART_RX_BUF); // 打印刚刚接收的数据
            USART_RX_STA = 0; // 继续接收数据
            memset(USART_RX_BUF, 0, USART_REC_LEN); // 将刚刚接收到的数据清空
        }
    }
}

重点:还有一个地方需要小修改(平台没有实现,我们这里替换下就行),有兴趣可以研究下功能的实现

在这里插入图片描述

void USART1_IRQHandler(void) { //串口1中断服务程序
	uint16_t Res;
	// 接收中断(接收到的数据必须是0x0d 0x0a结尾, 就是换行符\r\n)
	if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
		Res = USART_ReceiveData(USART1); //读取接收到的数据
		if ((USART_RX_STA & 0x8000) == 0) { //接收未完成
			if (USART_RX_STA & 0x4000) { //接收到了0x0d
				if (Res != 0x0a)
					USART_RX_STA = 0; //接收错误,重新开始
				else
					USART_RX_STA |= 0x8000; //接收完成了
			} else { //还没收到0X0D
				if (Res == 0x0d)
					USART_RX_STA |= 0x4000;
				else {
					USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;
					USART_RX_STA++;
					if (USART_RX_STA > (USART_REC_LEN - 1))
						USART_RX_STA = 0; //接收数据错误,重新开始接收
				}
			}
		}
	}
}

(3) 仿真效果

  1. 操作:打开串口–发送消息:123456\r\n
    在这里插入图片描述


三、ADC采集

这个实验需要添加电路,如下图:

  1. 将按钮移除
    在这里插入图片描述
  2. 添加电压调节器
    在这里插入图片描述

(1) 简介

  1. ADC是一个专门采集模拟量转为为数字信号的外设。
  2. ADC一般采集电压、电流、光敏(光亮度)、温度、湿度、压力、声音等等。

(2) 采集电压

本实验使用STM32采样ADC模拟输入器的数据,开启仿真后,串口助手将ADC数值与转换出的电压值一并打印。

(3) 示例代码(电压)

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "stm32f10x_conf.h"

#include "delay.h"
#include "led.h"
#include "adc.h"
#include "usart.h"

uint32_t adc_value = 0;
float voltage_value = 0;        //用于保存转换计算后的电压值

int main() {
    // LED初始化
    LED_Init();
    // ADC1通道1初始化
    Adc_Init();
    //串口初始化
    uart_init(115200);
    while(1) {
        // 通过ADC_GetConversionValue函数查询ADC的DR寄存器获取ADC转换结果值
        adc_value = Get_Adc(1);
        // 计算出模拟输入的电压值
        voltage_value=(float)adc_value*(3.3/4095);           
        
        // 打印ADC转换结果值
        printf("AD value is %d\n", adc_value);
        //打印计算出的电压值
        printf("voltage value is %f V\n", voltage_value);
        LED = !LED;
        delay_ms(50);
    }
}

(4) 仿真效果 (电压)

  1. 操作: 打开串口–调整电压
    在这里插入图片描述



(5) 采集光敏

  1. 光敏电阻的特性:光线越亮,阻值越小。
  2. 一般用于走廊,白天不亮,晚上亮,做到省电的效果。
  3. 按下图搭建电路
    在这里插入图片描述

(6) 示例代码(光敏)

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "stm32f10x_conf.h"

#include "delay.h"
#include "led.h"
#include "adc.h"
#include "usart.h"

//设定基于ADC信号的模拟光强阈值
#define lux 2200
uint32_t adc_value = 0;

int main() {
    // LED初始化
    LED_Init();
    // ADC1通道1初始化
    Adc_Init();
    //串口初始化
    uart_init(115200);
    while(1) {
        // 通过ADC_GetConversionValue函数查询ADC的DR寄存器获取ADC转换结果值
        adc_value = Get_Adc(1);
        // 打印ADC转换结果值
        printf("AD value is %d\n", adc_value);
        if (adc_value > lux) {
            LED = 0; // 点亮
        } else {
            LED = 1; // 熄灭
        }
        delay_ms(50);
    }
}

(6) 仿真效果 (光敏)

  1. 操作:打开串口–调节光敏电阻–从0-100%调整–当阻值>2000,点亮;阻值<2000,熄灭。
    在这里插入图片描述

(7) 内部温度

  1. 芯片内部温度,目的:让电阻计算更佳准确,因为温度会影响阻值。 (一般用不上,不精确)
  2. 测量CPU以及周围的温度,测量范围为-40~125度,误差为±1.5度
  3. 内部温度传感器更适合于检测温度的变化,需要测量精确温度的情况下,应使用外置传感器。
  4. 温度传感器模拟输入推荐采样时间是 17.1us。
  5. 温度的计算公式如下:
    T(℃)= {( V25-Vsense)/ Avg_Slope} + 25
    上式中:V25=Vsense 在 25 度时的数值(典型值为: 1.43)。
    Avg_Slope=温度与 Vsense 曲线的平均斜率(单位: mv/℃或 uv/℃)(典型值: 4.3mv/℃)。

(8) 示例代码(内部温度)

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "stm32f10x_conf.h"

#include "delay.h"
#include "led.h"
#include "adc.h"
#include "usart.h"

float temperate = 0;        //用于保存转换计算后的温度值
uint32_t adc_value = 0;

int main() {
    // LED初始化
    LED_Init();
    // ADC1通道1初始化
    Adc_Init();
    //串口初始化
    uart_init(115200);
    while(1) {
        // 通过ADC_GetConversionValue函数查询ADC的DR寄存器获取ADC转换结果值
        adc_value = Get_Adc(1);
        // 打印ADC转换结果值
        printf("AD value is %d\n", adc_value);

        temperate = (float)adc_value * (3.3 / 4095); // 先转成电压值
        temperate = (1.43 - temperate) / 0.0043 + 25;  // 再转换为温度值
        //打印计算出的温度值
        printf("MCU temperature is %f C \n", temperate);
        
        LED = !LED;
        delay_ms(50);
    }
}

(9) 仿真效果 (内部温度)

在这里插入图片描述



下一篇:[嵌入式软件][启蒙篇][仿真平台]STM32F103实现定时器

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

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

相关文章

c++小技巧14:多线程

1.前言 最近&#xff0c;被期末考试AK的zzb在回顾以前的代码时&#xff0c;无意看到一个问题: 请问: 大佬能解释一下怎么同时运行两个cfor循环吗&#xff1f; 就比如说游戏里你一边出招电脑也能出招这种的 当时&#xff0c;zzb是用的kd来解决(详见小技巧2) 而现在&#xff0c…

GO 的那些 IDE

文章目录 支持哪些功能快捷键代码高亮代码格式化代码提示导航跳转代码调试构建编译其他功能 GO有哪些IDEGolandVS CodeVim GOSublime TextAtomLiteIDEEclipse 总结 “程序员为什么要使用 IDE”&#xff0c;在一些社区论坛&#xff0c;经常可以看到这样的提问。关于是否应该使用…

AI创作之旅:探索提示工程的奇妙世界

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在当今信息爆炸的时代&#xff0c;人工智能的发…

ELK分离式日志(2)

目录 一.FilebeatELK 部署 开台服务器&#xff08;192.168.233.50&#xff09;下载fliebeat&#xff1a; 安装nginx后查看下日志文件&#xff1a; 设置 filebeat 的主配置文件: 关闭logstash&#xff0c;检测文件&#xff1a; 在50节点上启动filebeat&#xff1a; 访问页…

前端基础(三十八):iframe通信、浏览器跨窗口通信

iframe通信 - MessageChannel <!-- index.html --> <h3>MessageChannel</h3> <input id"input" type"text" oninput"handleInput(this.value)" /> <hr /> <iframe src"./demo.html"></iframe&…

Java 数据结构篇-实现红黑树的核心方法

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 红黑树的说明 2.0 红黑树的特性 3.0 红黑树的成员变量及其构造方法 4.0 实现红黑树的核心方法 4.1 红黑树内部类的核心方法 &#xff08;1&#xff09;判断当前…

k8s中服务器容器tcp连接数量优化

netty的http1服务器在运行一段时间后会无法提供服务&#xff0c;返回客户端socket hang up 使用apipost测试抓包显示三次握手后被reset 客户端使用了大量短连接&#xff0c;如果能改成长连接就会消耗更少的连接&#xff0c;但是客户端逻辑无法掌控&#xff0c;只能修改服务器。…

网络安全概述---笔记总结

网络安全概述 网络安全---Cyberspace security 2003年美国提出网络空间的概念 --- 一个由信息基础设施组成的互相依赖的网络。我国官方文件定义&#xff1a;网络空间为继海&#xff0c;陆&#xff0c;空&#xff0c;天以外的第五大人类活动领域 发展阶段&#xff1a; 通信保…

学习STM32,该用哪款开发工具?

有很多初学者在问&#xff1a;学习STM32&#xff0c;该用哪款开发工具&#xff1f; 我首先说一下我的观点&#xff1a; 1.没有最好&#xff0c;只有适不适合&#xff0c;适合自己的才是最好的。 2.开发工具很多&#xff0c;各有各的特点&#xff0c;有优点肯定也有缺点。 本文…

MySQL InnoDB 底层数据存储

InnoDB 页记录Page Directory记录迁移 页 是内存与磁盘交互的基本单位&#xff0c;16kb。 比如&#xff0c;查询的时候&#xff0c;并不是只从磁盘读取某条记录&#xff0c;而是记录所在的页 记录 记录的物理插入是随机的&#xff0c;就是在磁盘上的位置是无序的。但是在页中…

vscode连不上虚拟机,一直密码错误

最近在做毕设&#xff0c;但是vscode使用连接不上虚拟机&#xff0c;我以为是网络配置的问题&#xff0c;一顿查阅没找到原因。 后来查了一下ssh的日志&#xff0c;发现ssh有消息&#xff0c;但是也提示密码错误。 没找到密码配置格式什么的&#xff0c;经查看sshd配置文件发现…

easyexcel导入合并单元格解析(纵向合并,横向合并都支持)

1、按照开发逻辑&#xff0c;首先定义导入接收实体 package com.wang.test.excel;import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data;/***/ Data public class ExcelData1 {ExcelProperty(index 0)private String name;ExcelProperty(index 1)private S…

[C++] external “C“的作用和使用场景(案例)

C中extern "C"的作用是什么&#xff1f; 在 C 中&#xff0c;extern "C" 的作用是告诉编译器按照 C 语言的规范来处理函数名和变量名。这是因为 C 编译器会对函数名和变量名进行名称修饰(name mangling)&#xff0c;以区分不同的函数和变量。而在 C 语言中…

企业需要的3种供应商管理解决方案

传统的 "管理和监控 "供应商管理解决方案是对时间和金钱的巨大浪费。准入、资格认证和细分等孤立的供应商管理流程无法与其他采购流程整合在一起。 此外&#xff0c;从多个来源获取和管理供应商数据的过程只会增加固有的复杂性。而且&#xff0c;人工操作往往会延误…

【Java IO】设计模式 (装饰者模式)

Java I/O 使用了装饰者模式来实现。 装饰者模式 请参考装饰者模式详解 装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component)&#xff0c;具体组件的方法实现不需要依赖于其它对象&#xff0c;而装饰者组合了一个组件&#xff0c;这样它可以装饰其它装饰者…

Linux中文件IO(open、read、write、close函数使用)

介绍 什么是文件IO&#xff1f; 是操作系统提供的API接口函数。 POSIX接口 &#xff08;了解&#xff09; 注意&#xff1a;文件IO不提供缓冲机制 文件IO的API open close read read 文件描述符概念&#xff1a; 英文&#xff1a;缩写fd&#xff08;file descriptor&#xff…

前端和后端之间的CORS 跨域和解决办法

什么是CORS&#xff08;Cross-Origin Resource Sharing&#xff0c;跨源资源共享&#xff09; 跨源资源共享&#xff08;CORS&#xff0c;或通俗地译为跨域资源共享&#xff09;是一种基于 HTTP 头的机制&#xff0c;该机制通过允许服务器标示除了它自己以外的其他源&#xff0…

go 语言中 json.Unmarshal([]byte(jsonbuff), j) 字节切片得使用场景

struct_tag的使用 在上面的例子看到&#xff0c;我们根据结构体生成的json的key都是大写的&#xff0c;因为结构体名字在go语言中不大写的话&#xff0c;又没有访问权限&#xff0c;这种问题会影响到我们对json的key的名字&#xff0c;所以go官方给出了struct_tag的方法去修改…

【C++杂货铺】三分钟彻底搞懂如何使用C++中max函数

&#x1f308;前言 欢迎收看本期【C杂货铺】&#xff0c;这期内容&#xff0c;我们将围绕C中max函数部分进行讲解&#xff0c;包含了如何查询库函数&#xff0c;max函数的使用方法灯。如果你想学习C&#xff0c;或者刚学完C语言衔接C&#xff0c;那么这篇文章将会非常有效的帮助…

Redis学习——入门篇①

Redis学习——入门篇① 1、2&#xff1a;Redis入门概述3&#xff1a;Redis安装配置10 安装Redis-cli命令 4&#xff1a;Redis——十大数据类型11 redis数据类型12 命令查阅13 key常用命令介绍14 类型大小写和帮助命令15 String 命令&#xff08;上&#xff09;16 String 命令&a…