第十三届省赛蓝桥杯物联网程序设计试题

一、真题部分

二、LoRa_A

1、配置根据试题的要求配置STM32CubeMX

(1)引脚配置

将PC14引脚配置为输入模式

PC14 用户按键引脚

将PA10引脚配置为中断模式

PA10 LoRa模块DIO0引脚

将以下引脚配置为输出模式

PC15 用户LED引脚

PB5 OLED电源控制引脚

PA11和PA12 继电器控制引脚

PA4和PA9 LoRa模块片选和复位引脚,初始为高电平

GPIO引脚初始化

使能EXTI4_15中断

(2)配置I2C模块,因为新版数据资源包需要自己创建I2C模块的程序,所以利用STM32CubeMX配置硬件I2C模块

(3)配置串口模块,波特率为9600Baud,允许串口全局中断

(4)配置LoRa通信所需的SPI串行设备接口(全双工、高速、同步通信总线)

MOSI:主设备输出/从设备输入引脚,该引脚在主模式下发送数据,从模式下接受数据,对应PA7引脚

MISO:主设备输入/从设备输出引脚,该引脚在从模式下发送数据,主模式下接受数据,对应PA6引脚

SCLK:串行时钟信号,由主设备产生,对应PA5引脚

(5)配置系统时钟,采用32MHz时钟

2、程序设计

(1)导入数据资源包中提供的代码

(2)由于利用STM32创建I2C和SPI模块缺少对应的函数,所以需要添加一部分代码,通过运行程序可以发现OLED_Write函数和SPI_WriteRead函数缺少相关的定义

在i2c.c函数中定义OLED_Write函数,同时在i2c.h中声明OLED_Write函数

void OLED_Write(uint8_t ucType,uint8_t ucData)
{
  uint8_t pData[2];
  pData[0]=ucType;
  pData[1]=ucData;
  HAL_I2C_Master_Transmit(&hi2c3, 0x78, pData, 2, 10);
}

在spi.c中定义SPI_WriteRead函数,同时在spi.h中声明SPI_WriteRead函数

uint8_t SPI_WriteRead(uint8_t ucAddr, uint8_t ucData) 
{
  uint8_t pTxData[2], pRxData[2];
  pTxData[0] = ucAddr;
  pTxData[1] = ucData;
  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];
}

(3)在main.c定义任务初始化函数

void Task_Main()
{
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);//OLED屏幕上电
    HAL_Delay(200);//延时200ms十分重要,否则OLED可能无法显示
    OLED_Init();
    OLED_Clear();
    LORA_Init();
    OLED_ShowString(0,0,(uint8_t *)"       ",16);
    OLED_ShowString(0,2,(uint8_t *)"       ",16);
    OLED_ShowString(0,0,(uint8_t *)"     RX:     ",16);
    OLED_ShowString(0,2,(uint8_t *)"    NUM:0    ",16);
}

(4)在main.c中分别定义各个模块的函数

uint8_t RxData[16];
uint8_t TxData[5]="error";
char LCD_Line1st[16];
char LCD_Line2st[16];
uint8_t count=0;
uint8_t    UART_Proc()
{
    uint8_t ucValue=0;
    HAL_UART_Receive(&huart2,RxData,1,500);
    if(RxData[0]!=0)
    {
    if(RxData[0]=='@'||RxData[0]=='#'||RxData[0]=='$')
        {
            if(RxData[0]=='@'){
                ucValue=1;
            }
            if(RxData[0]=='#'){
                ucValue=2;
            }
            if(RxData[0]=='$'){
                ucValue=3;
            }
        }
        else
        {
            HAL_UART_Transmit(&huart2,TxData,sizeof(TxData),500);
            ucValue=4;
        }
                    return ucValue;
    }
    return 0;
}
void LED_Proc()
{
    uint8_t ucValue=UART_Proc();
    if(ucValue==1)
        HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_15);
    if(ucValue==2)
        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_11);
    if(ucValue==3)
        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_12);
}
void OLED_Proc()
{
    uint8_t ucValue=UART_Proc();
    if(ucValue==1){
        count=count+1;
        sprintf(LCD_Line2st,"     RX:@");
        OLED_ShowString(0,0,(uint8_t *)LCD_Line1st,16);
        sprintf(LCD_Line2st,"    NUM:%d",count);
        OLED_ShowString(0,2,(uint8_t *)LCD_Line2st,16);
    }
    if(ucValue==2){
        count=count+1;
        sprintf(LCD_Line2st,"     RX:#");
        OLED_ShowString(0,0,(uint8_t *)LCD_Line1st,16);
        sprintf(LCD_Line2st,"    NUM:%d",count);
        OLED_ShowString(0,2,(uint8_t *)LCD_Line2st,16);
    }
    if(ucValue==3){
        count=count+1;
        sprintf(LCD_Line2st,"     RX:$");
        OLED_ShowString(0,0,(uint8_t *)LCD_Line1st,16);
        sprintf(LCD_Line2st,"    NUM:%d",count);
        OLED_ShowString(0,2,(uint8_t *)LCD_Line2st,16);
    }
    if(ucValue==4){
        if(count==0)
            count=0;
        else
            count--;
        sprintf(LCD_Line1st,"     RX:error");
        OLED_ShowString(0,0,(uint8_t *)LCD_Line1st,16);
        sprintf(LCD_Line2st,"    NUM:%d",count);
        OLED_ShowString(0,2,(uint8_t *)LCD_Line2st,16);
    }
}
void LORA_Proc()
{
    uint8_t LD5=HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_15);
    uint8_t K1=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11);
    uint8_t K2=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12);
    uint8_t pcBuf[3]={LD5,K1,K2};
    if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)==GPIO_PIN_RESET)
        {
            HAL_Delay(10);
            if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)==GPIO_PIN_RESET)
                LORA_Tx(pcBuf,3);
        }
}

三、LoRa_B

1、配置根据试题要求配置STM32CubeMX

(1)引脚配置

将PC14引脚配置为输入模式

PC14 用户按键引脚

将PA10引脚配置为中断模式

PA10 LoRa模块DIO0引脚

将以下引脚配置为输出模式

PC15 用户LED引脚

PB5 OLED电源控制引脚

PA11和PA12 继电器控制引脚

PA4和PA9 LoRa模块片选和复位引脚,初始为高电平

使能EXTI4_15中断

(2)配置I2C模块,因为新版数据资源包需要自己创建I2C模块的程序,所以利用STM32CubeMX配置硬件I2C模块

(2)配置ADC模块,由原理图可以看出RP1对应引脚为PB1,RP2对应引脚为PB0,故使用ADC模块的8通道和9通道,同时需要DMA传输,将外设模块中的电压值传输到内存中

扫描模式是默认开启的,同时必须开启连续模式,否则采集一轮结束后不会继续采集,这样就不会触发DMA中断进入回调函数了。连续扫描模式下,多通道会根据length数量循环采集各通道,如ch8和ch9两通道,length为10的话,则adc_value[0][2][4][6][8]存放的就是ch8通道的采样值,adc_value[1][3][5][7][9]数组位置存放的是ch9的值:

(3)配置串口模块,通讯波特率为9600Baud,同时开启接受引脚的DMA传输

(4)配置LoRa通信所需的SPI串行设备接口(全双工、高速、同步通信总线)

MOSI:主设备输出/从设备输入引脚,该引脚在主模式下发送数据,从模式下接受数据,对应PA7引脚

MISO:主设备输入/从设备输出引脚,该引脚在从模式下发送数据,主模式下接受数据,对应PA6引脚

SCLK:串行时钟信号,由主设备产生,对应PA5引脚

(5)配置系统时钟,采用32MHz的时钟

2、程序设计

(1)导入数据资源包中的代码,配置底层接口,由于和LoRa_A部分方法一样,此处不再赘述,在spi.c和i2c.c中分别定义以下代码,但不要忘了在头文件中声明

void OLED_Write(uint8_t ucType,uint8_t ucData)
{
    uint8_t pData[2];
    pData[0]=ucType;
    pData[1]=ucData;
    HAL_I2C_Master_Transmit(&hi2c3,0x78,pData,2,10);
}
uint8_t SPI_WriteRead(uint8_t ucAddr,uint8_t ucData)
{
    uint8_t pTxData[2],pRxData[2];
    pTxData[0]=ucAddr;
    pRxData[1]=ucData;
    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];
}

(2)主体函数设计

char ucBuf[16];  //OLED转换值
uint8_t usADC[2];//ADC转换值
uint8_t count=0;//存储同步次数
uint8_t RxData[3];//存储LORA接受值
/*PA10中断函数,用于接受LROA发送过来的数据*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_10)
    {
            count++;
            LORA_Rx(RxData);
    }
}
/*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);//RP2
  if(HAL_ADC_PollForConversion(&hadc, 10) == HAL_OK)
    usData[1] = HAL_ADC_GetValue(&hadc);//RP1
}
/*ADC转换函数,将转换后的值显示在OLED对应的位置上*/
void ADC_Proc()
{
    ADC_Read(usADC);
    sprintf(ucBuf, "    RP2:%3.1fV", usADC[0]*3.3/4095);
    OLED_ShowString(0, 0, (uint8_t *)ucBuf, 16);
    sprintf(ucBuf, "    RP1:%3.1fV", usADC[1]*3.3/4095);
    OLED_ShowString(0, 2, (uint8_t *)ucBuf, 16);
}
/*状态显示函数*/
void State_Proc()
{
    sprintf(ucBuf,"    NUM:%d   ",count);
    OLED_ShowString(0,0,(uint8_t *)ucBuf,16);
    if(RxData[1]==GPIO_PIN_SET&&RxData[2]==GPIO_PIN_SET)
    {
      sprintf(ucBuf,"    STA:ON   ");
        OLED_ShowString(0,2,(uint8_t *)ucBuf,16);
    }
    else
    {
        sprintf(ucBuf,"    STA:OFF    ");
        OLED_ShowString(0,2,(uint8_t *)ucBuf,16);
    }
}
/*OLED屏幕界面切换函数*/
void OLED_Proc()
{
    if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)==GPIO_PIN_RESET)
    {
        HAL_Delay(10);
        if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_14)==GPIO_PIN_RESET)
            ucState^=1;
    }
    if(ucState==0)
        ADC_Proc();
    else
        State_Proc();
}
/*将A板对应的LED灯状态同步到B板*/
void LED_Proc()
{
    if(RxData[0]==GPIO_PIN_RESET)
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
    else
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
    if(RxData[1]==GPIO_PIN_RESET)
        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_RESET);
    else
        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_SET);
    if(RxData[2]==GPIO_PIN_RESET)
        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_RESET);
    else
        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_SET);
}

(3)在主函数中调用OLED_Proc()函数和LED_Proc()函数即可

物联沃分享整理
物联沃-IOTWORD物联网 » 第十三届省赛蓝桥杯物联网程序设计试题

发表评论