51 microcontroller programming - simple pedometer taxi

Written at the beginning: first because the program files are uploaded, there is some commented content is entirely independent of the program is useless when I originally wrote the part of the program, can be ignored, there are some other variables did not write indicate the specific role only see the program more difficult to understand, I have to explain at the time of this writing, we can then look here.

Taxi pedometer is a simple requirement:

(1)LED数码管或LCD显示路程和价格,价格单位为元,小数点后保留1位;路程单位为km,小数点后保留1位;
(2)起步价6.0元,3km;3km以后按1.2元/km计费;
(3)其他功能(创新部分),如显示时间、温湿度等;
(4)系统调试、分析、总结与功能实现。

The program I use Mistakes in An microcontroller 51, only the resources that the development board, not connected to any peripherals, made out of things quite simple, uses six digital tube on the microcontroller.

First, the design ideas

Mistakes in An microcontroller 51 is connected to P3.7 to P3.4 are independent keyboard s1 to s4, this procedure is only used s1, six are digital uses. The top three digital tube display away after three price displayed. From the initial value of 0.0, every time the distance s1 plus 0.5 Km. Is a segment from the relationship between price and function, from <3.0, the price is always equal to 6.0; from> greater than 3.0, the price is always equal to (from -3) * 1.2 + 6.0.
Wps done with the program made a flow chart, as follows:
Here Insert Picture Description
The following are a few renderings, is cut from the video was shot in the map, I now there are not 51 Mistakes in An MCU can only be used before the shot.
Here Insert Picture Description
1, from the initial value
Here Insert Picture Description
after 2, press the key three times, from 1.5, still price. 6
Here Insert Picture Description
3, seven button press, from 3.5 rate is 12.0 (= 3 + 0.5 12.0 * 1.2)

Second, the role of the program brief description, the header file, a function declaration, segment selection, bit selection, key use I / O port is defined, the global variable definition

The first to use macro definitions:

	#define uchar unsigned char
	#define uint unsigned int

After the program can reduce the burden, generally written microcontroller program is to be written on at the beginning.
P3.4 to P3.7 are then defined as separate keyboard s1 to s4, wherein only used s1, where appropriate, may be used when you want to add additional functions of the remaining three keys.

	sbit s1=P3^4;	 //定义P34口是s1
	sbit s2=P3^5;	 //定义P35口是s2
	sbit s3=P3^6;	 //定义P36口是s3
	sbit s4=P3^7;	 //定义P37口是s4

It defines an array of three LED display used:

uchar code table1[]={0x3f,0x06,0x5b,0x4f,
					 0x66,0x6d,0x7d,0x07,
				     0x7f,0x6f,0x77,0x7c,
			 	 	 0x39,0x5e,0x79,0x71};

The first array is displayed from 0 to F, of course, only be used where the 0 to 9

	uchar code table2[]={0xbf,0x86,0xdb,0xcf,
						 0xe6,0xed,0xfd,0x87,
						 0xff,0xef,0xf7,0xfc,
						 0xb9,0xde,0xf9,0xf1};		

The second and display an array of 0 to F, but the number will display each simultaneously display the lower right corner of the decimal point digital tube

	uchar code table3[]={0x7c,0x79,0x6e,0x3f,0x37,0x5e};

第三个算是个字母数组,总共6个元素,分别代表b,e,y,o,n,d,是用来在价格超过99.9,价格爆表时显示在整个六位数码管上的。
其余全局变量与函数声明的内容会在后面提到,这里先不说了

下面是主函数前包括程序作用简单描述,头文件,函数声明,段选、位选、按键使用I/O口定义和全局变量定义的内容的程序:

//按键一次加0.5公里,左三数码管显示路程,右三数码管显示对应的价格,
//每按一次独立按键k1加0.5公里,可更改
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
	
sbit s1=P3^4;	 //定义P34口是s1
sbit s2=P3^5;	 //定义P35口是s2
sbit s3=P3^6;	 //定义P36口是s3
sbit s4=P3^7;	 //定义P37口是s4

uchar code table1[]={0x3f,0x06,0x5b,0x4f,
					 0x66,0x6d,0x7d,0x07,
					 0x7f,0x6f,0x77,0x7c,
				 	 0x39,0x5e,0x79,0x71};
uchar code table2[]={0xbf,0x86,0xdb,0xcf,
					 0xe6,0xed,0xfd,0x87,
					 0xff,0xef,0xf7,0xfc,
					 0xb9,0xde,0xf9,0xf1};
uchar code table3[]={0x7c,0x79,0x6e,0x3f,0x37,0x5e};

sbit dula=P2^6;
sbit wela=P2^7;
										
uchar key;										
uint journey=0,cost=60;										
uint shi,ge,td;
uchar i,a=0xfe;
										
void delayms(uint);
void displayj(uint,uint,uint);
void displayc(uint,uint,uint);
void beyond();										
unsigned char keypros1();

三、程序主体内容

所有的数值都乘以了10,在数码管显示时将数字的百位当做十位,十位当做个位并加上小数点,个位当做十分位。如果不习惯这种用法,可以自己把程序里的数字除以10来使用。

void main()
{
	while(1)
	{
		if(keypros1())//检测是否按下s1
			journey+=5;					//每按一次按键,加5÷10=0.5公里,可更改,例,改为3,即为一次加0.3公里
		if(journey>30)
			cost=60+(journey-30)*12;
			
		if(journey<100)
			shi=0;
		else shi=journey/100;
		ge=journey/10%10;
		td=journey%10;
		displayj(shi,ge,td);
		
		if(cost<100)
			shi=0;
		else if(cost>999)
			beyond();
		else shi=cost/100;
		ge=cost/10%10;
		td=cost%10;		
		if(cost<100)
			shi=0;
		else shi=cost/100;		
		displayc(shi,ge,td);
		
		
	}
}

主函数主体为一个while函数,里面的内容无限循环,journey代表路程,为全局变量,初始值为0,keypros1()检测s1是否按下,若按下返回值1,反之,返回值0。

unsigned char keypros1()
{
  key=0;
	if(s1==0)		  //检测按键s1是否按下
	{	
		delayms(10);   //消除抖动 一般大约10ms
		if(s1==0)	 //再次判断按键是否按下
		{	
			key=1;		
		}
		while(!s1);	 //检测按键是否松开
	}
	if(key==1)
			return 1;
	else return 0;
}

由于本人在编程序时把所有的数字都乘以了10,也就是说,按键一次加0.5变成了加5,主函数循环检测是否按下按键,返回值为1,则journey加5。
全局变量cost,即价格的初始值为60,journey>30之前,不改变cost的值,journey>30之后,始终有cost=(journey-30)*12+60。
计算完journey和cost的值后,会将journey的百位赋给shi,十位赋给ge,个位赋给td。
shi代表十位,ge代表个位,td代表十分位,是英文tenths digit 的缩写。
然后使用函数displayj(shi,ge,td);这个函数是显示路程的函数:

void displayj(uint shi,uint ge,uint td)
{
	if(shi!=0)//shi为0时不显示
	{
		dula=1;
		P0=table1[shi];
		dula=0;
		P0=0xff;	
		wela=1;
		P0=0xfe;
		wela=0;
		delayms(1);
	}
	dula=1;
	P0=table2[ge];
	dula=0;
	P0=0xff;	
	wela=1;
	P0=0xfd;
	wela=0;
	delayms(1);
	
	dula=1;
	P0=table1[td];
	dula=0;
	P0=0xff;	
	wela=1;
	P0=0xfb;
	wela=0;
	delayms(1);	
}

当shi为0时不显示,如下图:
Here Insert Picture Description
shi和td显示时使用数组table1,即没有小数点的数组;
ge显示时使用数组table2,即有小数点的数组;

Then after the cost of one hundred assigned shi, ten assigned ge, bits assigned to td. Then displayc (uint shi, uint ge, uint td); and shown as a function of similar journey:

void displayc(uint shi,uint ge,uint td)
{
	if(shi!=0)
	{
		dula=1;
		P0=table1[shi];
		dula=0;
		P0=0xff;	
		wela=1;
		P0=0xf7;
		wela=0;
		delayms(1);
	}

	dula=1;
	P0=table2[ge];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xef;
	wela=0;
	delayms(1);
	
	dula=1;
	P0=table1[td];
	dula=0;
	P0=0xff;	
	wela=1;
	P0=0xdf;
	wela=0;
	delayms(1);	
}

If the press has been s1 until cost> 999, i.e., displayed value> 99.9, the burst table. Then if not restricted, ten will be displayed in hexadecimal, decimal digit is still completely laissez-faire.
Therefore, the main function will detect whether the cost is greater than 999 cycles, when the cost> 999, it goes to Beyond () function, the function as follows:

void beyond()
{
	while(1)
	{
		for(i=0;i<=5;i++)
		{
			dula=1;
			P0=table3[i];
			dula=0;
			P0=0xff;

			wela=1;
			P0=a;						   //a初值为0xfe,第一个数码管亮
			wela=0;
			delayms(1);				   //延时1s
			a=_crol_(a,1);			       //循环左移
			if(a==0xbf)					   
				a=0xfe;
		}
	}
}	

After entering this function will display six digital Beyond infinite loop, no longer return to the main function, the effect is as follows:
Here Insert Picture Description

Fourth, the simulation map

When drawing FIG simulation, since the connection is a digital tube P0, it must be an external pull-up resistor, if another I / O port is not necessary.
Here Insert Picture Description
In addition, if the program after the first segment selector position selected on the physical display is normal, there is a problem, this is the same program displayed in the proteus; on the contrary, the first digit after the election period on election no problem. Of course, if sufficient I / O port, can also be used two 8-bit I / O port is selected and the bit segments respectively selected, is displayed on this proteus absolutely no problem, but some superfluous.

Released three original articles · won praise 2 · Views 775

Guess you like

Origin blog.csdn.net/zh_j_wei/article/details/104213278