CUBEMX配置建议:
对于CUBEMX配置来说stm32l071kbu6的引脚不算太多,功能模块相对的也不多,所以我建议直接熟练到能将所有模块烂熟于心,不用看原理图就能熟练配置下来,因为国赛看原理图去配置太花费时间我建议学习的时候先将原理图看懂,哪个模块干嘛的什么原理搞懂,到后面做题就用简便方式配置
代码书写建议:
代码书写我目前认为最高效的写法是:
我建议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