蓝桥杯物联网竞赛 比赛总结

CUBEMX配置建议:

对于CUBEMX配置来说stm32l071kbu6的引脚不算太多,功能模块相对的也不多,所以我建议直接熟练到能将所有模块烂熟于心,不用看原理图就能熟练配置下来,因为国赛看原理图去配置太花费时间
我建议学习的时候先将原理图看懂,哪个模块干嘛的什么原理搞懂,到后面做题就用简便方式配置

物联网竞赛板CubMx全部功能简洁配置汇总

代码书写建议:

代码书写我目前认为最高效的写法是:

在这里插入图片描述
在这里插入图片描述
我建议main函数只填写一些基础的头文件,以及初始化,通过MyMain函数接口运行我们的代码

在这里插入图片描述
将要运行的代码写在自己定义的.c文件里,通过MyMain接口函数调到main函数中运行,这样的好处是需要修改函数或查找BUG的时候直接把范围锁定在自己的Function.c文件

为了更好的书写代码,确保代码的正确性,可以把题目中要求的基本模块先写出来,运行检查一下确保没有问题,例如比赛题目中有OLED显示功能,可以先把OLED功能写出来后,随便显示一个字符串,显示成功说明OLED配置以及代码没问题,如果后面运行主代码的时候发现改显示的数据没有显示的时候,那就自然而然排除是OLED配置和代码问题,就缩小了查BUG的范围

这就更加突出代码模块化的优势,将一个复杂的过程分开成两个或多个小的模块去完成,可以更好的去测试各个模块的完成情况

那么多个模块是怎么连接成小模块的呢?
这就需要全局变量来连接,全局变量的好处是,变量是公共的,模块A处理后模块B也可以处理

在这里插入图片描述
在这里插入图片描述
例如脉冲显示的时候我先用模块A采集数据,再用模块B处理数据并显示,期间还能单独对两个模块进行调试

在这里插入图片描述
定义好全局变量确保A和B函数都能访问

当然不是所有的参数都应该定义成全局变量,全局变量内部数据如果有时不清理的话,会导致数据的污染,例如第一次接收111到全局变量DATA内第二次接收99那么显然数据会被污染成991这个显然是期望之外的

解决方法,如果这个变量只有一个函数模块使用的话,那就设置成私有变量例如:

void OLED_Write(unsigned char type, unsigned char data){
	unsigned char WriteData[2];
	WriteData[0] = type;
	WriteData[1] = data;
	HAL_I2C_Master_Transmit(&hi2c3, 0x78, WriteData, 2, 0xff);
}

如果确实需要多个模块配合处理的话也可以定义一个清理函数,处理完后不需要就处理掉

void Function_ArrayClean(unsigned char* array, uint16_t len){
  for(unsigned char i = 0; i < len; i ++) array[i] = '\0';
}

调试是必不可少的,为了更高效的调试,我建议要么用debug调试,这个我用的不多,后端调试用的多,嵌入式还是喜欢用OLED显示参数,因为直观那么操作就是OLED_ShowString配合sprintf显示对应参数数值,这个我感觉及其不方便,特别是代码量很多的时候需要多次使用sprintf与OLED_ShowString

我建议结合sprintf和showstring函数直接重构一个myprintf函数

#include <stdarg.h>
void myprintf(unsigned char address, const char* format, ...) {
    char ARRAY[40];
	
	  // 使用va_list和va_start来处理可变参数
    va_list args;
    va_start(args, format);

    // 使用vsprintf将可变参数列表格式化的字符串存储到ARRAY中
    vsprintf(ARRAY, format, args);
    
    // 清理可变参数列表
    va_end(args);

    // 假设OLED_ShowString函数可以在OLED屏幕上显示字符串
    OLED_ShowString(address, (unsigned char*)ARRAY);
}

这个函数真是很简单就是处理后面的...不定参数,然后交给vsprintf字符串化,总体效果和printf几乎一模一样,无论调试还是显示都是非常的好用强烈建议学习这个重构方法

蓝桥杯物联网竞赛_STM32L071_20_用printf将数据显示在OLED上


当然以上都是我学习蓝桥杯物联网竞赛这一路以来的经验和技巧吧,在这里仅供参考,毕竟适合自己的才是最好的。那么我的蓝桥杯物联网竞赛就到此结束了,祝福诸君顺利。

—— 2024/6/6

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

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

相关文章

【设计模式深度剖析】【4】【行为型】【策略模式】

文章目录 策略模式定义英文原话直译 角色类图策略接口Strategy&#xff1a;具体策略类上下文类Context测试类 策略模式的应用策略模式的优点策略模式的缺点策略模式的使用场景 策略模式 策略模式&#xff08;Strategy Pattern&#xff09; Strategy策略也称作Policy政策。 想…

Springboot jar运行时,将jar内的文件拷贝到文件系统中

背景 因为执行需要&#xff0c;需要把jar内templates文件夹下的的文件夹及文件加压到宿主机器的某个路径下&#xff0c; 以便执行对应的脚本文件 PS: 通过类加载器等方式&#xff0c;直接getFile遍历文件&#xff0c;在idea中运行是没问题的&#xff0c;但是当打包成jar运行就会…

【JavaEE】留言板与图书管理系统

目录 留言板1. 准备工作2. 约定前后端交互接口lombok3. 服务器代码4. 调整前端页面代码 图书管理系统1. 准备工作2. 约定前后端交互接口3. 服务器代码4. 调整前端页面代码 留言板 需求: 界⾯如下图所⽰ 输⼊留⾔信息, 点击提交. 后端把数据存储起来.⻚⾯展⽰输⼊的表⽩墙的信…

Mysql使用中的性能优化——搭建Mysql的监测服务

大纲 环境安装配置Mysql安装设置root密码新增远程访问账户修改绑定地址重启 新增 MySQL Server Exporter 用户 安装启动mysqld_exporter安装启动新增配置启动 安装启动Prometheus创建用户下载并解压修改配置启动 安装启动grafana安装启动 测试参考资料 抛开场景和数据&#xff…

【YOLOv8改进[CONV]】SPDConv助力YOLOv8目标检测效果 + 含全部代码和详细修改方式 + 手撕结构图

本文将使用SPDConv助力YOLOv8目标检测效果的实践,文中含全部代码、详细修改方式以及手撕结构图。助您轻松理解改进的方法。 改进前和改进后的参数对比: 目录 一 SPDConv 二 SPDConv助力YOLOv8目标检测效果 1 整体修改 ① 添加SPDConv.py文件 ② 修改ultralytics/nn/tas…

笔记95:车辆横向动力学方程转化为误差形式 -- 详细推导过程

1. 非误差型车辆横向动力学方程 注&#xff1a;关于轮胎侧偏刚度的正负 深蓝课程推导得到的车辆横向动力学返程使用的轮胎侧偏刚度是默认为正数&#xff1b;老王课程推导得到的车辆横向动力学方程使用的轮胎侧偏刚度是默认为负数&#xff1b; 1.1 深蓝课程推导得到的方程&…

【Qt知识】部分QWidget属性表格

QWidget是Qt库中所有图形用户界面组件的基类&#xff0c;它提供了大量属性以供自定义和配置控件的行为和外观。下面列出了一些主要的QWidget属性及其作用。 属性 作用 accessibleName 控件的辅助技术名称&#xff0c;用于无障碍访问。 accessibleDescription 控件的辅助技…

18 - 各赛事的用户注册率(高频 SQL 50 题基础版)

18 - 各赛事的用户注册率 -- 注册率注册用户数/所有用户数 selectr.contest_id,round(100*count(*)/(select count(*) from Users),2) percentage from Register r group by r.contest_id order bypercentage desc,r.contest_id ASC;

网鼎杯 2020 玄武组 SSRFMe

复习一下常见的redis主从复制 主要是redis伪服务器的选择和一些小坑点 <?php function check_inner_ip($url) { $match_resultpreg_match(/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/,$url); if (!$match_result) { die(url fomat error); } try { …

3D Web轻量化平台HOOPS Web Platform助力Rapid DCS迅速推出成本与碳排放估算产品

英国公司Rapid DCS利用HOOPS Web平台在短短六个月内成功开发出创新的云解决方案Sterling&#xff0c;旨在帮助建筑行业客户高效地估算成本和计算碳排放。 Rapid DCS&#xff0c;一家总部位于英国的公司&#xff0c;专注于为建筑环境领域的客户提供全面的数字化解决方案和服务。…

NextJs 实现自定义点火操作

NextJs 实现自定义点火操作 前言实现自定义点火 前言 我希望在Nextjs 启动的时候&#xff0c;能够自定义实现一些项目的初始化逻辑&#xff0c;也可以说是一些点火操作&#xff0c;比如资源的加载&#xff0c;数据的初始化等操作。 实现自定义点火 我们可以在根目录下创建一…

22 - 游戏玩法分析 IV(高频 SQL 50 题基础版)

22 - 游戏玩法分析 IV 考点&#xff1a; 聚合函数 # 日期相加 date_add(min(event_date),INTERVAL 1 DAY) select round(count(distinct player_id)/(select count(distinct player_id) from Activity),2) fraction fromActivity where-- 如果日期加一天的数据能在表中…

界面组件DevExpress Reports v23.2增强用户体验 - 轻松导航Web设计器

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 DevExpress Reports v23.2(我们最近的主要更新…

C++ 11【右值引用】

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C修炼之路⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 1.C 11 简介 目录 1.C 11 简介 2. 统一的列表…

小程序自定义marker弹出框教程

需求背景 微信小程序开发&#xff0c;需要使用腾讯地图显示自定义marker&#xff0c;并且点击marker后弹出自定义的customCallout&#xff0c;并且customCallout的内容为用户点击marker的时候再从后台接口获取数据。 百度了一圈后发现居然没有一篇文章可以一次性完成&#xf…

使用opencv在图像上画带刻度线的十字线,以图像中心点为0点

使用OpenCV在图像上绘制带刻度线的十字线&#xff0c;可以通过以下步骤实现。我们将首先找到图像的中心点&#xff0c;然后绘制水平和垂直线&#xff0c;并在这些线的适当位置绘制刻度线。以下是详细的C代码示例&#xff1a; #include<opencv2\opencv.hpp> //画十字标注…

LeetCode题练习与总结:杨辉三角Ⅱ--119

一、题目描述 给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: rowIndex 3 输出: [1,3,3,1]示例 2: 输入: rowIndex 0 输出: [1]示例 3: 输入: rowIndex 1 输…

Spring Cloud工程添加子模块打包后文件为war包而非jar包

Spring Cloud工程添加子模块打包后文件为war包而非jar包 Spring Cloud子模块打出的包通常是JAR包而非WAR包&#xff0c;这是因为Spring Cloud主要基于Spring Boot构建&#xff0c;而Spring Boot默认打包为可执行JAR包。然而&#xff0c;如果遇到了Spring Cloud子模块打成了WAR…

前端 JS 经典:图片裁剪上传原理

前言&#xff1a;图片裁剪一般都是用户选择头像时用到&#xff0c;现在很多插件都可以满足这个功能&#xff0c;但是我们不仅要会用插件&#xff0c;还要自己懂的裁剪原理。 1. 流程 流程分为&#xff1a;1. 预览本地图片 2. 选择裁剪区域 3. 上传裁剪图像 2. 如何预览图片 …

08-指针与数组的结合——数组指针与指针数组的区别

指针与数组的结合 示例 1:指针访问数组元素 通过指针访问数组元素的例子&#xff1a; #include <stdio.h>int main() {int arr[5] {1,2,3,4,5};//int *p1 &arr;int *p1 (int *)&arr; // 需要强制类型转换int *p2 arr;printf("*p1:%d\n", *(p1 …