过渡模拟二与Led模块
过渡模拟二
设计思路
-
小数点输入
case 11://小数点输入 if(Seg_Disp_Mode == 0 && Point_Flag == 0 && Seg_Input[0] != 11)//处于温度采集界面、标志位为0、输入数组第一位有数据 { Seg_Point[2+Seg_Input_Index] = 1; Point_Wela = Seg_Input_Index;//记录此时指针状态 便于后期数据处理 Point_Flag = 1;//拉高标志位 保证一次输入周期小数点只能使能一次 } break; -
小数点位置(数据显示时候)
Temperature = Seg_Input[0] * 100 + Seg_Input[1] * 10 + Seg_Input[2] + 5; while(3 - Point_Wela) { Temperature /= 10.0; Point_Wela++; } -
长按与短按区分
if(Seg_Disp_Mode == 2)//处于参数设置界面 { if(Key_Down == 14)//S14按下 Time_Flag = 1;//计时开始 } if(Count_500Ms < 500)//短按 { if(Key_Up == 14)//S14抬起 { Time_Flag = Count_500Ms = 0;//状态复位 if(++Parameter[Parameter_Index] > 70)//超过上限值 Parameter[Parameter_Index] = 10; } } else//长按 { if(Key_Old == 14)//S14长按 { if(++Parameter[Parameter_Index] > 70)//超过上限值 Parameter[Parameter_Index] = 10; } if(Key_Up == 14)//S14抬起 Time_Flag = Count_500Ms = 0;//状态复位 }计时器里的操作
if(Time_Flag == 1) { if(++Count_500Ms == 600)//自加到五百毫秒以上就可以限制住 防止一直按下自加的时候数值越界 Count_500Ms = 600; } -
亮度等级
if(Temperature > Parameter_Ctrol[0]) Led_Pwm = 3; else if(Temperature < Parameter_Ctrol[0] && Temperature > Parameter_Ctrol[1]) Led_Pwm = 6; else Led_Pwm = 9;计时器里的操作(周期内的亮度闪烁,周期极短时,肉眼分辨不出来)
if(++Led_Num == 10) Led_Num = 0; if(Led_Num < Led_Pwm) Led_Disp(Led_Pos,ucLed[Led_Pos]); else Led_Disp(Led_Pos,0);总程序
/*头文件声明区域*/ #include <REGX52.H> #include "key.h" #include "Seg.h" #include "Led.h" /*变量声明区域*/ unsigned char Key_Slow_Down;//按键减速专业变量 unsigned int Seg_Slow_Down;//数码管减速专业变量 unsigned char Key_Val,Key_Up,Key_Down,Key_Old;//按键扫描专业变量 unsigned char Seg_Pos;//数码管扫描变量 unsigned char Seg_Buf[6] = {10,10,10,10,10,10};//数码管显示数据存放数组 unsigned char Seg_Point[6] = {0,0,0,0,0,0};//小数点点亮存放数组 unsigned char Led_Pos;//Led扫描变量 unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};//Led点亮存放数组 unsigned char Seg_Mode;//数码管显示模式 0-温度采集界面 1-数据显示界面 2-参数设置界面 unsigned char Seg_Input[3] = {11,11,11};//温度采集数组 unsigned char Seg_Input_Index; unsigned int Timer_500ms;//0.5s unsigned char Point_Wela;//小数点位置变量 unsigned char Parameter[2] = {30,20};//参数设置数组 unsigned char Parameter_Ctrol[2] = {30,20};//参数控制数组 unsigned int Count_500ms;//长按计时变量 unsigned char Led_Num;//Led亮度等级计时变量 unsigned char Led_Pwm;//Led亮度等级 float Temperature;//实际温度数据 bit Seg_Flag;//闪烁标志位 bit Point_Flag;//小数点标志位 0-输入 1-输入完成 bit Parameter_Flag;//参数标志为位 bit Time_Flag;//长按计时标志位 bit Error_Flag;//错误标志位 /*按键处理函数*/ void Key_Proc() { unsigned char i;//循环变量 if(Key_Slow_Down)return; Key_Slow_Down = 1;//按键减速程序 Key_Val = Key_Read();//读取键码值 Key_Down = Key_Val & (Key_Val ^ Key_Old);//检测下降沿 Key_Up = ~Key_Val & (Key_Val ^ Key_Old);//检测上升沿 Key_Old = Key_Val;//扫描辅助沿 if(Key_Down >= 1 && Key_Down <= 10)//0到9输入 { if(Seg_Mode == 0)//温度采集界面 { if(Seg_Input_Index < 3) { Seg_Input[Seg_Input_Index] = Key_Down - 1; Seg_Input_Index++; } } } if(Seg_Mode == 2) { if(Key_Down == 14) Time_Flag = 1;//开始计时 } if(Count_500ms < 500)//短按 { if(Key_Up == 14)//抬起 { Time_Flag = Count_500ms = 0; if(++Parameter[Parameter_Flag] > 70) Parameter[Parameter_Flag] = 10; } } else//长按 { if(Key_Old == 14) { if(++Parameter[Parameter_Flag] > 70) Parameter[Parameter_Flag] = 10; } if(Key_Up == 14) Time_Flag = Count_500ms = 0; } if(Seg_Mode == 2) { if(Key_Down == 15) Time_Flag = 1;//开始计时 } if(Count_500ms < 500)//短按 { if(Key_Up == 15)//抬起 { Time_Flag = Count_500ms = 0; if(--Parameter[Parameter_Flag] == 255) Parameter[Parameter_Flag] = 70; } } else//长按 { if(Key_Old == 15) { if(--Parameter[Parameter_Flag] == 255) Parameter[Parameter_Flag] = 70; } if(Key_Up == 15) Time_Flag = Count_500ms = 0; } switch(Key_Down) { case 11://小数点输入 if(Seg_Mode == 0 && Point_Flag == 0 && Seg_Input[0] != 11)//小数点输入的条件,确保第一位输入 { Seg_Point[2+Seg_Input_Index] = 1;//!!!不是3+Seg_Input_Index Point_Wela = Seg_Input_Index;//记录小数点的位置,方便数据显示 Point_Flag = 1; } break; case 12: if(Seg_Mode != 0)//非温度采集界面 Seg_Mode = (Seg_Mode == 1)?2:1; if(Seg_Mode == 2)//切换到参数设置界面 由1到2 { Parameter_Flag = 0; Parameter[0] = Parameter_Ctrol[0]; Parameter[1] = Parameter_Ctrol[1]; } else//切换到数据显示界面时候 { if(Parameter[0] >= Parameter[1] && Parameter[0] < 70 && Parameter[1] > 10) { Error_Flag = 0; Parameter_Ctrol[0] = Parameter[0]; Parameter_Ctrol[1] = Parameter[1]; } else Error_Flag = 1; } break; case 13: if(Seg_Mode == 2) { Parameter_Flag ^= 1; } break; case 16://进入温度采集界面 if(Seg_Mode != 0)//非温度采集界面 { Seg_Input_Index = 0;//指针复位 Point_Flag = 0;//小数点使能 Seg_Point[3] = Seg_Point[4] = 0;//小数点复位 for(i = 0;i < 3;i++)//数组复位 Seg_Input[i] = 11; } else//处于温度采集界面 { if(Point_Flag == 0 || Seg_Input_Index < 3)//数据无效 { Seg_Input_Index = 0;//指针复位 Point_Flag = 0;//小数点使能 Seg_Point[3] = Seg_Point[4] = 0;//小数点复位 for(i = 0;i < 3;i++)//数组复位 Seg_Input[i] = 11; } else//小数点使能 { Temperature = Seg_Input[0]*100 + Seg_Input[1]*10 + Seg_Input[2] + 5; while(3-Point_Wela)//根据小数点位置,判断数据的大小 { Temperature /= 10.0; Point_Wela++; } if((unsigned int)Temperature > 85)//超出上限 { Seg_Input_Index = 0;//指针复位 Point_Flag = 0;//小数点使能 Seg_Point[3] = Seg_Point[4] = 0;//小数点复位 for(i = 0;i < 3;i++)//数组复位 Seg_Input[i] = 11; } else//数据合理 { Seg_Input_Index = 0;//指针复位 Point_Flag = 0;//小数点使能 Seg_Point[3] = Seg_Point[4] = 0;//小数点复位 Seg_Mode = 1; } } } break; } } /*信息处理函数*/ void Seg_Proc() { if(Seg_Slow_Down)return; Seg_Slow_Down = 1;//按键减速程序 switch(Seg_Mode) { case 0://温度采集界面 Seg_Buf[0] = 12;//A Seg_Buf[1] = Seg_Buf[2] = 10; Seg_Buf[3] = Seg_Input[0]; Seg_Buf[4] = Seg_Input[1]; Seg_Buf[5] = Seg_Input[2]; if(Seg_Buf[5] == 11) Seg_Buf[3+Seg_Input_Index] = Seg_Flag?Seg_Input[Seg_Input_Index]:10; break; case 1: Seg_Buf[0] = 13;//C Seg_Buf[1] = Seg_Buf[2] = Seg_Buf[3] = 10; Seg_Buf[4] = (unsigned char)Temperature / 10; Seg_Buf[5] = (unsigned char)Temperature % 10; if(Seg_Buf[4] == 0)Seg_Buf[4] = 10; break; case 2: Seg_Buf[0] = 14;//P Seg_Buf[1] = 10; Seg_Buf[2] = Parameter[0] / 10; Seg_Buf[3] = Parameter[0] % 10; Seg_Buf[4] = Parameter[1] / 10; Seg_Buf[5] = Parameter[1] % 10; Seg_Buf[2+2*Parameter_Flag] = Seg_Flag?Parameter[Parameter_Flag]/10:10; Seg_Buf[3+2*Parameter_Flag] = Seg_Flag?Parameter[Parameter_Flag]%10:10; break; } } /*其他显示函数*/ void Led_Proc() { if(Temperature > Parameter_Ctrol[0]) Led_Pwm = 3; else if(Temperature < Parameter_Ctrol[0] && Temperature > Parameter_Ctrol[1]) Led_Pwm = 6; else Led_Pwm = 9; ucLed[0] = (int)Temperature/Parameter_Ctrol[0]; ucLed[1] = (!((int)Temperature/Parameter_Ctrol[0])) & ((int)Temperature/Parameter_Ctrol[1]); ucLed[2] = !((int)Temperature/Parameter_Ctrol[1]); ucLed[3] = Error_Flag; } /*定时器0初始化函数*/ void Timer0_Init(void) //1毫秒@12.000MHz { TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0x18; //设置定时初始值 TH0 = 0xFC; //设置定时初始值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; EA = 1; } /*定时器0中断服务函数*/ void Timer0Sever() interrupt 1 { TL0 = 0x18; //设置定时初始值 TH0 = 0xFC; //设置定时初始值 if(++Key_Slow_Down == 10)Key_Slow_Down = 0; if(++Seg_Slow_Down == 10)Seg_Slow_Down = 0; if(++Seg_Pos == 6)Seg_Pos = 0; if(++Led_Pos == 8)Led_Pos = 0; Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]); if(++Timer_500ms == 500) { Timer_500ms = 0; Seg_Flag ^= 1; } if(Time_Flag == 1) { if(++Count_500ms == 600) Count_500ms = 600;//限制最大值,以防超越 } /*亮度等级*/ if(++Led_Num == 10) Led_Num = 0; if(Led_Num < Led_Pwm) Led_Disp(Led_Pos,ucLed[Led_Pos]); else Led_Disp(Led_Pos,0); } /*Main*/ void main() { Timer0_Init(); while(1) { Key_Proc(); Seg_Proc(); Led_Proc(); } }Led模块
译码器控制锁存器的使能端(8421码)
P2_7,P2_6,P2_5控制Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7
P0 = 0xff;
P2 = P2 & 0x1f | 0x80;//先把高三位清0,保持后五位不变,然后再打开锁存器Y4
P2 &= 0x1f;
P0 = 0x00;
P2 = P2 & 0x1f | 0xa0;//先把高三位清0,保持后五位不变,然后再打开锁存器Y5
P2 &= 0x1f;
Led模块
#include "Led.h"
void Led_Disp(unsigned char addr,unsigned char enable)
{
static unsigned char temp = 0x00;
static unsigned char temp_old = 0xff;
if(enable)
temp |= 0x01 << addr;
else
temp &= ~(0x01 << addr);
if(temp != temp_old)
{
P0 = ~temp;
P2 = P2 & 0x1f | 0x80;
P2 &= 0x1f;
temp_old = temp;
}
}