成果展示视频:【【Let's do第四期】DIY液体流量检测仪-项目展示】 https://www.bilibili.com/video/BV1wJfZYpEsj/?vd_source=1b092d899318d2ac63cda1ed6ce04937
EETV成果视频链接:https://v.eepw.com.cn/video/play/id/16227
本期给大家分享一下我的制作成果。
液体流量监测仪:
按键双击快速控制水泵开关;
按键长按 选择开关状态,或者选择定量值设定,任意值可设,由于精度差异,设定步进值为50ml;
总流量累计;
功能模块设计调试:
搭建keil环境;
OLED 显示。
继电器控制抽水泵通断。
实现流量计测量功能。
实现定量 任意 水量控制。
KEY_FLAG Key_s; //声明一个按键结构体变量
/*=========================== 单击 双击 长按 =============================*/
void key_det_1(void)
{
Key_s.key_1 = (~Buttons_GetState()) & (1 << 0);
// printf ("%d\\n\\r",Key_s.key_1);
if(Key_s.key_flag_1 == 1) //单击
{
Key_s.key_flag_1 = 0;
Key_s.key_resault = 1;
}
else if(Key_s.key_flag_1 == 2) //长按
{
Key_s.key_flag_1 = 0;
Key_s.key_resault = 2;
}
else if(Key_s.key_flag_1 == 3)//双击
{
Key_s.key_flag_1 = 0;
Key_s.key_resault = 3;
}
switch(Key_s.key_state)
{
case 0:
if(Key_s.key_1 == 0) //按下
{
if(++Key_s.key_cnt_1 > 5) //主循环进来一次 作用:按下消抖
{
Key_s.key_cnt_1 = 0;
Key_s.key_state = 1;
}
}
else
{
Key_s.key_cnt_1 = 0;
}
break;
case 1:
if(Key_s.key_1 == 1) //松开
{
Key_s.key_cnt_1 = 0;
Key_s.key_state = 2;
return;
}
if(++Key_s.key_cnt_1 >= 200)
{
Key_s.key_cnt_1 = 0;
Key_s.key_state = 3;
Key_s.key_flag_1 = 2; //长按事件
return;
}
break;
case 2:
if(Key_s.key_1 == 0) //按下
{
Key_s.key_cnt_1 = 0;
Key_s.key_state = 3;
Key_s.key_flag_1 = 3; //双击判断
return;
}
if(++Key_s.key_cnt_1 >= 40) // 计时超过400ms判断为单击事件
{
Key_s.key_cnt_1 = 0;
Key_s.key_flag_1 = 1; //单击事件
Key_s.key_state = 3;
return;
}
break;
case 3:
if(Key_s.key_1 == 1) //松开
{
Key_s.key_state = 0;
}
break;
default:
Key_s.key_state = 0;
}
Key_s.key_flag_1 = 0;
}void UI_Disply(void)
{
switch(StrFlow.step)
{
case 0:
OLED_ShowChinese(16*0,16+5,0,16,1);
OLED_ShowChinese(16*1,16+5,1,16,1);
OLED_ShowChinese(16*2,16+5,2,16,1);
OLED_ShowChinese(16*3,16+5,3,16,1);
OLED_ShowChinese(16*4,16+5,4,16,1);
OLED_ShowChinese(16*5,16+5,5,16,1);
OLED_ShowChinese(16*6,16+5,6,16,1);
OLED_ShowChinese(16*7,16+5,7,16,1);
StrFlow.step = 1;
OLED_Refresh();
delay_ms(2000);
OLED_Clear();
break;
case 1:
OLED_ShowChinese(16*0,16*0,8,16,1);
OLED_ShowChinese(16*1,16*0,4,16,1); OLED_ShowChar(16*2 ,16*0,':',16,1);
OLED_ShowChinese(16*0,16*1+5*1,2,16,1);
OLED_ShowChinese(16*1,16*1+5*1,3,16,1); OLED_ShowChar(16*2 ,16*1+5*1,':',16,1);
OLED_ShowChinese(16*0,16*2+5*2,2,16,1);
OLED_ShowChinese(16*1,16*2+5*2,4,16,1); OLED_ShowChar(16*2 ,16*2+5*2,':',16,1);
OLED_ShowNum(OLED_X_I ,16*0 ,StrFlow.SetmL,5,16,1);
OLED_ShowNum(OLED_X_I ,16*1+5*1,StrFlow.QmL,5,16,1);
OLED_ShowNum(OLED_X_I ,16*2+5*2,StrFlow.TotalmL*1,5,16,1);//0.
OLED_ShowString(16*5+5,16*0, "ml", 16,1);
OLED_ShowString(16*5+5,16*1+5*1,"ml/S",16,1);
OLED_ShowString(16*5+5,16*2+5*2,"ml", 16,1);
if(!StrFlow.Ctr_Relay)
{
OLED_ShowString(128-25,16*0, "OFF",16,1);
}
else
{
OLED_ShowString(128-25,16*0, "ON ",16,1);
}
StrFlow.step = 0xFF;
break;
default:
OLED_ShowNum(OLED_X_I ,16*1+5*1,StrFlow.QmL,5,16,1);
OLED_ShowNum(OLED_X_I ,16*2+5*2,StrFlow.TotalmL,5,16,1);
switch(Key_s.key_resault)
{
case CLICK_DOUBLE:
(StrFlow.Ctr_Relay == 0)?(StrFlow.Ctr_Relay = 1):(StrFlow.Ctr_Relay = 0);
if(!StrFlow.Ctr_Relay)
{
GPIO_PinWrite (GPIOA, 8, Switch_Relay(false));
}
else
{
FlowSetup();
GPIO_PinWrite (GPIOA, 8, Switch_Relay(true));
}
break;
case CLICK_LONG:
switch(GetCursor)
{
case 0:
GetCursor = 1;
if(!StrFlow.Ctr_Relay)
{
Switch_Relay(false);
}
else if(1==StrFlow.Ctr_Relay)
{
Switch_Relay(true);
}
break;
case 1:
GetCursor = 2;
OLED_ShowNum(OLED_X_I ,16*0 ,StrFlow.SetmL,5,16,0);
break;
default:
if(StrFlow.SetmL>10 && StrFlow.Ctr_Relay==1)
{
GPIO_PinWrite (GPIOA, 8, Switch_Relay(true));
}
break;
}
break;
case CLICK:
switch(GetCursor)
{
case 1:
(StrFlow.Ctr_Relay == 0)?(StrFlow.Ctr_Relay = 1):(StrFlow.Ctr_Relay = 0);
if(!StrFlow.Ctr_Relay)
{
OLED_ShowString(128-25,16*0, "OFF",16,1);
}
else
{
OLED_ShowString(128-25,16*0, "ON ",16,1);
}
GetCursor = 2;
break;
case 2:
OLED_ShowNum(OLED_X_I ,16*0 ,StrFlow.SetmL+=50,5,16,0);
break;
}
break;
}
Key_s.key_resault = 0;
break;
}
}以上就是主要代码和实现功能的方式,很高兴您能看到这里。 希望可以帮助你。
由于没有多少事件细化代码,代码比较乱,就不开源了,如果群友们有要求,那我就抽时间整理后再开源。
在这里先感谢DigiKey联合EEPW举办的此次活动,不仅有老师在线讲解还有众多群友的帮助完成任务。期待下一次的活动。
我要赚赏金
