出租车计价器的设计
设计内容与要求:
(1) 里程显示为:***.**
(2)能预置起步价与单价:如起步3 公里 6.00元; 1.60.公里。(可通过按键产生公里数,如每按一次为0.1公里,里程数和价格都用数码管显示)
采用矩阵键盘实现
#include<reg51.h>
#define GPIO_DIG P0
#define GPIO_KEY P1
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
unsigned char KeyValue;
//用来存放读取到的键值
typedef unsigned char u8;
typedef unsigned int u16;
u8 KeyState; //记录按键的状态,0没有,1有
u8 DisplayData[8]; //用来存放要显示的8位数的值
u8 priceFlag; //设置价格的判断
u8 initPriceFlag; //设置起步价的判断
u16 price, initPrice;//单价,起步价
u16 tempPrice; //中间变量,为了处理小数点准备的
u16 money; //价钱
u16 keyNum; //里程
//常规延时
void Delay(i) //延时
{
while(i--);
}
//延时10ms
void Delay10ms() //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}
//数码管的显示
void DigDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i)
{
case 0:LSA=0;LSB=0;LSC=0; break;
case 1:LSA=1;LSB=0;LSC=0; break;
case 2:LSA=0;LSB=1;LSC=0; break;
case 3:LSA=1;LSB=1;LSC=0; break;
case 4:LSA=0;LSB=0;LSC=1; break;
case 5:LSA=1;LSB=0;LSC=1; break;
case 6:LSA=0;LSB=1;LSC=1; break;
case 7:LSA=1;LSB=1;LSC=1; break;
}
GPIO_DIG=DisplayData[i];
Delay(100);
GPIO_DIG=0x00;//消隐
}
}
//按键扫描
void KeyDown()
{
u16 a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)
{
Delay(1000);
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)
{
KeyState=1;//有按键按下
//测试列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}
//测试行
GPIO_KEY=0XF0;
Delay10ms();
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
while((a<50)&&(GPIO_KEY!=0xf0)) //按键松手检测
{
Delay10ms();
a++;
}
}
}
}
void initTwo()
{
u8 i;
for(i=0;i<8;i++)
DisplayData[i]=0x00;
}
void init()
{
initTwo();
price=0;
initPrice=0;
money=0;
keyNum=0;
}
//输入流动的数据
void setDate()
{
tempPrice=tempPrice*10;
tempPrice=tempPrice+KeyValue;
DisplayData[3]=DisplayData[2];
DisplayData[2]=DisplayData[1];
DisplayData[1]=DisplayData[0];
DisplayData[0]=smgduan[KeyValue];
}
//小数点的处理
void decimalPoint()
{
DisplayData[0]=DisplayData[0]|0x80;
if(priceFlag) price=tempPrice*100;
if(initPriceFlag) initPrice=tempPrice*100;
tempPrice=0;
}
//确认键
void sureKey()
{
if(priceFlag) price=tempPrice+price;
if(initPriceFlag) initPrice=tempPrice+initPrice;
initPriceFlag=0;
priceFlag=0;
tempPrice=0;
}
u16 tempNum;
void datapros()
{
tempPrice=initPrice;
tempNum=keyNum;
if(keyNum <= 30){
DisplayData[0]=smgduan[tempPrice%10];
tempPrice=tempPrice/10;
DisplayData[1]=smgduan[tempPrice%10];
tempPrice=tempPrice/10;
DisplayData[2]=smgduan[tempPrice%10]|0x80;
tempPrice=tempPrice/10;
DisplayData[3]=smgduan[tempPrice%10];
}else{
money=keyNum-30;
money=money*price;
money=money/10;
money=money+initPrice;
DisplayData[0]=smgduan[money % 10];
money = money / 10;
DisplayData[1]=smgduan[money % 10];
money = money / 10;
DisplayData[2]=smgduan[money % 10]|0x80;
money = money / 10;
if(money)
{
DisplayData[3]=smgduan[money % 10];
}
}
DisplayData[4]=smgduan[tempNum%10];
tempNum = tempNum / 10;
DisplayData[5]=smgduan[tempNum%10]|0x80;
tempNum = tempNum / 10;
if(tempNum) DisplayData[6]=smgduan[tempNum%10];
tempNum = tempNum / 10;
if(tempNum) DisplayData[7]=smgduan[tempNum%10];
}
void main(void)
{
KeyState=0;
while(1)
{
KeyDown();
if(KeyState==1)
{
switch(KeyValue)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
if(initPriceFlag || priceFlag) setDate();
break;
case 10: initPriceFlag=1; //S11
priceFlag=0;
break;//选择设置起步价
case 11: priceFlag=1; //选额设置价格 S12
initPriceFlag=0;
break;
case 12: sureKey();//确认按键 S13
initTwo();
break;
case 13: decimalPoint(); //S14
break; //小数点按键处理
case 14: init(); break; //复位 S15
case 15: keyNum++; //里程设置
datapros();
break;
}
KeyState=0;
}
DigDisplay();
}
}
版本二
#include<reg51.h>
#define GPIO_DIG P0
#define GPIO_KEY P1
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
unsigned char KeyValue;
//用来存放读取到的键值
typedef unsigned char u8;
typedef unsigned int u16;
u8 KeyState; //记录按键的状态,0没有,1有
u8 DisplayData[8]; //用来存放要显示的8位数的值
u8 priceFlag; //设置价格的判断
u8 initPriceFlag; //设置起步价的判断
u8 cadFlag;
u16 price, initPrice;//单价,起步价
u16 tempPrice; //中间变量,为了处理小数点准备的
u16 money; //价钱
u16 keyNum; //里程
//常规延时
void Delay(i) //延时
{
while(i--);
}
//延时10ms
void Delay10ms() //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}
//数码管的显示
void DigDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i)
{
case 0:LSA=0;LSB=0;LSC=0; break;
case 1:LSA=1;LSB=0;LSC=0; break;
case 2:LSA=0;LSB=1;LSC=0; break;
case 3:LSA=1;LSB=1;LSC=0; break;
case 4:LSA=0;LSB=0;LSC=1; break;
case 5:LSA=1;LSB=0;LSC=1; break;
case 6:LSA=0;LSB=1;LSC=1; break;
case 7:LSA=1;LSB=1;LSC=1; break;
}
GPIO_DIG=DisplayData[i];
Delay(100);
GPIO_DIG=0x00;//消隐
}
}
//按键扫描
void KeyDown()
{
u16 a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)
{
Delay(1000);
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)
{
KeyState=1;//有按键按下
//测试列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}
//测试行
GPIO_KEY=0XF0;
Delay10ms();
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
while((a<50)&&(GPIO_KEY!=0xf0)) //按键松手检测
{
Delay10ms();
a++;
}
}
}
}
void initOne()
{
u8 i;
for(i=0;i<4;i++)
DisplayData[i]=smgduan[0];
}
void init()
{
price=0;
initPrice=0;
money=0;
keyNum=0;
}
void setRad()
{
u8 i;
for(i=0;i<8;i++)
DisplayData[i]=0x00;
}
//输入流动的数据
void setDate()
{
tempPrice=tempPrice*10;
tempPrice=tempPrice+KeyValue;
DisplayData[3]=DisplayData[2];
DisplayData[2]=DisplayData[1];
DisplayData[1]=DisplayData[0];
DisplayData[0]=smgduan[KeyValue];
}
//小数点的处理
void decimalPoint()
{
DisplayData[0]=DisplayData[0]|0x80;
if(priceFlag) price=tempPrice*100;
if(initPriceFlag) initPrice=tempPrice*100;
tempPrice=0;
}
//确认键
void sureKey()
{
if(priceFlag) price=tempPrice+price;
if(initPriceFlag) initPrice=tempPrice+initPrice;
initPriceFlag=0;
priceFlag=0;
tempPrice=0;
}
u16 tempNum;
void datapros()
{
tempPrice=initPrice;
tempNum=keyNum;
if(keyNum <= 30){
DisplayData[0]=smgduan[tempPrice%10];
tempPrice=tempPrice/10;
DisplayData[1]=smgduan[tempPrice%10];
tempPrice=tempPrice/10;
DisplayData[2]=smgduan[tempPrice%10]|0x80;
tempPrice=tempPrice/10;
if(tempPrice) DisplayData[3]=smgduan[tempPrice%10];
}else{
money=keyNum-30;
money=money*price;
money=money/10;
money=money+initPrice;
DisplayData[0]=smgduan[money % 10];
money = money / 10;
DisplayData[1]=smgduan[money % 10];
money = money / 10;
DisplayData[2]=smgduan[money % 10]|0x80;
money = money / 10;
if(money)
{
DisplayData[3]=smgduan[money % 10];
}
}
DisplayData[4]=smgduan[tempNum%10];
tempNum = tempNum / 10;
DisplayData[5]=smgduan[tempNum%10]|0x80;
tempNum = tempNum / 10;
if(tempNum) DisplayData[6]=smgduan[tempNum%10];
tempNum = tempNum / 10;
if(tempNum) DisplayData[7]=smgduan[tempNum%10];
}
void main(void)
{
KeyState=0;
while(1)
{
KeyDown();
if(KeyState==1)
{
switch(KeyValue)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
if(cadFlag)
{
cadFlag=0;
setRad();
}
if(initPriceFlag || priceFlag) setDate();
break;
case 10: initPriceFlag=1; //S11
priceFlag=0;
initOne();
cadFlag=1;
break;//选择设置起步价
case 11: priceFlag=1; //选额设置价格 S12
initPriceFlag=0;
initOne();
cadFlag=1;
break;
case 12: sureKey();//确认按键 S13
break;
case 13: decimalPoint(); //S14
break; //小数点按键处理
case 14: init();
setRad();
break; //复位 S15
case 15: keyNum++; //里程设置
datapros();
break;
}
KeyState=0;
}
DigDisplay();
}
}
0 | 1 | 2 | 3 |
4 | 5 | 6 | 7 |
8 | 9 | 起步价 | 单价 |
确定 | 小数点 | 复位 | 里程 |