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





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

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


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

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

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

c 复制代码
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数值的时候备份一下,在定时器里去分析是否稳定,不稳定定时器计数值归零否者继续计数

c 复制代码
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;
}
c 复制代码
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直接清屏就行,断开电源开启还要初始化很麻烦


储存用结构体

c 复制代码
typedef struct{
  unsigned char MEMWT[10];
	unsigned char MEMBF[10];
}MEMO;

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

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

c 复制代码
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));
}
c 复制代码
        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是不行的,这就要用算法来操作了

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

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

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

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

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

c 复制代码
            while(UARTRXMSG[i ++] != ',');
			while(UARTRXMSG[i] != '\0') TEMPUARTRX[j ++] = UARTRXMSG[i ++];

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

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

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

相关推荐
麦兜*2 天前
MongoDB 在物联网(IoT)中的应用:海量时序数据处理方案
java·数据库·spring boot·物联网·mongodb·spring
元亓亓亓2 天前
LeetCode热题100--105. 从前序与中序遍历序列构造二叉树--中等
算法·leetcode·职场和发展
测试老哥2 天前
Selenium 使用指南
自动化测试·软件测试·python·selenium·测试工具·职场和发展·测试用例
仙俊红2 天前
LeetCode每日一题,20250914
算法·leetcode·职场和发展
亿坊电商3 天前
物联网领域中PHP框架的最佳选择有哪些?
物联网·struts·php
御控工业物联网3 天前
灌区泵站远程监控物联网网关解决方案
物联网·远程监控·物联网网关·泵站·灌区泵站
前端小超超3 天前
capacitor配置ios应用图标不同尺寸
ios·蓝桥杯·cocoa
BAGAE3 天前
MODBUS 通信协议详细介绍
linux·嵌入式硬件·物联网·硬件架构·iot·嵌入式实时数据库·rtdbs
睡不醒的kun3 天前
leetcode算法刷题的第三十四天
数据结构·c++·算法·leetcode·职场和发展·贪心算法·动态规划
吃着火锅x唱着歌3 天前
LeetCode 1446.连续字符
算法·leetcode·职场和发展