十一届蓝桥杯嵌入式个人赛

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
直接上代码首先是所有变量加LCD任务和ADC读取

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "key.h"
#include "led.h"
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
__IO uint32_t keyTick;    //按键扫描时间
__IO uint32_t adcTick;    //adc扫描时间
__IO uint32_t uartTick;   //串口扫面时间
u8 Lcdpage;               //界面序号
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
u8 Vmax = 30,Vmin=10;     //lcd显示的电压最大最小值
u8 Vmax_com = 30,Vmin_com = 10;  //B1返回主界面时进行逻辑判断的变量
u8 Vmax_uart; u8 Vmin_uart;      //串口命令是否合理变量判断
u16 Time,sec;                 //电压计时
u8 led_ctrl;                  //led灯点亮

_Bool rx_cnt_flag = 0;        //串口命令是否正确
_Bool timeflag;               //D1灯标志位
_Bool keyflag;                //D2灯标志位
_Bool uartflag;               //D3灯标志位
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
u16 adc2_value,adc_num;        //adc2_value读取值,adc__num为均值滤波
u8  adc_cnt;                    //adc采集的数量
float v37,V15_value;           //v37是当前时刻电位,V15_value为上一时刻电位

u8 uart_buf[2];                //串口发送,重定向
u8 rx_buf[10];                 //串口接收数组
u8 rx_cnt;                     //串口接收几个数
/* USER CODE END PM */

void LCD_Process()
{
   u8 text[30];
  if(!Lcdpage)         //主界面
  {
   LCD_SetTextColor(White);
  sprintf((char*)text,"      Data");
  LCD_DisplayStringLine(Line1,text);
  
  sprintf((char*)text,"  V:%0.2fv",v37);
  LCD_DisplayStringLine(Line3,text);
  
  sprintf((char*)text,"  T:%ds",sec);
  LCD_DisplayStringLine(Line4,text);
  }

  if(Lcdpage==1)      //参数界面
  { 
   LCD_SetTextColor(White);
   sprintf((char*)text,"      Para");
  LCD_DisplayStringLine(Line1,text);
  
  sprintf((char*)text,"  V:%0.1fV",Vmax/10.0f);
  LCD_DisplayStringLine(Line3,text);
  
  sprintf((char*)text,"  T:%0.1fV",Vmin/10.0f);
  LCD_DisplayStringLine(Line4,text);
  }
}
//2.adc的采集
void ADC_Process()
{

  HAL_ADC_Start(&hadc2);                   //开启adc2
  adc2_value = HAL_ADC_GetValue(&hadc2);   //获取adc2值
  adc_num = adc_num+adc2_value;            //采集5次adc值的总和
  adc_cnt++;
  if(adc_cnt == 5)                         //把5次的值进行均算
  {

    V15_value = v37;
    v37 = (adc_num/5.0f) / 4095.0f* 3.3f;   
    adc_num = 0;
    adc_cnt = 0;
  }

}

随后加按键的任务

//3.按键任务
void KEY_Process()
{
   //10ms扫描一次
  if(uwTick - keyTick<10) return;
  
  keyTick = uwTick;
  Key_Read();
  //KB1按下
  if(Trg & 0x01)
  {
    	LCD_Clear(Black);//刷新界面
    
     Lcdpage =(Lcdpage+1)%2;
    
    if(!Lcdpage)      //逻辑判断,数值是否合理,主界面生效
    {
      if(Vmax>=(Vmin+10))
      {
        keyflag = 0;
       Vmax_com = Vmax;
       Vmin_com = Vmin;
      }
      else
      {
        keyflag = 1;     //不合理则D2的标志位打开,D2亮
        Vmax = Vmax_com;
        Vmin = Vmin_com;
      }
    }
  }
    //KB2
  if(Trg & 0x02)
  {
    if(Lcdpage)
    {
      if(Vmax<33)
       Vmax+=1;
      else
       Vmax = 0;
    } 
    }
    //KB3
  if(Trg & 0x04)
  {
    if(Lcdpage)
    {
      if(Vmin<33)
       Vmin+=1;
      else
       Vmin = 0;
    }
  }  
}

随后是计时adc读取的时间,注意函数
void SysTick_Handler(void),我从stm32g4xx_it.c文件中剪切到了main.c文件

//5.adc计时时间
void ADC_Time()
{
  //从小往大,穿过最小值
   if((V15_value<=(Vmin/10.0f))&&(v37>=(Vmin/10.0f)))
   {
         sec = 0;
         timeflag=1;   //开始计时
   }
   //从小往大,穿过最大值
   if((V15_value<=(Vmax/10.0f))&&(v37>=(Vmax/10.0f)))
   {
         timeflag=0;
   }
   //注释处为增加任务合理性
//   if((V15_value<=(Vmin/10.0f))&&(v37<=(Vmin/10.0f)))
//   {
//         sec = 0;
//         timeflag=0;
//   }
}
//6.SysTick中断任务,1ms执行一次,用于adc计时
void SysTick_Handler(void)
{
  HAL_IncTick();
  if(timeflag==1)
  {
    //1ms执行一次
    Time++;
    
    if(Time ==1000)
    {
      //1s后sec自加
      Time=0;
      sec++;
    }
  }
}

再是串口任务,这次串口不用重定向,不过我还是建议各位都写写

//7.50ms定时清除串口接收数组
void RxIde_Process(void)
{
  //50ms执行
   if(uwTick - uartTick<50) return;
    uartTick = uwTick;
  
  //如果串口有数据并且不到7个
  if((rx_cnt>0) &&(rx_cnt_flag==0))
  {
      uartflag = 1;   //D3灯亮
      printf("input error\r\n");
  
  }
  rx_cnt_flag = 0;    //串口是否接收7个数据标志位
  rx_cnt = 0;         //串口接收数量
  memset(rx_buf,'\0',sizeof(rx_buf));  //清空rx__buf数组
 
 //8.检查串口发送数据的正确性
_Bool Check_String(u8 *str)
{
  //判断每一位的数据,不对返回0,正确返回1
  if((str[1] !='.') || (str[3] != ',')|| (str[5] !='.'))
    return 0;
  if((str[0] < '0') || (str[0]>'9'))
    return 0;
  if((str[2] < '0') || (str[2]>'9'))
    return 0;
  if((str[4] < '0') || (str[4]>'9'))
    return 0;
  if((str[6] < '0') || (str[6]>'9'))
    return 0;

    return 1;
} 
}
//9.串口接收回调函数执行的任务
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  uartTick = uwTick;  //每执行一次回调函数重新计时50ms
  rx_buf[rx_cnt++] = uart_buf[0];     
  HAL_UART_Receive_IT(&huart1,uart_buf,1); //开启串口接收中断
  if(rx_cnt == 7)   //接收7个数据
  {
    rx_cnt_flag = 1;
    if(Check_String(rx_buf) == 0) //检查数据合理性,不合理打印错误
    {
     printf("input error\r\n");
    }
   if(Check_String(rx_buf) == 1)//检查数据合理性,合理改变电位极限值
   {
       Vmax_uart = (rx_buf[0] - '0')*10 + rx_buf[2] - '0';
       Vmin_uart = (rx_buf[4] - '0')*10 + rx_buf[6] - '0';
     //判断串口的数据电位是否合理
        if(Vmax_uart>=(Vmin_uart+10) && (Vmax_uart<33)&& (Vmin_uart<33))
      {
        uartflag = 0;
       Vmax = Vmax_uart;
       Vmin = Vmin_uart;
      }
      else
      {
        uartflag = 1;
       Vmax_uart = Vmax;
       Vmin_uart = Vmin;
      }
   }
    rx_cnt =0;
  }
}

//4.led任务
void LED_Process()
{
  if(timeflag)       //D1的亮灭
    led_ctrl |= 0x01;
  else 
    led_ctrl &= ~0x01;
  
  if(keyflag)
    led_ctrl |= 0x02;    //D2的亮灭
  else 
    led_ctrl &= ~0x02;
  
  if(uartflag)
    led_ctrl |= 0x04;   //D3的亮灭
  else 
    led_ctrl &= ~0x04;      
  
  LED_Control(led_ctrl);
}

主函数调用任务函数即可

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    LCD_Process();
    LED_Process();
    ADC_Process();
    KEY_Process();
    ADC_Time();
    RxIde_Process();

  }

最后欢迎各位指正错误

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值