基于51单片机的出租车计价器源程序与Proteus仿真设计

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

本设计是针对城市出租车运营的一个计价器。设计基于STC15F2K60S2单片机为主控制芯片,通过霍尔传感器来给单片机产生脉冲,从而累计车轮旋转的圈数,利用算法来计算出行驶的路程,并根据相应的收费标准计算出应当收取的费用,通过LCD1602液晶显示屏来显示路程,单价,消费金额,路程中等待的时间等信息。本设计还可以根据自身的需要对收费的标准进行调整。系统硬件包括CPU控制模块、按键模块、显示模块、电源模块等四部分。软件设计包括系统总流程图与每个模块的流程图,最后将软件与硬件联调,达到所需功能要求。

(1)不同情况具有不同的收费标准。
白天,晚上,途中等待(>=10min 开始收费)
(2)能进行手动修改单价
(3)具有数据的复位功能
(4)具有启动计时开关、白天/晚上收费标准的转换开关、数据的清零开关、单价的调整(最好使用+和-按键)
(5) 数据输出:单价输出 2 位(要能输入小数),路程输出 2 位,总金额输出 3 位(有 1 位小数)。

一个基于单片机STC15F2K60S2的出租车自动计价器,附带有键盘电路,显示模块等。在上电时LCD1602显示最初的起步价,里程单价,等待时间收费三种收费,通过按键可以调整起步价、里程单价和等待时间收费。通过电机来模拟出租车轮胎的转动和停止。在LCD1602液晶上可以显示运行的路程,运行时暂停的时间,通过软件计算可以得出乘客所需要支付的费用。在这里主要是以STC15F2K60S2单片机为核心控制器,P0口接1602液晶显示模块,P1口接按键原理电路,霍尔传感器连接在外部中断0口向单片机输入脉冲,一个脉冲代表车轮转动一周,从而计算出运行的路程和费用。
设计方案

通过单片机作为主控器,利用1602字符液晶作为显示电路,采用内部时钟脉冲,通过按键可以方便调节,而且控制简单,成本低廉,设计电路简单,易操作,以下是系统流程图。如图1.1所示。

当我们乘坐出租车时,出租车司机通过电源启动计价器后,只要汽车一启动,随着行驶里程的增加,当小于某一个值的时候<如3km>时,就会看到出租车里面的计价器里程数字显示的读数为起步价,而当行驶到某一值<如3km)计费数字显示开始从起步价<如7.7元)增加。当出租车到达某地需要在那里等候时,司机只要按一下“等待”键,每等候一定的时间<如10分钟),计费显示就增加一个该收的等候费用<如每10 分钟收取3.3元)。出租车继续行驶时,停止计算等候费用,继续增加里程计费。到达目的地,便可按显示的数字收费。然后关闭计费器,对计数器清零,等待下次计费开始。
由stc15f2k60s2作为主控制芯片,并连接按键系统和lcd1602显示系统,用电机来模拟车轮的转动,通过霍尔传感器对单片机输入一个脉冲,一个脉冲待变车轮转动一周,假设转动一周的距离为0.01km,由此来判断出租车行驶的距离,从而计算出乘客应付的价钱。
在司机等待时按下等待按键,则计时器开始工作,等待10分钟则开始加价,停止等待时,页面会自动返回到初始计价页面,等待价钱和时间不清零,结束计价时则把等待价钱和显示价钱一起算。
本次设计利用单片机技术来实现一台出租车计价器,具有性能可靠、电路简单、成本低等特点。本次设计所设计的出租车计价器的主要功能有:数据的复位、白天/晚上转换、数据输出、计时计价、单价输出及调整、路程输出、等功能。输出采用LCD1602液晶。本电路设计的计价器不但能实现基本的计价,而且还能根据白天、黑夜、中途等待来调节单价,

第二章 硬件电路设计

2.1按键电路
采用独立式键盘,每个按键占用一个I/O口,每个按键相对独立,I/O口通过按键与地相连,无键按下时,引脚端为高电平,有键按下时,引脚端为低电平。所以可以通过判断每个引脚端是否为低电平,就可以知道是否有键按下。图2.1为按键电路。

图2.1  按键电路

S1:接P1.0口,开始计费和结束计费按键,按单次为开始计费,按双次为结束计费。
S2:接P1.1口,是暂停按键,按下后,开启定时器0,LCD1602会开始显示等待时间并且在等待开始十分钟后开始增加等待价钱,在按下结束键之前,等待时间和金钱不会清零。
S3:接P1.2口,是设置按键,在结束计价的时候,按一次,对起步价可以进行调整;按两次,对等待10分钟的等待价钱可以进行调整;按三次,对晚上可以单价进行调整;按四次,可以对白天单价进行调整;按第五次时,回到初始界面,然后循环。
S4:接P1.3口,是用来调整单价增加的键。
S5:接P1.4口,是用来调整单价减少的键。
S6:接P1.5口,复位键,按下之后所有的数据恢复到刚开始的状态。

2.2直流电机电路

该直流电机主要是通过驱动芯片L298来驱动,这款芯片可以同时驱动2个直流电机,可以用直流电或PWM脉冲波驱动第5,7脚为控制电机的正反转,一个接负电压,一个接正电压,第6脚ENA控制电机的转速,通过PWM可以控制转速,.这里我们给它-一个高电平就可以了。直流电机电路如图2.2所示。

图2.2 直流电机电路

2.3显示电路

2.3.1 LCD1602的基本参数及引脚功能

引脚功能说明:
1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表1所示。

2.4脉冲输入电路

利用霍尔传感器来对单片机输入一个脉冲,从而计算出租车行驶的路程,将霍尔传感器接到单片机外部中断0上,触发中断,计算公里数。
由于A44E属于开关型的霍尔器件,其工作电压范围比较宽<4.5~18V),其输出的信号符合TTL电平标准,可以直接接到单片机的I0端口上,而且其最高检测频率可达到1MHz。
A44E集成霍耳开关由稳压器A、霍耳电势发生器(即硅霍耳片>B、差分放大器C、施密特触发器D和0CI门输出E五个基本部分组成。
如图2.4所示为霍尔传感器连接电路。

图2.4  霍尔传感器连接电路

2.5 STC15F2K60S2的引脚连接和说明

2.5.1 STC15F2K60S2的引脚连接

P2口连接LCD1602D0-D7口;
P0.0连接LCD1602RS口,P0.1连接LCD1602的R/W口,P0.2连接LCD1602的EN口;
P1.0-P1.5为按键连接口;
P3.2为外部中断0连接口,连接霍尔传感器输入端,向单片机输入脉冲来计算行车途中的行驶里程;
P3.0和P3.1口连接驱动芯片L298N的输入端IN1和IN2,用来控制电机转动和停止,用来模仿出租车的行驶和停止。
如图2.5为STC15F2K60S2的引脚连接图:

图2.5 STC15F2K60S2的引脚连接图

第三章 软件设计

3.1 单片机资源利用

在本次设计中电路键盘用到了P1口,其中P1.0口到P1.5口作为键盘的输入,显示电路用到了P0口和P2口,P2口为液晶的数据口,P3.2口作为脉冲的输入端。
3.2单片机软件模块设计
如图3.1所示为总体软件设计流程图。
如图3.2所示为外部中断0计算路程流程图。
如图3.3所示为按键子函数流程图。
如图3.4 定时器T0计时收费流程图。

图3.3 按键子函数流程图

在软件设计中,用T0来计时,当汽车停下来等待时,出租车司机则按下等待键,开启定时器T0,定时器每次定50ms,定20次就是1s,此时miao就加一,当miao=59时,执行miao=0,fen++;当fen=59时,执行fen=0,shi++;接下来判断fen是否>=10?若>=10,计价器就按收费标准开始计算价钱。如图3.3为定时器T0计时收费流程图。

图3.4 定时器T0计时收费流程图

第四章 总结

本款出租车计价器有不少功能,其中包括单价输出、单价调整、路程输出、显示途中等待时间和相应的价钱、显示总价等功能。另外,这个出租车计价器还具有性能可靠、电路简单、成本低、实用性强等特点。

单片机源程序如下:

  1. #include<reg51.h>

  2. #include<LCD1602.h>

  3. #define uchar unsigned char

  4. #define uint  unsigned int

  5. sbit key_start =P1^0;         //开始/结束计价

  6. sbit key_wait  =P1^1;         //等待

  7. sbit key_set   =P1^2;         //设置

  8. sbit key_jia   =P1^3;         //加值

  9. sbit key_jian  =P1^4;         //减值

  10. sbit key_dn    =P1^5;   //控制白天晚上

  11. sbit key_fuwei =P1^6;  //复位

  12. sbit mod=P1^7;          //电机控制

  13. /************************——变量定义***********************/

  14. uint start_price=77;                //起步价

  15. uint white_price=66;         //白天的单价   超过3公里每公里6元

  16. uint black_price=88;        //夜晚的单价   超过3公里每公里8元

  17. uint Wait_price=100;                //等待价钱

  18. bit dnc=0;                   //白天晚上的转换标志

  19. bit qiting;                 //起 停标志位

  20. uint price1,price2;                           //总价钱、等待价钱

  21. uint   mil;                //里程数

  22. uint mil2;

  23. uchar shi,fen,miao;

  24. uchar  moshi,moshi2,ms,set_f;                                //模式mos=0初始界面,=1改价页面,=2等待页面

  25. //set_f设置标志=1设置初始价格,=2设置等待价格,=3设置晚上单价,=4设置白天单价

  26. void delay(uchar ms)        //延时函数

  27. {

  28. uchar j;

  29. while(ms--)

  30. {

  31. for(j=0;j<130;j++);

  32. }

  33. }

  34. void key()        //按键函数

  35. {

  36. if(key_dn==0)

  37. {

  38. delay(5);   //延时去抖

  39. if(key_dn==0)

  40. {

  41. while(!key_dn);

  42. dnc=~dnc;

  43. }

  44. }

  45. if(key_start==0)

  46. {

  47. delay(5);

  48. if(key_start==0)

  49. {

  50. while(!key_start);   //检测按键是否松开

  51. qiting=~qiting;      //起 停 转换

  52. if(qiting==0)

  53. {

  54. moshi=0;

  55. }

  56. mod=~qiting;         //电机打开/关闭

  57. TR0=qiting;          //定时器0打开/关闭

  58. set_f=0;

  59. }

  60. }

  61. if(key_fuwei==0)          //复位

  62. {

  63. delay(5);

  64. if(key_fuwei==0)

  65. {

  66. while(!key_fuwei);

  67. miao=0;fen=0;shi=0;

  68. price1=0;price2=0;        mil=0;moshi=0;

  69. }

  70. }

  71. if(key_wait==0)

  72. {

  73. delay(5);

  74. if(key_wait==0)

  75. {

  76. while(!key_wait);

  77. miao=0;fen=0;shi=0;

  78. moshi=2;

  79. }

  80. }

  81. if(qiting==0)         //结束计价后才能设置

  82. {

  83. if(key_set==0)

  84. {

  85. delay(5);

  86. if(key_set==0)

  87. {

  88. while(!key_set);

  89. set_f++;

  90. moshi=1;

  91. if(set_f==5){moshi=0;set_f=0;}

  92. }

  93. }

  94. if(set_f!=0)

  95. {

  96. if(key_jia==0)

  97. {

  98. delay(5);

  99. if(key_jia==0)

  100. {

  101. while(!key_jia);

  102. if(set_f==1){if(start_price<999)start_price++;}

  103. if(set_f==2){if(Wait_price<999)Wait_price++;}

  104. if(set_f==3){if(black_price<999)black_price++;}

  105. if(set_f==4){if(white_price<999)white_price++;}

  106. }

  107. }

  108. if(key_jian==0)

  109. {

  110. delay(5);

  111. if(key_jian==0)

  112. {

  113. while(!key_jian);

  114. if(set_f==1){if(start_price>0)start_price--;}

  115. if(set_f==2){if(Wait_price>0)Wait_price--;}

  116. if(set_f==3){if(black_price>0)black_price--;}

  117. if(set_f==4){if(white_price>0)white_price--;}

  118. }

  119. }

  120. }

  121. }

  122. }

  123. void xianshi()

  124. {

  125. if(moshi!=moshi2)

  126. {

  127. lcd_wcmd(0x01);       //清显示屏

  128. moshi2=moshi;

  129. }

  130. if(moshi==0)

  131. {

  132. lcd_wcmd(0x80);

  133. lcd_data('N');

  134. lcd_data('J');

  135. lcd_data(':');

  136. lcd_data(ASCII[black_price%1000/100]);

  137. lcd_data(ASCII[black_price%100/10]);

  138. lcd_data('.');

  139. lcd_data(ASCII[black_price%10]);

  140. //       lcd_wcmd(0x80);

  141. //                         lcd_data('D');

  142. //       lcd_data('J');

  143. //                         lcd_data(':');

  144. //                         lcd_data(ASCII[white_price%1000/100]);

  145. //                         lcd_data(ASCII[white_price%100/10]);

  146. //                         lcd_data('.');

  147. //                         lcd_data(ASCII[white_price%10]);

  148. //                         lcd_data('Y');

  149. lcd_data('G');

  150. lcd_data(':');

  151. lcd_data(ASCII[mil%1000/100]);

  152. lcd_data(ASCII[mil%100/10]);

  153. lcd_data('.');

  154. lcd_data(ASCII[mil%10]);

  155. lcd_data('K');

  156. lcd_data('M');

  157. lcd_wcmd(0x80+0x40);

  158. lcd_data('D');

  159. lcd_data('J');

  160. lcd_data(':');

  161. lcd_data(ASCII[white_price%1000/100]);

  162. lcd_data(ASCII[white_price%100/10]);

  163. lcd_data('.');

  164. lcd_data(ASCII[white_price%10]);

  165. lcd_data('Y');

  166. lcd_data('Y');

  167. lcd_data('Q');

  168. lcd_data(':');

  169. lcd_data(ASCII[price1%1000/100]);

  170. lcd_data(ASCII[price1%100/10]);

  171. lcd_data('.');

  172. lcd_data(ASCII[price1%10]);

  173. lcd_data('O');

  174. lcd_data('Y');

  175. }

  176. if(moshi==1)       //改价页面

  177. {

  178. lcd_wcmd(0x80);

  179. lcd_data('S');

  180. lcd_data('J');

  181. lcd_data(ASCII[start_price%1000/100]);

  182. lcd_data(ASCII[start_price%100/10]);

  183. lcd_data('.');

  184. lcd_data(ASCII[start_price%10]);

  185. lcd_data('Y');

  186. lcd_data(' ');

  187. lcd_data('P');

  188. lcd_data('T');

  189. lcd_data(ASCII[Wait_price%1000/100]);

  190. lcd_data(ASCII[Wait_price%100/10]);

  191. lcd_data('.');

  192. lcd_data(ASCII[Wait_price%10]);

  193. lcd_data('Y');

  194. lcd_wcmd(0x80+0x40);

  195. lcd_data('N');

  196. lcd_data('J');

  197. lcd_data(ASCII[black_price%1000/100]);

  198. lcd_data(ASCII[black_price%100/10]);

  199. lcd_data('.');

  200. lcd_data(ASCII[black_price%10]);

  201. lcd_data('Y');

  202. lcd_data(' ');

  203. lcd_data('D');

  204. lcd_data('J');

  205. lcd_data(ASCII[white_price%1000/100]);

  206. lcd_data(ASCII[white_price%100/10]);

  207. lcd_data('.');

  208. lcd_data(ASCII[white_price%10]);

  209. lcd_data('Y');

  210. }

  211. if(moshi==2)       //等待页面

  212. {

  213. lcd_wcmd(0x80);

  214. lcd_data('W');

  215. lcd_data('a');

  216. lcd_data('i');

  217. lcd_data('t');

  218. lcd_data(':');

  219. lcd_data(' ');

  220. lcd_data(' ');

  221. lcd_data(ASCII[shi%100/10]);

  222. lcd_data(ASCII[shi%10]);

  223. lcd_data(':');

  224. lcd_data(ASCII[fen%100/10]);

  225. lcd_data(ASCII[fen%10]);

  226. lcd_data(':');

  227. lcd_data(ASCII[miao%100/10]);

  228. lcd_data(ASCII[miao%10]);

  229. lcd_wcmd(0x80+0x40);

  230. lcd_data('D');

  231. lcd_data('D');

  232. lcd_data('M');

  233. lcd_data(':');

  234. //                         lcd_data(ASCII[(white_price/2)%1000/100]);

  235. //                         lcd_data(ASCII[(white_price/2)%100/10]);

  236. lcd_data(ASCII[price2%1000/100]);

  237. lcd_data(ASCII[price2%100/10]);

  238. lcd_data('.');

  239. lcd_data(ASCII[price2%10]);

  240. //lcd_data(ASCII[(white_price/2)%10]);

  241. lcd_data(' ');

  242. lcd_data('Y');

  243. }

  244. }

  245. void jiaqianjisuan()         //计算价钱

  246. {

  247. if(dnc==0)   //白天价钱

  248. {

  249. if(mil>30)

  250. {

  251. price1=(white_price*((mil-30)/10));

  252. price1=price1+start_price+price2;

  253. }

  254. else

  255. price1=start_price+price2;

  256. }

  257. else         //晚上价钱

  258. {

  259. if(mil>30)

  260. {

  261. price1=(black_price*((mil-30)/10));

  262. price1=price1+start_price+price2;

  263. }

  264. else

  265. price1=start_price+price2;

  266. }

  267. }

  268. void T0_init()                   //定时器0初始化

  269. {

  270. EA=1;                  //开总中断

  271. ET0=1;                 //定时器T0中断允许

  272. TMOD=0x01;             //使用定时器T0的模式1

  273. TH0=(65536-50000)/256; //定时器T0的高8位赋初值

  274. TL0=(65536-50000)%256; //定时器T0的低8位赋初值

  275. TR0=0;                                         //关闭定时器0

  276. EX0=1;                 //外部中断0允许位

  277. IT0=1;                 //下降沿触发外部中断

  278. }

  279. void main()

  280. {

  281. lcd_init();           //LCD1602初始化

  282. T0_init();           //定时器0初始化

  283. while(1)                                                         //死循环

  284. {

  285. jiaqianjisuan();

  286. key();                        //按键检测处理

  287. xianshi();

  288. }

  289. }

  290. void timer0() interrupt 1                  //定时器0中断函数

  291. {

  292. TH0=(65536-50000)/256;

  293. TL0=(65536-50000)%256;                //定50ms

  294. ms++;

  295. if(ms>=20)

  296. {

  297. ms=0;

  298. miao++;

  299. if(moshi==0)

  300. ……………………

  301. …………限于本文篇幅 余下代码请从51黑下载附件…………

复制代码

所有资料51hei提供下载(仿真+代码):

(0)

相关推荐