第十三届蓝桥杯物联网试题(国赛)

news2024/11/25 23:31:30

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

还是那句话不能掉以轻心,全力以赴吧,遇事不要慌,该做的都做了,冷静沉稳的处理,看看配置,看看代码,还是不行就重启,都没问题换个板子

下面对比较复杂的部分的处理过程进行展现:

在这里插入图片描述
这个我是配合定时器和中断按键处理的,大致思路,按下按键在按键中断函数中将相应标志位置1

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){  // 按键
	//OLED_ShowString(0, "victory");
	STARTTEST = 1;
	MEMFLAG = 1;
}

主函函数识别标志位变为1则做相应ADC获取,以及OLED显示

void Function_StartAdc(){  
  if(STARTTEST == 1){
		//Function_OledInit(10);
		HAL_TIM_Base_Start_IT(&htim7);
	    Function_GetAdc();
		Function_OledShow();
		HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_SET);
	}else {
		HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_RESET);
	    OLED_Clear();
		//HAL_GPIO_WritePin(OLED_Power_GPIO_Port, OLED_Power_Pin, GPIO_PIN_SET);
	}
}

检测数值是否稳定,在第一次获取ADC数值的时候备份一下,在定时器里去分析是否稳定,不稳定定时器计数值归零否者继续计数

void Function_GetAdc(){
	uint16_t AdcData[2];
	for(unsigned char i = 0; i < 2; i ++){
	  HAL_ADC_Start(&hadc);
		HAL_ADC_PollForConversion(&hadc, 0xff);
		AdcData[i] = HAL_ADC_GetValue(&hadc);
		HAL_Delay(5);
	}
	HAL_ADC_Stop(&hadc);
	RP1Value = AdcData[1] * 3.30f / 4095;
	RP2Value = AdcData[0] * 3.30f / 4095;
	if(MEMFLAG == 1){  // 做备份
		MEMFLAG = 0;
		MEMRP1VALUE = RP1Value;
		MEMRP2VALUE = RP2Value;
	}
	if(RP1Value <= 3.3) WT = RP1Value * 80 / 3.3;
	else WT = 80;
	if(RP2Value <= 1) BF = 5;
	else if(RP2Value > 1 && RP2Value < 2) BF = RP2Value * 40 - 35;
	else BF = 45;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){  // 10ms
	//OLED_ShowString(0, "victory");
	if(STARTTEST == 1){ // 测量体重
	  if(COUNTNUMBER >= 300){
			//HAL_TIM_Base_Stop_IT(&htim7);
			STARTTEST = 0;
			TESTVICTORY  = 1;
			COUNTNUMBER = 0;
			sprintf((char* )SENDMSG, "#%.1f#%.1f", WT, BF);
			LORA_Tx(SENDMSG, 20);
		}			
	    DERTARP1 = RP1Value - MEMRP1VALUE;
		DERTARP2 = RP2Value  - MEMRP2VALUE;
	  if(DERTARP1 > -0.1 && DERTARP1 < 0.1 && DERTARP2 > -0.1 && DERTARP2 < 0.1) COUNTNUMBER ++;
	  else {
			MEMRP1VALUE = RP1Value;
			MEMRP2VALUE = RP2Value;
		    COUNTNUMBER = 0;
		}
  }
	
	if(TESTVICTORY == 1){  // LD5闪烁
		if(COUNTNUMBER <= 300) {
		     COUNTNUMBER ++;
			 if(COUNTNUMBER % 10 == 0) HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
		}
		else{
			TESTVICTORY = 0;
			HAL_TIM_Base_Stop_IT(&htim7);
			HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET);
			COUNTNUMBER = 0;
		}
	}
}

LD5是每0.1s反转一次,也就是整10位反转,所以直接%10即可

够3s后OLED直接清屏就行,断开电源开启还要初始化很麻烦

在这里插入图片描述
储存用结构体

typedef struct{
  unsigned char MEMWT[10];
	unsigned char MEMBF[10];
}MEMO;

符合要求得数据直接memcpy过来就行

在这里插入图片描述

对于LORA传输的数据要做一些处理,再判断

void Function_LorRxHandle(){
  if(RECEIVEMSG[0] == '#'){
		Function_ArrayClean(RXWT, sizeof(WT));
		Function_ArrayClean(RXBF, sizeof(BF));
		unsigned char i = 1;
		unsigned char j = 0;
		while(RECEIVEMSG[i] != '#') RXWT[j ++] = RECEIVEMSG[i ++];
		i ++;
		j = 0;
		while(RECEIVEMSG[i] != '\0') RXBF[j ++] = RECEIVEMSG[i ++];
		//OLED_ShowString(0, WT);
		//OLED_ShowString(2, BF);
		TPRXBF = strtof((char* )RXBF, NULL);
		TPMAXBF = strtof((char* )MAXBF, NULL);
		TPMINBF = strtof((char* )MINBF, NULL);
		if(!(TPRXBF >= TPMINBF && TPRXBF <= TPMAXBF)){
			HAL_TIM_Base_Start_IT(&htim7);
		}else{
			HAL_TIM_Base_Stop_IT(&htim7);
			HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET);
			Function_ArrayClean(WT, sizeof(WT));
		  Function_ArrayClean(BF, sizeof(BF));
			memcpy(BF, RXBF, 10);
			memcpy(WT, RXWT, 10);
			memcpy(MEMORX[INDEX].MEMBF, BF, 10);
			memcpy(MEMORX[INDEX].MEMWT, WT, 10);
			INDEX = (INDEX + 1) % 20;
		}
	}
	if(RECEIVEMSG[0] != '\0') Function_ArrayClean(RECEIVEMSG, sizeof(RECEIVEMSG));
}

        unsigned char i = 1;
		unsigned char j = 0;
		while(RECEIVEMSG[i] != '#') RXWT[j ++] = RECEIVEMSG[i ++];
		i ++;  // 跳过'#'
		j = 0;
		while(RECEIVEMSG[i] != '\0') RXBF[j ++] = RECEIVEMSG[i ++];

这一步部分的作用是将例如#value1#value2分别取出来,因为value1和2的位数不知道所以用memcpy是不行的,这就要用算法来操作了

操作之前记得将数组里的值清除一下,防止这次的数据被前面接收的数据污染:

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

将处理函数放外面是因为,比赛可能有其他人发送的数据可能会被误收,更要清除

在这里插入图片描述

对串口数据的处理更是将神器strtof函数运用到极致,真是不得不佩服大佬写的函数

void Function_UartRxMsgHandle(){
  if(UARTRXMSG[0] != '\0'){
	    HAL_Delay(10);
		//OLED_ShowString(0, UARTRXMSG);
		TEMP = strtof((char* )UARTRXMSG, &p);
		if(*p == '\0'){  // 查询指令
			if(TEMP >= 1 && TEMP <= 20){
				Function_ArrayClean(SENDMSG, sizeof(SENDMSG));
				sprintf((char* )SENDMSG, "WT:%sKG,BF:%s%%", MEMORX[(int)TEMP - 1].MEMWT, MEMORX[(int)TEMP - 1].MEMBF);
				HAL_UART_Transmit(&huart2, SENDMSG, sizeof(SENDMSG), 0xff);
			}else{
				HAL_UART_Transmit(&huart2, (unsigned char* )SDERREOR, strlen(SDERREOR), 0xff);
			}
		}else if(*p == ','){  // 改变指令
			Function_ArrayClean(TEMPUARTRX, sizeof(TEMPUARTRX));
			unsigned char i = 0;
			unsigned char j = 0;
			while(UARTRXMSG[i ++] != ',');
			while(UARTRXMSG[i] != '\0') TEMPUARTRX[j ++] = UARTRXMSG[i ++];
			
			TEMP1 = strtof((char* )TEMPUARTRX, &q);
			if(*q == '\0' && TEMP <= TEMP1 && TEMP >= 0 && TEMP <= 45 && TEMP1 >= 0 && TEMP1 <= 45){
			  sprintf((char* )MINBF, "%d", (int)TEMP);
				sprintf((char* )MAXBF, "%d", (int)TEMP1);
			}else HAL_UART_Transmit(&huart2, (unsigned char* )SDERREOR, strlen(SDERREOR), 0xff);
		}else HAL_UART_Transmit(&huart2, (unsigned char* )SDERREOR, strlen(SDERREOR), 0xff);
		Function_ArrayClean(UARTRXMSG, sizeof(UARTRXMSG));
		 
	}
}

延时10ms是因为是DMA接收,所以让CPU别急着处理让DMA将数据接受完再处理

之前讲过strtof的性质,将字符串转换成浮点型直到不能转换为止,所以利用这个性质:
将数据先全部转换一次,如果全部都能转换即指针指向空字符,那么就是查询语句,如果指针指向’,‘那就说明是设置值命令,如果指向的是其他字符,则可返还错误,如果指向‘,’此时可利用上面分割#字符的方式将’,'字符分割到另一个数组做分析,再次分析另一个设置数据合不合法

            while(UARTRXMSG[i ++] != ',');
			while(UARTRXMSG[i] != '\0') TEMPUARTRX[j ++] = UARTRXMSG[i ++];

先跳过第一个‘,’再对后一个字符串做处理

这个处理过程让我找到了后端开发的感觉,先写主体判断框架,再实现框架内部内容

这一部分得慢慢来慢慢调试

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

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

相关文章

【排序】冒泡排序

在我们的生活中&#xff0c;到处都离不开排序的作用&#xff0c;考试分数要排序&#xff0c;商场购物要排序&#xff0c;可以说排序对我们来说处处存在&#xff0c;那么从本章开始&#xff0c;我将要依次分享一些排序方法&#xff0c;从易到难&#xff0c;包括冒泡&#xff0c;…

Linux 编译安装python

以deepin操作系统安装Python3.8.10为例。 下载 python3.8.10 官网下载 Linux要下载源码&#xff0c;进行编译。 下图tarball即tar包&#xff0c;是压缩包的意思。python官网给出两种压缩格式的tarball&#xff0c;下载哪个都可以。 方式一&#xff1a;直接点击链接下载 方式…

中间件复习之-消息队列

消息队列在分布式架构的作用 消息队列&#xff1a;在消息的传输过程中保存消息的容器&#xff0c;生产者和消费者不直接通讯&#xff0c;依靠队列保证消息的可靠性&#xff0c;避免了系统间的相互影响。 主要作用&#xff1a; 业务解耦异步调用流量削峰 业务解耦 将模块间的…

线上 | OpenSergo - [规范]

INDEX 1 参考资料2 OpenSergo 与 Sentinel 关系3 规范体系3.1 服务元数据ReportMetadataRequest 信息![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ffba569841ae4668b4cff74e4d41d21f.png)##### ReportMetadataReply 信息![在这里插入图片描述](https://img-blog…

链表相交00

题目链接 链表相交 题目描述 注意点 题目数据保证整个链式结构中不存在环函数返回结果后&#xff0c;链表必须保持其原始结构设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案 解答思路 双指针分别指向headA和headB&#xff0c;当遍历完某个链表后&#xff0c;将指针指…

【面结构光三维重建】0.基于openCV实现相机的标定

1.标定结果 2.相机标定原理 相机标定是计算机视觉和机器视觉领域中的重要技术,用于确定相机成像的几何关系和畸变特性,以提高成像的精度和稳定性。该技术广泛应用于三维重建、机器人视觉、自动驾驶等领域。 世界坐标系:由用户定义的三维世界坐标系,描述物体和相机在真实世…

生产现场的作业标准化,这么做就对了!

制造型企业的生产过程是以计划的成本、工时生产出达到客户要求的产品。如果在制造过程中&#xff0c;产品工艺、作业方法或作业条件有所变化的话&#xff0c;一定无法生产出符合上述要求的产品。 因此&#xff0c;公司领导必须对作业工艺流程、作业方法、作业条件进行标准化管…

无缝接入GPT-4o:智创聚合API平台的创新与实践

在2024年5月13日&#xff0c;美国开放人工智能研究中心&#xff08;OpenAI&#xff09;发布了最新版本的ChatGPT——GPT-4o。这一更新标志着人工智能领域的又一重大进步&#xff0c;引起了全球科技界的广泛关注。GPT-4o的“o”代表“omni”&#xff08;全能&#xff09;&#x…

ARM-V9 RME(Realm Management Extension)系统架构之系统能力的设备隔离和保护

安全之安全(security)博客目录导读 目录 三、设备隔离和保护 1、外设隔离 2、非pe请求者(设备) 3、可编程完成端过滤器Programmable completer-side filters 4、RME设备分配 4.1 设备权限表 本博客探讨 RME 所需系统能力的设备隔离和保护&#xff0c;以保证 Arm CCA 对于…

辅导男朋友转算法岗的第2天|self Attention与kv cache

文章目录 公式KV CacheMHA、MQA、GQA 面试题为什么除以 d k \sqrt{d_k} dk​ ​Multihead的好处decoder-only模型在训练阶段和推理阶段的input有什么不同&#xff1f;手撕必背-多头注意力 公式 $ \text{Output} \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) \times …

SG7050EEN差分晶体振荡器:为5G路由器提供卓越的时钟源

随着5G技术的快速发展&#xff0c;5G路由器作为连接高速网络的重要设备&#xff0c;正迅速普及。为了确保5G路由器在高宽带和低延迟的网络环境中表现出色&#xff0c;选择一款高性能的晶体振荡器至关重要。爱普生推出的SG7050EEN差分晶体振荡器&#xff0c;以其高精度、低相位噪…

K210视觉识别模块学习笔记2:固件的下载升级_官方数字识别例程导入方法

今日开始学习K210视觉识别模块:固件的下载升级_官方数字识别例程导入方法 主要学习如何升级固件库&#xff0c;在哪下载固件库&#xff0c;以及如何在TF卡正确导入官方例程&#xff1a; 亚博智能的K210视觉识别模块...... 本次最终目的是正确导入官方的数字识别例程&#xff0…

Python 之SQLAlchemy使用详细说明

目录 1、SQLAlchemy 1.1、ORM概述 1.2、SQLAlchemy概述 1.3、SQLAlchemy的组成部分 1.4、SQLAlchemy的使用 1.4.1、安装 1.4.2、创建数据库连接 1.4.3、执行原生SQL语句 1.4.4、映射已存在的表 1.4.5、创建表 1.4.5.1、创建表的两种方式 1、使用 Table 类直接创建表…

小程序使用Canvas设置文字竖向排列

在需要使用的js页面引入js文件,传入对应参数即可 /** * 文本竖向排列 */ function drawTextVertical(context, text, x, y) {var arrText text.split();var arrWidth arrText.map(function (letter) {return 26; // 字体间距,需要自定义可以自己加参数,根据传入参数进行…

飞凌嵌入式FET3568/3568J-C核心板现已适配OpenHarmony4.1

近日&#xff0c;飞凌嵌入式为FET3568/3568J-C核心板适配了OpenHarmony4.1系统&#xff0c;新系统的加持使核心板在兼容性、稳定性与安全性等方面都得到进一步提升&#xff0c;不仅为FET3568/3568J-C核心板赋予了更强大的功能&#xff0c;也为开发者们提供了更加广阔的创新空间…

WordPress中借助Table of Contents Plus+Widget Options插件,实现仅在文章侧边栏显示文章目录的功能

本文转自博主的个人博客&#xff1a;https://blog.zhumengmeng.work,欢迎大家前往查看。 原文链接&#xff1a;点我访问 序言&#xff1a;今天心血来潮&#xff0c;写了一篇文章&#xff0c;忽然发现自己的文章极少有目录&#xff0c;这对于长文章的阅读来说是十分不利的&#…

vivado 时序约束

时间限制 以下ISE设计套件时序约束可以表示为XDC时序约束 Vivado设计套件。每个约束描述都包含一个UCF示例和 等效的XDC示例。 在未直接连接到边界的网络上创建时钟时&#xff0c;UCF和XDC不同 的设计&#xff08;如端口&#xff09;。在XDC中&#xff0c;当在上定义带有create…

微信小程序发送订阅消息

小程序后台。订阅消息里面&#xff0c;新建一个消息模板 小程序代码&#xff0c;登录后&#xff0c;弹出订阅信息 requestSubscribeMessage: function () {wx.requestSubscribeMessage({tmplIds: [-323232-32323], // 替换为你的模板IDsuccess(res) {// 用户订阅结果console.l…

【康耐视国产案例】Nvidia/算能+智能AI相机:用AI驱动 | 降低电动车成本的未来之路

受环保观念影响、政府激励措施推动与新能源技术的发展&#xff0c;消费者对电动汽车(EV)的需求正在不断增长&#xff0c;电动汽车已经成为了未来出行方式的重要组成部分。然而&#xff0c;电动汽车大规模取代燃油汽车的道路还很漫长。最大的障碍就是电动汽车的售价相对过高。尽…

day2数据结构

双链表的插入 循环链表&#xff0c;判断循环链表是否为空 指向的是自己 仅设表尾指针的循环链表合并 代码举例 删除线性表的最小值&#xff0c;并由函数返回删除的值&#xff0c;空的位置&#xff0c;由最后一个元素填补&#xff0c;若表为空显示出错信息 &L 因为L会发生…