前言
个人认为,比赛前做大量的练习,是非常必要的。我只放了一部分主要代码,思路还是挺清晰的。给大家创造的空间。如果想要源码,最下面也有途径。下面上干货。
一、题目重述
功能描述
二、系统设计分析
思路:题目所给任务,进行逐级分析,分块实现。(下手角度因人而异)
首先,我考虑的是先实现功能三,先实现按键控制功能切换。
在按键切换功能完成的基础上,分别按照题目要求,进完善每个功能。我选择的是先从简单的入手。
程序框架如下:
void KEY_Cmd_Judge(void)
{
key_cmd_flag = KEY_Read();
if(key_cmd_flag == 1)
{
B1_Cmd_Processing(); //按键1://按键 B1 为设置键,按下后进入阈值设置显示界 面,再次按下时保存设置结果到 EEPROM,并返回液位检测显示界面。
}
else if(key_cmd_flag == 2)
{
B2_Cmd_Processing(); //按键2
}
else if(key_cmd_flag == 3)
{
B3_Cmd_Processing(); //按键3
}
else if(key_cmd_flag == 4)
{
B4_Cmd_Processing(); //按键4
}
}
2、按键 B1
实现切换阈值设置显示界面,和将设置阈值存入 EEPROM,并返回液位检测显示界面。
static void B1_Cmd_Processing(void)
{
cmd1_flag++;
//按键 B1 为设置键,按下后进入阈值设置显示界面,
//再次按下时保存设置结果到 EEPROM,并返回液位检测显示界面
if(cmd1_flag%2 == 1)
{
//阈值显示设置界面
Threshold_Display();
}
if(cmd1_flag%2 == 0)
{
EEPROM_Write(); //写入数据
LED_State(7); //状态显示
Liquid_Display();
}
}
2、按键 B2
切换键,切换选择 3 个阈值,被选择的阈值突出显示。
static void B2_Cmd_Processing(void)
{
//按键 B2 为切换键,切换选择 3 个阈值,被选择的阈值突出显示。
//这个在设置阈值的时候,有所体现。
cmd2_flag++;
LCD_SetTextColor(Blue);
Threshold_Display();
if(cmd2_flag == 1)
{
LED_State(4);
High1 = threshold;
}
else if(cmd2_flag == 2)
{
LED_State(5);
High2 = threshold;
}
else if(cmd2_flag == 3)
{
LED_State(6);
High3 = threshold;
}
else if(cmd2_flag == 4)
{
cmd2_flag = 0;
LED_State(8);
}
}
3、按键 B3
阈值加,每按一次,阈值增加 5cm,增加到 95cm 为止。
static void B3_Cmd_Processing(void)
{
threshold += 5;
if(threshold > 95)threshold = 95;//限定一定小于95
if(cmd2_flag == 1)
{
High1 = threshold;
}
else if(cmd2_flag == 2)
{
High2 = threshold;
}
else if(cmd2_flag == 3)
{
High3 = threshold;
}
if(cmd1_flag%2 == 1) Threshold_Display();
}
4、按键 B4
为加键,每按一次,阈值增减 5cm,增加到 5cm 为止。
static void B4_Cmd_Processing(void)
{
threshold -= 5;
if(threshold < 5)threshold = 5; //限定一定大于5
if(cmd2_flag == 1)
{
High1 = threshold;
}
else if(cmd2_flag == 2)
{
High2 = threshold;
}
else if(cmd2_flag == 3)
{
High3 = threshold;
}
if(cmd1_flag%2 == 1) Threshold_Display();
}
5、子函数:一些框架内功能的实现
LED状态显示函数
static void LED_State(uint8_t LED)
{
switch(LED)
{
case 1:
{
LED_Control(LED1,1);
LED_Control(LED2|LED3|LED4|LED5|LED6|LED7,0);
break;
}
case 2:
{
LED_Control(LED2,1);
LED_Control(LED1|LED3|LED4|LED5|LED6|LED7,0);
break;
}
case 3:
{
LED_Control(LED3,1);
LED_Control(LED2|LED1|LED4|LED5|LED6|LED7,0);
break;
}
case 4:
{
LED_Control(LED4,1);
LED_Control(LED2|LED1|LED3|LED5|LED6|LED7,0);
break;
}
case 5:
{
LED_Control(LED5,1);
LED_Control(LED2|LED1|LED3|LED4|LED6|LED7,0);
break;
}
case 6:
{
LED_Control(LED6,1);
LED_Control(LED2|LED1|LED3|LED5|LED4|LED7,0);
break;
}
case 7:
{
LED_Control(LED7,1);
LED_Control(LED2|LED1|LED3|LED5|LED6|LED4,0);
break;
}
case 8:
{
LED_Control(LED2|LED1|LED3|LED5|LED6|LED4|LED7,0);
break;
}
default:
{
break;
}
}
}
液面显示、阈值突出显示功能
void Liquid_Display(void)
{
//正常显示页面信息
LCD_Clear(White);
LCD_SetTextColor(Blue);
VR_37 = (float)ADCConvertedValue*3.3/4096;
High = Get_High(VR_37);
Level = Get_Level(High);
LCD_DisplayStringLine(Line1," Liquid Level ");
sprintf((char*)Txt_Threshold," Height:%dcm ",High);
LCD_DisplayStringLine(Line5,Txt_Threshold);
sprintf((char*)Txt_Threshold," VR37: %1.2fv ",VR_37);
LCD_DisplayStringLine(Line6,Txt_Threshold);
sprintf((char*)Txt_Threshold," Level: %d ",Level);
LCD_DisplayStringLine(Line7,Txt_Threshold);
}
void Threshold_Display(void)
{
//阈值重点显示
LCD_Clear(White);
if((cmd2_flag == 0)||(cmd2_flag == 4))
{
LCD_SetTextColor(Blue);
LCD_DisplayStringLine(Line1," Threshold Setup ");
sprintf((char*)Txt_Threshold," Threshold1: %2dcm ",High1);
LCD_DisplayStringLine(Line5,Txt_Threshold);
sprintf((char*)Txt_Threshold," Threshold2: %2dcm ",High2);
LCD_DisplayStringLine(Line6,Txt_Threshold);
sprintf((char*)Txt_Threshold," Threshold3: %2dcm ",High3);
LCD_DisplayStringLine(Line7,Txt_Threshold);
}
else if(cmd2_flag == 1)
{
LCD_SetTextColor(Blue);
sprintf((char*)Txt_Threshold," threshold: %2dcm ",threshold);
LCD_DisplayStringLine(Line9,Txt_Threshold);
LCD_DisplayStringLine(Line1," Threshold Setup ");
LCD_SetTextColor(Red);
sprintf((char*)Txt_Threshold," Threshold1: %2dcm ",High1);
LCD_DisplayStringLine(Line5,Txt_Threshold);
LCD_SetTextColor(Blue);
sprintf((char*)Txt_Threshold," Threshold2: %2dcm ",High2);
LCD_DisplayStringLine(Line6,Txt_Threshold);
sprintf((char*)Txt_Threshold," Threshold3: %2dcm ",High3);
LCD_DisplayStringLine(Line7,Txt_Threshold);
}
else if(cmd2_flag == 2)
{
LCD_SetTextColor(Blue);
sprintf((char*)Txt_Threshold," threshold: %2dcm ",threshold);
LCD_DisplayStringLine(Line9,Txt_Threshold);
LCD_DisplayStringLine(Line1," Threshold Setup ");
sprintf((char*)Txt_Threshold," Threshold1: %2dcm ",High1);
LCD_DisplayStringLine(Line5,Txt_Threshold);
LCD_SetTextColor(Red);
sprintf((char*)Txt_Threshold," Threshold2: %2dcm ",High2);
LCD_DisplayStringLine(Line6,Txt_Threshold);
LCD_SetTextColor(Blue);
sprintf((char*)Txt_Threshold," Threshold3: %2dcm ",High3);
LCD_DisplayStringLine(Line7,Txt_Threshold);
}
else if(cmd2_flag == 3)
{
LCD_SetTextColor(Blue);
sprintf((char*)Txt_Threshold," threshold: %2dcm ",threshold);
LCD_DisplayStringLine(Line9,Txt_Threshold);
LCD_DisplayStringLine(Line1," Threshold Setup ");
sprintf((char*)Txt_Threshold," Threshold1: %2dcm ",High1);
LCD_DisplayStringLine(Line5,Txt_Threshold);
sprintf((char*)Txt_Threshold," Threshold2: %2dcm ",High2);
LCD_DisplayStringLine(Line6,Txt_Threshold);
LCD_SetTextColor(Red);
sprintf((char*)Txt_Threshold," Threshold3: %2dcm ",High3);
LCD_DisplayStringLine(Line7,Txt_Threshold);
}
}
液面高度转换,Level判断,EEPROM存储
float Get_High(float V) //获取页面高度
{
return (V/3.3)*100;
}
static uint8_t Get_Level(uint16_t H) //获取页面高度
{
uint8_t L_temp = 0;
if(H<=High1)
{
L_temp = 1;
}
else if((H > High1) && (H <= High2))
{
L_temp =2;
}
else if((H > High2) && (H <= High3))
{
L_temp =3;
}
else if(H>High3)
{
L_temp = 4;
}
return L_temp;
}
void EEPROM_Read(void)
{
//存储EEPROM数据 选前三个内存地址 存入 easy
High1 = Byte_Read(0x00);
High2 = Byte_Read(0x02); //需要加延时么? 待测
High3 = Byte_Read(0x04);
}
void EEPROM_Write(void)
{
//存储EEPROM数据 选前三个内存地址 存入 easy
Byte_Write(0x00,High1);
Delay_Soft(0xffff);
Byte_Write(0x02,High2); //需要加延时时间 自行调试
Delay_Soft(0xffff);
Byte_Write(0x04,High3);
}
到此前三个任务已经完成
下面功能4:
串口查询与输出功能:中断实现
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART_PORT, USART_IT_RXNE) != RESET)
{
Usart_temp = getchar();
Usart_flag = 1;
if(Usart_temp == 'C')
{
printf("C:\n High:%d Level:%d\r\n",High,Level);
}
if(Usart_temp == 'S')
{
printf("S:\n Threshold1:%d cm\n Threshold2:%d cm\n Threshold3:%d cm\n\r\n\n",High1,High2,High3);
}
}
USART_ClearITPendingBit(USART_PORT,USART_IT_RXNE);
}
功能5
状态显示
void SysTick_Handler(void)
{
Time_Handler_Display++;
Time_Handler_LED2++;
Time_Handler_LED3++;
if(Time_Handler_Display == Liquid_Display_Time)
{
Time_Handler_Display = 0;
if(cmd1_flag%2 == 0)
{
LED_Toggle(1);
Liquid_Display();
}
}
if(Time_Handler_LED2 == LED2_Toggle_Time) //不用每次都判断 0.2s判断一次就够了
{
Time_Handler_LED2 = 0;
if(Level != Level_temp)
{
LED_Toggle(2);
Level_temp_i++;
Level_Change();
}
}
if(Time_Handler_LED3 == LED3_Toggle_Time) //不用每次都判断 0.2s判断一次就够了
{
Time_Handler_LED3 = 0;
if(Usart_flag == 1)
{
LED_Toggle(3);
Usart_i++;
if(Usart_i == 10)
{
Usart_flag = 0;
Usart_i = 0;
}
}
}
if(TimeDelay_Ms != 0)
{
TimeDelay_Ms--;
}
}
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART_PORT, USART_IT_RXNE) != RESET)
{
Usart_temp = getchar();
Usart_flag = 1;
if(Usart_temp == 'C')
{
printf("C_cmd:\n High:%d Level:%d\r\n",High,Level);
}
if(Usart_temp == 'S')
{
printf("S_cmd:\n Threshold1:%d cm\n Threshold2:%d cm\n Threshold3:%d cm\n\r\n\n",High1,High2,High3);
}
}
USART_ClearITPendingBit(USART_PORT,USART_IT_RXNE);
}
main.c
int main(void)
{
ALL_Init();
while(1)
{
KEY_Cmd_Judge();
}
}
三、测试
led也是按照预期闪烁
四、总结:
主要用到的模块:ADC、EEPROM、USART、GPIO、Systick、LCD、KEY.
先整体搭建程序框架、逐步完善。关于LCD的显示倒没什么,主要是中间有一些细节,什么时候显示什么界面,需要底层判断,然后判断flag,然后就是ADC和串口的配置,需要熟练掌握。EEPROM注意在写入的时候,加延时,否则会出错。
工程源码:
私信即可