> 文档中心 > STM32ADC--基于HAL库(第十届蓝桥杯嵌入式省赛)

STM32ADC--基于HAL库(第十届蓝桥杯嵌入式省赛)

文章目录

  • 前言
  • 一、CubeMX配置(第十届蓝桥杯嵌入式省赛完整版)
  • 二、代码相关定义、声明
    • 1.函数声明
    • 2.宏定义
    • 3.变量定义
  • 三、主要函数
    • 1.按键扫描
    • 2.设置模式
    • 3.获取R37电压
    • 4.选中行高亮
    • 5.LED灯关闭
    • 6.Main函数
  • 四、实验结果
  • 五、源码(转载请注明出处)
  • 总结

前言

相关说明:

开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
涉及题目:STM32ADC–基于HAL库(第十届蓝桥杯嵌入式省赛-研究生组)
题目难点:LCD与LED冲突。LED3在作为Upper LED,当前电压超出阈值时闪烁时仍存在问题,其他皆正常,用的是新板,不确定是否与板子有关。


CubeMX配置、主要函数代码及说明:

一、CubeMX配置(第十届蓝桥杯嵌入式省赛完整版)

1.使能外部高速时钟:在这里插入图片描述

2.配置时钟树:在这里插入图片描述

3.GPIO:在这里插入图片描述

4.ADC(除图中配置,其他默认即可):在这里插入图片描述

5.I2C(存储电压值、LED灯):在这里插入图片描述

6.TIM6(0.2s中断):在这里插入图片描述
在这里插入图片描述

二、代码相关定义、声明

1.函数声明

void EEPROM_WriteBuff(uint8_t addr,uint8_t *writeBuff,uint32_t numToWrite);//EEPROM写数组void EEPROM_ReadBuff(uint8_t addr,uint8_t *readBuff,uint32_t numToRead);//EEPROM读数组double ADC_GetValue(void);//获取ADC的值void KEY_Scan(void);//按键扫描void Setting_Mode(void);//设置模式void Color_change(void);//选中行高亮void Data_change(uint8_t mode);//数据更改(max/min/led)void Data_read(void);//从EEPROM中读取数据void Data_save(void);//数据保存char* GET_Statue(void);//获取当前状态(Upper/Lower/Normal)void LCD_fresh(void);//LCD更新void LCD_Init_Show(void);//LCD初始化void LED_refresh(void);//LED更新

2.宏定义

#define LED_GPIO_PORT   GPIOC#define LED1_GPIO_PINGPIO_PIN_8#define LED2_GPIO_PINGPIO_PIN_9#define LED3_GPIO_PINGPIO_PIN_10#define LED4_GPIO_PINGPIO_PIN_11#define LED5_GPIO_PINGPIO_PIN_12#define LED6_GPIO_PINGPIO_PIN_13#define LED7_GPIO_PINGPIO_PIN_14#define LED8_GPIO_PINGPIO_PIN_15#define ON GPIO_PIN_RESET#define OFFGPIO_PIN_SET#define TOG2#define LED1(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED1_GPIO_PIN,a)#define LED2(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED2_GPIO_PIN,a)#define LED3(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED3_GPIO_PIN,a)#define LED4(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED4_GPIO_PIN,a)#define LED5(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED5_GPIO_PIN,a)#define LED6(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED6_GPIO_PIN,a)#define LED7(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED7_GPIO_PIN,a)#define LED8(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED8_GPIO_PIN,a)#define LED1_TOG()HAL_GPIO_TogglePin(LED_GPIO_PORT,LED1_GPIO_PIN)#define LED2_TOG()HAL_GPIO_TogglePin(LED_GPIO_PORT,LED2_GPIO_PIN)#define LED3_TOG()HAL_GPIO_TogglePin(LED_GPIO_PORT,LED3_GPIO_PIN)#define LED4_TOG()HAL_GPIO_TogglePin(LED_GPIO_PORT,LED4_GPIO_PIN)#define LED5_TOG()HAL_GPIO_TogglePin(LED_GPIO_PORT,LED5_GPIO_PIN)#define LED6_TOG()HAL_GPIO_TogglePin(LED_GPIO_PORT,LED6_GPIO_PIN)#define LED7_TOG()HAL_GPIO_TogglePin(LED_GPIO_PORT,LED7_GPIO_PIN)#define LED8_TOG()HAL_GPIO_TogglePin(LED_GPIO_PORT,LED8_GPIO_PIN)#defineKEY1_GPIO_PORT GPIOB#define KEY1_GPIO_PINGPIO_PIN_0#defineKEY2_GPIO_PORT GPIOB#define KEY2_GPIO_PINGPIO_PIN_1#defineKEY3_GPIO_PORT GPIOB#define KEY3_GPIO_PINGPIO_PIN_2#defineKEY4_GPIO_PORT GPIOA#define KEY4_GPIO_PINGPIO_PIN_0#define max 2//max数据对应行 下三个同理#define min 4#define upper6#define lower 8#define add   1//加模式#define sub  0//减模式

3.变量定义

double writeBuff[1];//EEPROM写数据数组double readBuff[1];//EEPROM读数据数组uint8_t v_maxAddr=0X08;//EEPROM存储上限电压的地址uint8_t v_minAddr=0X00;//EEPROM存储下限电压的地址double v_max;//上限电压double v_min;//下限电压double v_now;//当前电压double v_step=0.3;//电压每次改变值double v_upper=3.3;//电压更改最大值double v_lower=0;//电压更改最小值uint8_t led_upAddr=0X10;//EEPROM存储Upper LED的地址uint8_t led_lowAddr=0X18;//EEPROM存储Lower LED的地址int led_up;//Upper对应LEDint led_low;//Lower对应LEDint led_max=8;//最大为LED8int led_min=1;//最小为LED1int led_step=1;//LED每次改变值int led_statue=1;//LED灯状态(0低于下限/1正常状态/2高于上限)int led_change=0;//LED灯状态改变标志位uint8_t led_close[9];//LED灯关闭数组(为1则下标对应的LED灯关闭)uint8_t page=1;//LCD页面(1/2)uint8_t line_now=48;//当前行对应坐标uint8_t line_old=48;//初始行对应坐标uint8_t line_end=192;//结束行对应坐标uint8_t line_setp=48;//每行坐标差uint8_t lcd_fresh_num=0;//主循环中LCD更新标志(0.4s更新一次,减小LCD更新对LED的影响)char str[30];//组合字符串

三、主要函数

1.按键扫描

主循环中只有一个按键有效。

void KEY_Scan(){//KEY1 界面切换if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET);page=2;//LCD页改变LCD_fresh();//LCD更新Setting_Mode();//进入设置模式led_change=1;//LED更新标志,使新用新设定的LED}}}

2.设置模式

相比于之前,本次设置模式函数的编写降低了程序耦合度,将数据的增加,减小和保存都写成一个独立的函数来调用。

void Setting_Mode()//设置模式{uint8_t i;line_now=line_old;//当前行更新uint8_t lcd_change=0;//LCD更新标志位Color_change();//当前行颜色翻转,上一行颜色恢复while(1){if(lcd_change){lcd_change=0;Color_change();//当前行颜色翻转,上一行颜色恢复}//KEY1 界面切换if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET);Data_save();//将数据存储至EEPROMfor(i=1;i<9;i++)//LED关闭数组重置{led_close[i]=1;}led_close[led_up]=0;//将新设定的Upper LED对应下标改为0led_close[led_low]=0;//将新设定的Lower LED对应下标改为0page=1;//LCD显示页改变LCD_fresh();//LCD更新break;//退出循环}}//KEY2 选择按键else if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET);line_now+=line_setp;//行增加if(line_now>line_end)//如果当前行大于末尾行则回到初始行line_now=line_old;lcd_change=1;//LCD改变标志位置1}}//KEY3 ++else if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET);Data_change(add);//当前数据以增模式改变lcd_change=1;//LCD改变标志位置1}}//KEY4 --else if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET);Data_change(sub);//当前行数据以减模式改变lcd_change=1;//LCD改变标志位置1}}v_now=ADC_GetValue();//获取R37的电压值LED_refresh();//LED动态更新}//while}

3.获取R37电压值

使用ADC时需注意,每次GetValue之前都要调用一次Start函数。

double ADC_GetValue(){doublecount;HAL_ADC_Start(&hadc2);count=HAL_ADC_GetValue(&hadc2);return count*3.3/4096;}

4.选中行高亮

函数中str保存当前行显示字符串,str2保存上一行显示字符串,首行数据的上一行是末尾行。

void Color_change(){char str2[30];if(line_now==line_old+line_setp*0){sprintf(str,"   Max Volt:%.2fV",v_max);sprintf(str2,"   Lower:LD%d    ",led_low);}else if(line_now==line_old+line_setp*1){sprintf(str,"   Min Volt:%.2fV",v_min);sprintf(str2,"   Max Volt:%.2fV",v_max);}else if(line_now==line_old+line_setp*2){sprintf(str,"   Upper:LD%d",led_up);sprintf(str2,"   Min Volt:%.2fV",v_min);}else if(line_now==line_old+line_setp*3){sprintf(str,"   Lower:LD%d    ",led_low);sprintf(str2,"   Upper:LD%d",led_up);}LCD_SetTextColor(Blue);//上一行颜色恢复LCD_SetBackColor(White);if(line_now==line_old)LCD_DisplayStringLine(line_end,(unsigned char*)str2);elseLCD_DisplayStringLine(line_now-line_setp,(unsigned char*)str2);LCD_SetTextColor(White);//当前颜色翻转LCD_SetBackColor(Blue);LCD_DisplayStringLine(line_now,(unsigned char*)str);}

5.LED灯关闭

LED关闭数组中,若值为1,则下标对应LED灯关闭。

void LED_AllClose()//LED关闭数组中,若值为1,则下标对应LED灯关闭{uint8_t i;for(i=1;i<9;i++){if(led_close[i]==1){switch(i){case 1:LED1(OFF);break;case 2:LED2(OFF);break;case 3:LED3(OFF);break;case 4:LED4(OFF);break;case 5:LED5(OFF);break;case 6:LED6(OFF);break;case 7:LED7(OFF);break;case 8:LED8(OFF);break;}}}HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);}

6.Main函数

int main(void){uint8_t i;  /* 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_ADC2_Init();  I2CInit();  MX_TIM6_Init();  /* USER CODE BEGIN 2 */LCD_Init();HAL_ADC_Start(&hadc2);//开启ADC2LCD_Init_Show();//LCD开机界面显示TIM6->SR=0;//中断标志位置0Data_read();//从EEPROM中读取数据for(i=1;i<9;i++)//初始化LED关闭数组{led_close[i]=1;}led_close[led_up]=0;//开启Upper LEDled_close[led_low]=0;//开启Lower LEDLED_AllClose();//其余灯全部关闭  /* USER CODE END 2 */  /* Infinite loop */  /* USER CODE BEGIN WHILE */  while (1)  {    /* USER CODE END WHILE */    /* USER CODE BEGIN 3 */KEY_Scan();//按键扫描v_now=ADC_GetValue();//获取ADC的值if(led_statue==2 ||led_statue==0)//LED状态为闪烁(Upper/Lower){if(lcd_fresh_num>1)//每0.4s刷新一次LCD{lcd_fresh_num=0;LCD_fresh();}}else//LED为常亮{LCD_fresh();}LED_refresh();//LED更新  }  /* USER CODE END 3 */}

四、实验结果

Max==Min bug已修复

五、源码(转载请注明出处)

STM32ADC--基于HAL库(第十届蓝桥杯嵌入式省赛)


总结

以上就是全部内容,如有错误请批评指正。

读书笔记网