2024年蓝桥杯物联网省赛
#记录第四次蓝桥杯#
一、题目介绍
二、题目分析
2.1外设分析
通过对题目解读,一共会用到如下外设和资源:GPIO、OLED、LED、Lora模块、矩阵按键、电位器、继电器等。
软件层面需要使用到:定时器、中断、ADC
通信协议:IIC(OLED控制)、SPI(Lora通信)
2.2思路
我个人看到题目之后,是先从NODE.B开始编写的,除了Lora通信控制的部分,我是先写完NODE.B,再去写NODE.A的。先完成两个模块的一些基本功能(比如OLED显示、继电器控制、AD采集、按键等),最后再实现两边的通信。
三、CUBEMX配置
3.1控制器(NODE.A)
3.1.1引脚图
3.1.2时钟树
3.1.3定时器配置
3.1.4IIC配置
3.1.5 SPI配置
3.1.6 中断配置
定时器和外部中断设置好后,一定要记得使能(enable)
3.1.7GPIO配置
3.2采集器(NODE.B)
3.1.1引脚图
3.1.2ADC设置
ADC使用的是通道8和通道9
其余的配置同NODE.A一致,除了GPIO由于多了几个引脚可能配置不一样。
CUBEMX可能有些地方配置有些多余,这里仅供参考。
四、部分代码
这里只展示主函数部分,详细请看压缩包
4.1NODE.A
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "spi.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "lora.h"
#include "oled.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
void key_check(void);
void lora_proc(void);
void oled_proc(void);
uint16_t Scan_Col1(void);
uint16_t Scan_Col2(void);
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
struct key{
uint8_t B1;
uint8_t B2;
uint8_t B4;
uint8_t B5;
}key1;
struct show{
float CV;
float PV;
uint8_t K1;
uint8_t K2;
uint8_t mode;
}show1;
uint8_t Lora_Txbuff[6];
uint8_t Lora_Rxbuff[7];
uint8_t Strbuff[17];
uint8_t key_value;
uint8_t Tx_flag;
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C3_Init();
MX_SPI1_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
//OLED_Init();
HAL_NVIC_DisableIRQ(TIM2_IRQn);
HAL_TIM_Base_Start_IT(&htim2);
LORA_Init();
Write(ROW1,RESET);
Write(ROW2,RESET);
key_value=0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
lora_proc();
key_check();
oled_proc();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_3;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C3;
PeriphClkInit.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint16_t ms=0;
static uint8_t s=0;
if(++ms==999)
{
ms=0;
if(++s==3)
{
s=0;
Write(LD5,SET);
HAL_NVIC_DisableIRQ(TIM2_IRQn);
}
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case GPIO_PIN_1:
key_value=Scan_Col1();
while(Read(COL1)==0);
break;
case GPIO_PIN_0:
key_value=Scan_Col2();
while(Read(COL2)==0);
break;
default:
break;
}
}
void key_check(void)
{
if(key_value != 0)
{
switch(key_value)
{
case 1:
key1.B1=1;
break;
case 2:
key1.B2=1;
static uint8_t oled_flag=1;
if(oled_flag==1)
{
OLED_Init();
oled_flag=0;
}
Write(LD5,RESET);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
break;
case 4:
key1.B4=1;
break;
case 5:
key1.B5=1;
break;
default:
break;
}
Tx_flag=1;
key_value=0;
}
}
uint16_t Scan_Col1(void)
{
static uint16_t ucKey_val=0; //设立变量存键值
HAL_GPIO_WritePin(ROW1,GPIO_PIN_SET);//拉高3列的电平
HAL_GPIO_WritePin(ROW2,GPIO_PIN_SET);
//遍历列
for(uint8_t i=0;i<2;i++)
{
HAL_NVIC_DisableIRQ(EXTI0_1_IRQn);//关闭ROW1的中断
switch(i){
case 0:
HAL_GPIO_WritePin(ROW1,GPIO_PIN_RESET);//拉低列1
if(HAL_GPIO_ReadPin(COL1) == 0)//读取键值
ucKey_val = 1;
HAL_GPIO_WritePin(ROW1,GPIO_PIN_SET);//拉高列1
break;
case 1:
HAL_GPIO_WritePin(ROW2,GPIO_PIN_RESET);//拉低列2
if(HAL_GPIO_ReadPin(COL1) == 0)//读取键值
ucKey_val = 4;
HAL_GPIO_WritePin(ROW2,GPIO_PIN_SET);//拉高列2
break;
default:
break;
}
}
//拉低三列的电平
HAL_GPIO_WritePin(ROW1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(ROW2,GPIO_PIN_RESET);
//打开ROW1中断
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
return ucKey_val;
}
uint16_t Scan_Col2(void)
{
static uint16_t ucKey_val=0; //设立变量存键值
HAL_GPIO_WritePin(ROW1,GPIO_PIN_SET);//拉高3列的电平
HAL_GPIO_WritePin(ROW2,GPIO_PIN_SET);
//遍历列
for(uint8_t i=0;i<2;i++)
{
HAL_NVIC_DisableIRQ(EXTI0_1_IRQn);//关闭ROW1的中断
switch(i){
case 0:
HAL_GPIO_WritePin(ROW1,GPIO_PIN_RESET);//拉低列1
if(HAL_GPIO_ReadPin(COL2) == 0)//读取键值
ucKey_val = 2;
HAL_GPIO_WritePin(ROW1,GPIO_PIN_SET);//拉高列1
break;
case 1:
HAL_GPIO_WritePin(ROW2,GPIO_PIN_RESET);//拉低列2
if(HAL_GPIO_ReadPin(COL2) == 0)//读取键值
ucKey_val = 5;
HAL_GPIO_WritePin(ROW2,GPIO_PIN_SET);//拉高列2
break;
default:
break;
}
}
//拉低三列的电平
HAL_GPIO_WritePin(ROW1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(ROW2,GPIO_PIN_RESET);
//打开ROW1中断
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
return ucKey_val;
}
void lora_proc(void)
{
if(Tx_flag==1)
{
Tx_flag=0;
Lora_Txbuff[0]='Z'; //数据校验
Lora_Txbuff[1]=key1.B1;
Lora_Txbuff[2]=key1.B2;
Lora_Txbuff[3]=key1.B4;
Lora_Txbuff[4]=key1.B5;
Lora_Txbuff[5]='F';
LORA_Tx(Lora_Txbuff,sizeof(Lora_Txbuff));
//清空
key1.B1=0;
key1.B2=0;
key1.B4=0;
key1.B5=0;
}
if(LORA_Rx(Lora_Rxbuff)==6&&Lora_Rxbuff[0]=='Y')
{
show1.CV=(float)Lora_Rxbuff[1]/10;
show1.PV=(float)Lora_Rxbuff[2]/10;
show1.K1=Lora_Rxbuff[3];
show1.K2=Lora_Rxbuff[4];
show1.mode=Lora_Rxbuff[5];
}
}
void oled_proc(void)
{
sprintf((char*)Strbuff," %.1fV - %.1fV ",show1.CV,show1.PV);
OLED_ShowString(0,Strbuff);
sprintf((char*)Strbuff," %d%d%d ",show1.K1,show1.K2,show1.mode);
OLED_ShowString(2,Strbuff);
}
4.2NODE.B
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "spi.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "stdlib.h"
#include "oled.h"
#include "lora.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
void get_adc(void); //ADC采样控制
void adc_Prog(void);
void para_Prog(void);
void relay_Prog(void);
void show_Prog(void);
void led_prog(void);
void lora_Prog(void); //Lora通信设置
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint16_t Adc_val[2];
struct Adc{
uint16_t RP1; //RP1电压
uint16_t RP2; //RP2电压
uint16_t CV; //电压差
uint16_t PV; //电压参数
}val;
struct time{
uint16_t us; //定时微秒
uint16_t ms; //定时毫秒
uint16_t s; //定时器秒
}time;
uint8_t Lora_Txbuff[6];
uint8_t Lora_Rxbuff[7];
uint8_t Strbuff[17]; //OLED显示字符串
uint8_t dis_Mode; //模式切换标志位
uint8_t work_Mode; //模式选择
uint8_t adc_flag; //ADC采样控制
uint8_t tx_flag;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC_Init();
MX_I2C3_Init();
MX_TIM2_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
OLED_Init();
LORA_Init(); //lora初始化
HAL_TIM_Base_Start_IT(&htim2); //打开定时器2
dis_Mode=0;
work_Mode=0;
val.PV=10;
adc_flag=1;
tx_flag=0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
led_prog();
show_Prog();
relay_Prog();
lora_Prog();
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_3;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C3;
PeriphClkInit.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/*外部中断*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(HAL_GPIO_ReadPin(USER)==0)
if(++dis_Mode==2)
dis_Mode=0;
}
/*定时器中断*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(++time.ms==99)
{
time.ms=0;
adc_flag=1;
}
}
void get_adc(void)
{
HAL_ADC_Start(&hadc);
if(HAL_ADC_PollForConversion(&hadc,10)==HAL_OK)
Adc_val[0]=HAL_ADC_GetValue(&hadc);
if(HAL_ADC_PollForConversion(&hadc,10)==HAL_OK)
Adc_val[1]=HAL_ADC_GetValue(&hadc);
val.RP1=(int)(Adc_val[1]*3.3/4095*10);
val.RP2=(int)(Adc_val[0]*3.3/4095*10);
}
/*ADC显示程序*/
void adc_Prog(void)
{
sprintf((char*)Strbuff," RP1:%.1fV ",(float)val.RP1/10);
OLED_ShowString(0,Strbuff);
sprintf((char*)Strbuff," RP2:%.1fV ",(float)val.RP2/10);
OLED_ShowString(2,Strbuff);
}
void para_Prog(void)
{
sprintf((char*)Strbuff," CV:%.1fV ",(float)val.CV/10);
OLED_ShowString(0,Strbuff);
sprintf((char*)Strbuff," PV:%.1fV ",(float)val.PV/10);
OLED_ShowString(2,Strbuff);
}
void relay_Prog(void)
{
if(work_Mode==0)
{
if(val.CV>val.PV)
{
HAL_GPIO_WritePin(Relay1,OFF);
HAL_GPIO_WritePin(Relay2,ON);
}
else
{
HAL_GPIO_WritePin(Relay1,ON);
HAL_GPIO_WritePin(Relay2,OFF);
}
}
}
/*OLED显示*/
void show_Prog(void)
{
if(adc_flag==1)
{
get_adc();
adc_flag=0;
val.CV=abs(val.RP1-val.RP2);
}
if(dis_Mode==0)
adc_Prog();
else
para_Prog();
}
/*LED指示灯*/
void led_prog(void)
{
if(work_Mode==0)
HAL_GPIO_WritePin(LD5,OFF);
else
HAL_GPIO_WritePin(LD5,ON);
}
void lora_Prog(void)
{
if(tx_flag==1)
{
tx_flag=0;
Lora_Txbuff[0]='Y'; //数据校验
Lora_Txbuff[1]=(int)(val.CV);
Lora_Txbuff[2]=(int)(val.PV);
Lora_Txbuff[3]=Read(Relay1);
Lora_Txbuff[4]=Read(Relay2);
Lora_Txbuff[5]=work_Mode;
LORA_Tx(Lora_Txbuff,sizeof(Lora_Txbuff));
}
if(LORA_Rx(Lora_Rxbuff)==6&&Lora_Rxbuff[0]=='Z'&&Lora_Rxbuff[5]=='F')
{
if(Lora_Rxbuff[1]==1)
{
if(++work_Mode==2)
work_Mode=0;
}
if(Lora_Rxbuff[2]==1)
{
tx_flag=1;
}
if(Lora_Rxbuff[3]==1)
{
switch(work_Mode)
{
case 0:
val.PV+=1;
break;
case 1:
HAL_GPIO_TogglePin(Relay1);
break;
default:
break;
}
}
if(Lora_Rxbuff[4]==1)
{
switch(work_Mode)
{
case 0:
val.PV-=1;
break;
case 1:
HAL_GPIO_TogglePin(Relay2);
break;
default:
break;
}
}
}
}
/* USER CODE END 4 */
五、效果
效果还没拍视频,后期再补上
六、总结与感悟
这是本人第一次写这么多内容的blog,还有本人语文素养比较低。可能有些措辞不当或者语句不通顺的地方,希望能够指正。
代码总体来说的话,大部分是自己编写的,有一部分是借鉴网上的大佬的代码。由于本人C语言功底比较薄弱,所以有些语法写的很笨。或许有更好更高效的方法,也希望能给我指出一些建议。
第四次参加蓝桥杯了,之前参加的是单片机和嵌入式组。今年是第一次参加物联网,也是最后一次参加蓝桥杯了。赛前没有很好的准备,赛场上只完成了部分功能,赛后经过不断完善,基本上将所有功能都实现了。虽然没有在赛场上完成全部功能,但是赛后能把所有功能都实现,也算是不给自己留下太多遗憾了。
七、代码及题目链接
百度网盘:链接:https://pan.baidu.com/s/16Qw5IuQn-rivRKj6Fb_RAg?pwd=h8tu 提取码:h8tu
作者:Aladdin5298