题目

蓝桥杯大赛历届真题 - 物联网设计与开发科目模拟试题 - 蓝桥云课 (lanqiao.cn)

看题目,
        A板涉及继电器K1,K2,按键USER,通信LoRa,显示OLED
        B板涉及ADC,LoRa,OLED

题目分析

A板

分析题目,A板没有插扩展板,只需要写oled显示,user按键,Lora信息传输三个功能函数

OLED:显示K1-LED,K2-LED的亮灭状态

USER:每次按下通过lora传输数据

LoRa:传输数据,注意地址配置。

B板

分析题目,B板扩展了模拟输出&指示灯模块,需要写adc采集数据,oled显示,Lora信息传输三个功能函数

ADC:采集电压值

OLED:根据a板发送的信息,更新显示REC,ADC的数值

LoRa:传输数据

题目解答

A板CubeMax配置

 这里注意几个点:
1.配置PC15的LED用于显示lora传输状态,高电平熄灭,低电平点亮
2.PC14的USER按键配置成外部中断模式,下降沿触发,这样可以及时响应
3.I2C3的oled要配置PB5引脚,这是oled的供电引脚
4.LoRa要配置PA4,PA10,PA9这三个脚,是LORA的片选,中断,和复位

使能时钟32MHz,就可以输出代码了。

添加OLED.c OLED.h LoRa.C LoRa.h的底层驱动文件到Inc,Src文件夹内,编译

A板功能代码编写

在i2c.c的初始化函数void MX_I2C3_Init(void)用户沙箱内添加100ms延时函数,用于OLED的充电等待

 i2c.c中的函数用户沙箱内添加接口函数

/**
  * @brief  OLED写入函数
  * @param  Type,Data
  * @retval 无
  */
void OLED_Write(uint8_t Type,uint8_t Data)
{
	uint8_t pData[2];
	pData[0] = Type;
	pData[1] = Data;
	HAL_I2C_Master_Transmit(&hi2c3,0x78,pData,2,10);
}

在spi.c的初始化函数void MX_SPI1_Init(void)的用户沙箱内拉高PA4,PA9。这是lora的片选和复位引脚,初始使能两个引脚。

spi.c中的函数用户沙箱内添加接口函数

/**
  * @brief  spi命令写入/读取
  * @param  ucAddr Data
  * @retval pRxData[1]
  */
uint8_t SPI_WriteRead(uint8_t ucAddr,uint8_t Data)
{
	uint8_t pTxData[2],pRxData[2];
	
	pTxData[0] = ucAddr;
	pTxData[1] = Data;
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi1,pTxData,pRxData,2,10);
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
	return pRxData[1];
}

在main.c中的函数用户沙箱内添加功能函数

定义变量

uint8_t A_Addr[7]={0x14,0x02,0x35,0x69,0x41,0x0A,0x01};
uint8_t B_Addr[7]={0x14,0x02,0x35,0x69,0x42,0x0B,0x11};	
uint8_t ucStata;
uint8_t *ubuff;

 数据传输和显示

void OLED_Proc(uint8_t ucStata)
{
	uint8_t *buff;
	switch(ucStata)
	{
		case 0x11:
			HAL_GPIO_WritePin(K1_GPIO_Port,K1_Pin,GPIO_PIN_SET);
			HAL_GPIO_WritePin(K2_GPIO_Port,K2_Pin,GPIO_PIN_RESET);
			sprintf((char *)buff,"K1-LED: ON");
			OLED_ShowString(0,0,buff,16);
			sprintf((char *)buff,"K2-LED:OFF");
			OLED_ShowString(0,2,buff,16);break;
		case 0x12:
			HAL_GPIO_WritePin(K1_GPIO_Port,K1_Pin,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(K2_GPIO_Port,K2_Pin,GPIO_PIN_SET);
			sprintf((char *)buff,"K1-LED:OFF");
			OLED_ShowString(0,0,buff,16);
			sprintf((char *)buff,"K2-LED: ON");
			OLED_ShowString(0,2,buff,16);break;
		case 0x13:
			HAL_GPIO_WritePin(K1_GPIO_Port,K1_Pin,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(K2_GPIO_Port,K2_Pin,GPIO_PIN_RESET);
			sprintf((char *)buff,"K1-LED:OFF");
			OLED_ShowString(0,0,buff,16);
			sprintf((char *)buff,"K2-LED:OFF");
			OLED_ShowString(0,2,buff,16);break;
	}
}
void Lora_Porc(uint8_t Addr[])
{
	uint8_t buff[7],count=0;
	LORA_Tx(Addr,7);
	if(LORA_Rx(buff) == 7)
	{
		for(int i=0;i<5;i++)
			if(buff[i]==B_Addr[i])
				count++;
	}
	if(count == 5)
		ucStata = buff[6];
}

在中断回调函数中调用两个中断函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	while(HAL_GPIO_ReadPin(USER_GPIO_Port,USER_Pin) == 0);//检测松手
	Lora_Porc(A_Addr);
	OLED_Proc(ucStata);
	HAL_GPIO_TogglePin(LD5_GPIO_Port,LD5_Pin);//测试代码
}

这样A板就写好了

B板CubeMax配置

 和A板的配置相似,增加了ADC采集,使能IN8,注意使能低功率等待

B板功能代码编写

oled和lora的底层代码与A板一致,在adc的void MX_ADC_Init(void)初始化函数中添加自动转换函数

    HAL_ADCEx_Calibration_Start(&hadc,ADC_SINGLE_ENDED);

添加ADC采集转换函数

void ADC_Read(uint16_t *usData)
{
	HAL_ADC_Start(&hadc);
	if(HAL_ADC_PollForConversion(&hadc,10) == HAL_OK)
	{
		usData[0] = HAL_ADC_GetValue(&hadc);
		HAL_GPIO_TogglePin(LD1_GPIO_Port,LD1_Pin);
	}
	if(HAL_ADC_PollForConversion(&hadc,10) == HAL_OK)
	{
		usData[1] = HAL_ADC_GetValue(&hadc);
		//HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
	}
}

在main.c中添加功能代码

定义变量

uint8_t A_Addr[7]={0x14,0x02,0x35,0x69,0x41,0x0A,0x01};
uint8_t B_Addr[7]={0x14,0x02,0x35,0x69,0x42,0x0B,0x11};	
uint16_t ucADC[2];
uint8_t stata;

OLED,LORA功能函数

void LORA_Proc(void)
{
	uint8_t buff[7],count=0,command;
	if(LORA_Rx(buff) == 7)              //地址判断
		for(int i = 0;i < 5;i ++)
		{
			if(A_Addr[i] == buff[i])
				count++;
		}
	if(count == 5 && buff[6] == 0x01)  //地址码正确,命令码正确
	{
		stata = 1;                       //改变OLED显示状态
		ADC_Read(ucADC);                 //读取ADC
		if(ucADC[0]*3.3/4095 < 1.5)      //判断ADC的电压区间
			command = 0x11;
		else if(ucADC[0]*3.3/4095 >= 1.5 && ucADC[0]*3.3/4095 < 2.5)
			command = 0x12;
		else if(ucADC[0]*3.3/4095 >= 2.5)
			command = 0x13;
		B_Addr[6] = command;//改变B的命令码
		LORA_Tx(B_Addr,7);//发送B的地址码,命令码
	}
}
void OLED_Proc(uint8_t stata)
{
	uint8_t* buff;
	if(stata==1)          //切换显示状态,保持两秒
	{
		stata=0;
		sprintf((char*)buff,"REC:OK  ");
		OLED_ShowString(0,0,buff,16);
		sprintf((char*)buff,"ADC:%.2fV",ucADC[1]*3.3/4095);
		OLED_ShowString(0,2,buff,16);
		delay_ms(2000);
	}
	else
	{
		sprintf((char*)buff,"REC:None");
		OLED_ShowString(0,0,buff,16);
		sprintf((char*)buff,"ADC:None");
		OLED_ShowString(0,2,buff,16);
	}
}
void delay_ms(uint16_t ms) //自定义毫秒级延时函数
{
	uint16_t i = 0;
	while(ms--){
		i=12000;
		while(i--);
	}
}

在主循环中调用这两个功能代码即可

这样B板的程序也写好了,编译下载,观察现象

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐