目录
前言
本次的记录是第七届蓝桥杯省赛程序设计题
一、题目介绍
二、模块实现
1.key+定时器
在本次的题目中,除了按键消抖用到一个定时器外,还有测量R37的输出电压,三个LED灯这两个地方需要定时来操作。为了减少定时器的数目,所以我这里只定时了一个0.2秒的定时器,题目中的一秒就采用了计数的方式来实现,也不用一会儿开启一会儿关闭。
/**********************************回调函数**********************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
keys[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
keys[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for (int i=0;i<4;i++)
{
switch(keys[i].key_pro)
{
case 0:
if(keys[i].key_sta==0)
keys[i].key_pro=1;
break;
case 1:
if(keys[i].key_sta==0)
keys[i].key_pro=2;
else
keys[i].key_pro=0;
break;
case 2:
if(keys[i].key_sta==1)
{
keys[i].key_pro=0;
keys[i].key_flg=1;
}
break;
}
}
}
if(htim->Instance==TIM3)
{
Invoid_Complict();
count++;
//间隔一秒测量R37输出电压
if(count%5==0)
{
Get_adc();
level_confirm();
}
//运行状态下间隔一秒LED1亮灭闪烁
if(count%5==0 && menu%2==0)
{
led1_sta^=1;
Control_Single_Led(0x01,led1_sta);
}
else if(menu%2)
{
Control_Single_Led(0x01,1);
led1_sta=1;
}
//液位等级变化下LED2间隔0.2秒闪烁5次
if(level_flg==1)
{
if(shrink_count_led2==10)
{
Control_Single_Led(0x02,1);
led2_sta=1;
level_flg=0;
shrink_count_led2=0;
}
else
{
led2_sta^=1;
Control_Single_Led(0x02,led2_sta);
shrink_count_led2++;
}
}
//通讯状态下LED3间隔0.2秒闪烁5次
if(check_flg==1)
{
if(shrink_count_led3==10)
{
Control_Single_Led(0x04,1);
led3_sta=1;
check_flg=0;
shrink_count_led3=0;
}
else
{
led3_sta^=1;
Control_Single_Led(0x04,led3_sta);
shrink_count_led3++;
}
}
}
}
/***************************************按键功能实现***********************/
void Key_Function()
{
//显示界面切换
if(keys[0].key_flg==1)
{
menu++;
keys[0].key_flg=0;
}
//切换阈值修改处
if(menu%2==1 && keys[1].key_flg==1)
{
change_thre++;
Display_lcd();
keys[1].key_flg=0;
}
//阈值增加
if(menu%2==1 && keys[2].key_flg==1)
{
if(threshold[change_thre%3]!=95)
{
threshold[change_thre%3]+=5;
eeprom_update_thres();
}
keys[2].key_flg=0;
}
//阈值减少
if(menu%2==1 && keys[3].key_flg==1)
{
if(threshold[change_thre%3]!=5)
{
threshold[change_thre%3]-=5;
eeprom_update_thres();
}
keys[3].key_flg=0;
}
Display_lcd();
Display_led();
}
2.LED+LCD
这里的需要注意的就是选择修改的阈值处时需要加上高亮,其余的都是和前面的一样
//定义外部变量
extern uint8_t threshold[3];//初始阈值
extern char str[30];
extern float height;//液位高度,R37输出电压
extern float v_37;
extern uint8_t level;//液位等级
extern int8_t change_thre; //阈值改变处
extern uint8_t menu,level_flg,check_flg,level_before;
extern uint8_t led1_sta,led2_sta,led3_sta;//LED1,LED2,LED3的电平状态
extern uint8_t shrink_count_led2,shrink_count_led3;
extern TIM_HandleTypeDef htim4,htim3;
/****************************LED显示****************************/
void led_init()
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void Control_Single_Led(unsigned char location,unsigned char value)
{
HAL_GPIO_WritePin(GPIOC,location<<8,value);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void Invoid_Complict()
{
HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void Display_led()
{
Invoid_Complict();
//运行状态指示灯--LED1
if(menu%2==0)
{
led1_sta^=1;
Control_Single_Led(0x01,led1_sta);
}
//液位等级变化指示灯--LED2
if(level_flg==1)
{
led2_sta^=1;
Control_Single_Led(0x02,led2_sta);
}
//通讯状态指示灯--LED3
if(check_flg==1)
{
led3_sta^=1;
Control_Single_Led(0x04,led3_sta);
}
}
/****************************LCD显示****************************/
void LCD_Check()
{
level_confirm();
sprintf(str," Liquid Level ");
LCD_DisplayStringLine(Line1,(u8*)str);
sprintf(str," Height:%.1f ",height);
LCD_DisplayStringLine(Line2,(u8*)str);
sprintf(str," ADC:%.2f ",v_37);
LCD_DisplayStringLine(Line3,(u8*)str);
sprintf(str," Level:%d ",level);
LCD_DisplayStringLine(Line4,(u8*)str);
}
void LCD_Setting()
{
sprintf(str," Parameter Setup ");
LCD_DisplayStringLine(Line1,(u8*)str);
if(change_thre%3==0)
{
sprintf(str," Threshold1:%d ",threshold[0]);
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line2,(u8*)str);
LCD_SetBackColor(Black);
sprintf(str," Threshold2:%d ",threshold[1]);
LCD_DisplayStringLine(Line3,(u8*)str);
sprintf(str," Threshold3:%d ",threshold[2]);
LCD_DisplayStringLine(Line4,(u8*)str);
}
else if(change_thre%3==1)
{
sprintf(str," Threshold1:%d ",threshold[0]);
LCD_DisplayStringLine(Line2,(u8*)str);
sprintf(str," Threshold2:%d ",threshold[1]);
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line3,(u8*)str);
LCD_SetBackColor(Black);
sprintf(str," Threshold3:%d ",threshold[2]);
LCD_DisplayStringLine(Line4,(u8*)str);
}
else
{
sprintf(str," Threshold1:%d ",threshold[0]);
LCD_DisplayStringLine(Line2,(u8*)str);
sprintf(str," Threshold2:%d ",threshold[1]);
LCD_DisplayStringLine(Line3,(u8*)str);
sprintf(str," Threshold3:%d ",threshold[2]);
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line4,(u8*)str);
LCD_SetBackColor(Black);
}
}
void Display_lcd()
{
eeprom_get_thres();
if(menu%2==0)
LCD_Check();
else
LCD_Setting();
}
3.USART+eeprom+ADC
/***********************************串口通信****************************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)
{
RXbuff[BufIndex++]=Rxdat;
HAL_UART_Receive_IT(&huart1,&Rxdat,1);
}
}
void Deal_Infromation()
{
if(BufIndex==0)
return ;
if(RXbuff[0]=='C' )
{
sprintf(str,"C:H%.1f+L%d\r\n",height,level);
HAL_UART_Transmit(&huart1,(u8*)str,sizeof(str),50);
check_flg=1;
}
else if(RXbuff[0]=='S')
{
sprintf(str,"S:TL%d+TM%d+TH%d\r\n",threshold[0],threshold[1],threshold[2]);
HAL_UART_Transmit(&huart1,(u8*)str,sizeof(str),50);
check_flg=1;
}
else
{
sprintf(str,"INPUT ERROR\r\n");
HAL_UART_Transmit(&huart1,(u8*)str,sizeof(str),50);
}
BufIndex=0;
}
/**********************************EEPROM*************************************/
void eeprom_update_thres()
{
//第一次上电
if(thres_init==0)
{
uint8_t thre1,thre2,thre3;
thre1=20; thre2=40; thre3=60;
Eeprom_Write_Bytes(0x10,&thre1,1);
HAL_Delay(10);
Eeprom_Write_Bytes(0x11,&thre2,1);
HAL_Delay(10);
Eeprom_Write_Bytes(0xa0,&thre3,1);
HAL_Delay(10);
thres_init=1;
}
else
{
Eeprom_Write_Bytes(0x10,&threshold[0],1);
HAL_Delay(10);
Eeprom_Write_Bytes(0x11,&threshold[1],1);
HAL_Delay(10);
Eeprom_Write_Bytes(0xa0,&threshold[2],1);
HAL_Delay(10);
}
}
void eeprom_get_thres()
{
Eeprom_Read_Bytes(0x10,&threshold[0],1);
HAL_Delay(10);
Eeprom_Read_Bytes(0x11,&threshold[1],1);
HAL_Delay(10);
Eeprom_Read_Bytes(0xa0,&threshold[2],1);
HAL_Delay(10);
}
/*********************************ADC*********************************/
void Get_adc()
{
int adc;
HAL_ADC_Start(&hadc2);
adc=HAL_ADC_GetValue(&hadc2);
HAL_ADC_Stop(&hadc2);
v_37=adc*3.3/4096;
}
4.其他函数
这里液位等级判定我单独搞了一个函数,因为这里需要处理的仔细一点,避免LED2一直闪烁
//液位等级判定
void level_confirm()
{
height=v_37*(100/3.3);
level_before=level;
if(height<=threshold[0])
level=0;
else if(height>threshold[0] && height<=threshold[1])
level=1;
else if(height>threshold[1] && height<=threshold[2])
level=2;
else
level=3;
char str1[20];
if(level>level_before)
{
sprintf(str1,"A:H%.1f+L%d+U\r\n",height,level);
HAL_UART_Transmit(&huart1,(u8*)str1,sizeof(str1),50);
}
else if(level<level_before)
{
sprintf(str1,"A:H%.1f+L%d+D\r\n",height,level);
HAL_UART_Transmit(&huart1,(u8*)str1,sizeof(str1),50);
}
if( level_flg==0 && level!=level_before)
{
level_flg=1;
//避免指示灯多次闪烁
level_before=level;
}
}
总结
本次的记录到这就结束,希望在记录的过程中可以对在看这篇文章有些帮助。博主的蓝桥杯系统文章也可以瞧瞧哦
系列文章目录
第六届省赛
第十届省赛
第十一届省赛
第十三届省赛第一场
第十三届省赛第二场
第十四届省赛
第十五届模拟赛加部分更新