您的位置 首页 分销

第36节:带数码管显现的加法简易计算器

开场白:这一节要做一个简单的计算器。这个计算器不带小数点,只能进行不超过8位数据的加法运算,它麻雀虽小但是五脏俱全,它能清晰地勾

开场白:

这一节要做一个简略的计算器。这个计算器不带小数点,只能进行不超越8位数据的加法运算,它麻雀虽小可是五脏俱全,它能明晰地勾勒出商业计算器的程序结构和思路。读者只需看懂本节程序结构的规则,今后自己想做一个杂乱一点的计算器应该是没问题的。杂乱的计算器在算法上要用数组进行特别处理,不能简略地直接用C言语的+,-,*,/运算符,这方面的内容我会在今后的章节中跟我们共享。
这一节要教会我们两个知识点:
榜首个:数字按键的输入和十进制数值的移位办法。
第二个:持续加深了解按键与数码管的相关程序结构。

详细内容,请看源代码解说。

(1)硬件渠道:

依据朱兆祺51单片机学习板。数字1键对应S1键,数字2键对应S2键,数字3键对应S3键…. 数字9键对应S9键, 数字0键对应S10键。加号键对应S13,等于号键对应S14,铲除复位按键对应S16。其它按键不必。

(2)完成功用:

常用的加法计算器功用。有连加功用。
本程序有2个窗口。
第1个窗口:原始数据和运算成果窗口。比方加法运算中的被加数
第2个窗口:第二个参加运转的数据窗口。比方加法运算中的加数
(3)源代码解说如下:

  1. #include “REG52.H”
  2. #define const_voice_short40 //蜂鸣器短叫的持续时刻
  3. #define const_voice_long 900 //蜂鸣器长叫的持续时刻
  4. #define const_key_time10 //按键去颤动延时的时刻
  5. #define const_1s 422 //发生一秒钟的时刻基准
  6. void initial_myself();
  7. void initial_peripheral();
  8. void delay_short(unsigned int uiDelayShort);
  9. void delay_long(unsigned int uiDelaylong);
  10. void T0_time();//守时中止函数
  11. void key_service();
  12. void key_scan(); //按键扫描函数 放在守时中止里
  13. void number_key_input(unsigned long ucWhichKey);//因为数字按键的代码类似度高,因而封装在这个函数里
  14. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
  15. void display_drive();//放在守时中止里的数码管驱动函数
  16. void display_service();
  17. sbit key_sr1=P0^0; //榜首行输入
  18. sbit key_sr2=P0^1; //第二行输入
  19. sbit key_sr3=P0^2; //第三行输入
  20. sbit key_sr4=P0^3; //第四行输入
  21. sbit key_dr1=P0^4; //榜首列输出
  22. sbit key_dr2=P0^5; //第二列输出
  23. sbit key_dr3=P0^6; //第三列输出
  24. sbit key_dr4=P0^7; //第四列输出
  25. sbit beep_dr=P2^7; //蜂鸣器的驱动IO口
  26. sbit led_dr=P3^5; //LED指示灯
  27. sbit dig_hc595_sh_dr=P2^0; //数码管 的74HC595程序
  28. sbit dig_hc595_st_dr=P2^1;
  29. sbit dig_hc595_ds_dr=P2^2;
  30. sbit hc595_sh_dr=P2^3; //LED灯的74HC595程序
  31. sbit hc595_st_dr=P2^4;
  32. sbit hc595_ds_dr=P2^5;
  33. unsigned char ucKeyStep=1;//按键扫描过程变量
  34. unsigned char ucKeySec=0; //被触发的按键编号
  35. unsigned intuiKeyTimeCnt=0; //按键去颤动延时计数器
  36. unsigned char ucKeyLock=0; //按键触发后自锁的变量标志
  37. unsigned char ucRowRecord=1; //记载当时扫描到第几列了
  38. unsigned intuiVoiceCnt=0;//蜂鸣器鸣叫的持续时刻计数器
  39. unsigned char ucDigShow8=0;//第8位数码管要显现的内容
  40. unsigned char ucDigShow7=0;//第7位数码管要显现的内容
  41. unsigned char ucDigShow6=0;//第6位数码管要显现的内容
  42. unsigned char ucDigShow5=0;//第5位数码管要显现的内容
  43. unsigned char ucDigShow4=0;//第4位数码管要显现的内容
  44. unsigned char ucDigShow3=0;//第3位数码管要显现的内容
  45. unsigned char ucDigShow2=0;//第2位数码管要显现的内容
  46. unsigned char ucDigShow1=0;//第1位数码管要显现的内容
  47. unsigned char ucDigShowTemp=0; //暂时中心变量
  48. unsigned char ucDisplayDriveStep=1;//动态扫描数码管的过程变量
  49. unsigned char ucDisplayUpdate=1; //更新显现标志
  50. unsigned long ulSource=0;//原始数据 比方在加法运算中的被加数
  51. unsigned long ulOther=0; //别的一个参加运算的数据比方在加法运算中的加数
  52. unsigned long ulResult=0; //运算成果
  53. unsigned char ucOperator=0; //运转符号。0代表当时没有挑选运转符号。1代表当时的运算符是加法。
  54. /* 注释一:
  55. *ucWd变量是本程序最中心的变量,代表数码管显现哪一个窗口
  56. *本程序只要两个窗口,他们分别是:
  57. *榜首个窗口:原始数据和运算成果窗口。比方加法运算中的被加数
  58. *第二个窗口:第二个参加运转的数据窗口。比方加法运算中的加数
  59. */
  60. unsigned char ucWd=1;
  61. code unsigned char dig_table[]=
  62. {
  63. 0x3f,//0 序号0
  64. 0x06,//1 序号1
  65. 0x5b,//2 序号2
  66. 0x4f,//3 序号3
  67. 0x66,//4 序号4
  68. 0x6d,//5 序号5
  69. 0x7d,//6 序号6
  70. 0x07,//7 序号7
  71. 0x7f,//8 序号8
  72. 0x6f,//9 序号9
  73. 0x00,//不显现序号10
  74. };
  75. void main()
  76. {
  77. initial_myself();
  78. delay_long(100);
  79. initial_peripheral();
  80. while(1)
  81. {
  82. key_service();
  83. display_service();
  84. }
  85. }
  86. void display_service()//放在守时中止里的显现应用程序
  87. {
  88. if(ucDisplayUpdate==1)//有数据更新显现
  89. {
  90. ucDisplayUpdate=0;
  91. switch(ucWd) //本程序最中心的变量ucWd
  92. {
  93. case 1://窗口1原始数据和运算成果窗口
  94. if(ulSource>=10000000)
  95. {
  96. ucDigShow8=ulSource/10000000;
  97. }
  98. else
  99. {
  100. ucDigShow8=10;//数据显现空
  101. }
  102. if(ulSource>=1000000)
  103. {
  104. ucDigShow7=ulSource%10000000/1000000;
  105. }
  106. else
  107. {
  108. ucDigShow7=10;//数据显现空
  109. }
  110. if(ulSource>=100000)
  111. {
  112. ucDigShow6=ulSource%1000000/100000;
  113. }
  114. else
  115. {
  116. ucDigShow6=10;//数据显现空
  117. }
  118. if(ulSource>=10000)
  119. {
  120. ucDigShow5=ulSource%100000/10000;
  121. }
  122. else
  123. {
  124. ucDigShow5=10;//数据显现空
  125. }
  126. if(ulSource>=1000)
  127. {
  128. ucDigShow4=ulSource%10000/1000;
  129. }
  130. else
  131. {
  132. ucDigShow4=10;//数据显现空
  133. }
  134. if(ulSource>=100)
  135. {
  136. ucDigShow3=ulSource%1000/100;
  137. }
  138. else
  139. {
  140. ucDigShow3=10;//数据显现空
  141. }
  142. if(ulSource>=10)
  143. {
  144. ucDigShow2=ulSource%100/10;
  145. }
  146. else
  147. {
  148. ucDigShow2=10;//数据显现空
  149. }
  150. ucDigShow1=ulSource%10;
  151. break;
  152. case 2://窗口2第二个参加运管用据的窗口比方加法运算中的加数
  153. if(ulOther>=10000000)
  154. {
  155. ucDigShow8=ulOther/10000000;
  156. }
  157. else
  158. {
  159. ucDigShow8=10;//数据显现空
  160. }
  161. if(ulOther>=1000000)
  162. {
  163. ucDigShow7=ulOther%10000000/1000000;
  164. }
  165. else
  166. {
  167. ucDigShow7=10;//数据显现空
  168. }
  169. if(ulOther>=100000)
  170. {
  171. ucDigShow6=ulOther%1000000/100000;
  172. }
  173. else
  174. {
  175. ucDigShow6=10;//数据显现空
  176. }
  177. if(ulOther>=10000)
  178. {
  179. ucDigShow5=ulOther%100000/10000;
  180. }
  181. else
  182. {
  183. ucDigShow5=10;//数据显现空
  184. }
  185. if(ulOther>=1000)
  186. {
  187. ucDigShow4=ulOther%10000/1000;
  188. }
  189. else
  190. {
  191. ucDigShow4=10;//数据显现空
  192. }
  193. if(ulOther>=100)
  194. {
  195. ucDigShow3=ulOther%1000/100;
  196. }
  197. else
  198. {
  199. ucDigShow3=10;//数据显现空
  200. }
  201. if(ulOther>=10)
  202. {
  203. ucDigShow2=ulOther%100/10;
  204. }
  205. else
  206. {
  207. ucDigShow2=10;//数据显现空
  208. }
  209. ucDigShow1=ulOther%10;
  210. break;
  211. }
  212. }
  213. }
  214. void display_drive()//放在守时中止里的数码管驱动函数
  215. {
  216. //以下程序,假如加一些数组和移位的元素,还能够紧缩容量。可是鸿哥寻求的不是容量,而是明晰的解说思路
  217. switch(ucDisplayDriveStep)
  218. {
  219. case 1://显现第1位
  220. ucDigShowTemp=dig_table[ucDigShow1];
  221. dig_hc595_drive(ucDigShowTemp,0xfe);
  222. break;
  223. case 2://显现第2位
  224. ucDigShowTemp=dig_table[ucDigShow2];
  225. dig_hc595_drive(ucDigShowTemp,0xfd);
  226. break;
  227. case 3://显现第3位
  228. ucDigShowTemp=dig_table[ucDigShow3];
  229. dig_hc595_drive(ucDigShowTemp,0xfb);
  230. break;
  231. case 4://显现第4位
  232. ucDigShowTemp=dig_table[ucDigShow4];
  233. dig_hc595_drive(ucDigShowTemp,0xf7);
  234. break;
  235. case 5://显现第5位
  236. ucDigShowTemp=dig_table[ucDigShow5];
  237. dig_hc595_drive(ucDigShowTemp,0xef);
  238. break;
  239. case 6://显现第6位
  240. ucDigShowTemp=dig_table[ucDigShow6];
  241. dig_hc595_drive(ucDigShowTemp,0xdf);
  242. break;
  243. case 7://显现第7位
  244. ucDigShowTemp=dig_table[ucDigShow7];
  245. dig_hc595_drive(ucDigShowTemp,0xbf);
  246. break;
  247. case 8://显现第8位
  248. ucDigShowTemp=dig_table[ucDigShow8];
  249. dig_hc595_drive(ucDigShowTemp,0x7f);
  250. break;
  251. }
  252. ucDisplayDriveStep++;
  253. if(ucDisplayDriveStep>8)//扫描完8个数码管后,从头从榜首个开端扫描
  254. {
  255. ucDisplayDriveStep=1;
  256. }
  257. }
  258. //数码管的74HC595驱动函数
  259. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
  260. {
  261. unsigned char i;
  262. unsigned char ucTempData;
  263. dig_hc595_sh_dr=0;
  264. dig_hc595_st_dr=0;
  265. ucTempData=ucDigStatusTemp16_09;//先送高8位
  266. for(i=0;i<8;i++)
  267. {
  268. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
  269. else dig_hc595_ds_dr=0;
  270. /* 注释二:
  271. *留意,此处的延时delay_short有必要尽可能小,不然动态扫描数码管的速度就不行。
  272. */
  273. dig_hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  274. delay_short(1);
  275. dig_hc595_sh_dr=1;
  276. delay_short(1);
  277. ucTempData=ucTempData<<1;
  278. }
  279. ucTempData=ucDigStatusTemp08_01;//再先送低8位
  280. for(i=0;i<8;i++)
  281. {
  282. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
  283. else dig_hc595_ds_dr=0;
  284. dig_hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  285. delay_short(1);
  286. dig_hc595_sh_dr=1;
  287. delay_short(1);
  288. ucTempData=ucTempData<<1;
  289. }
  290. dig_hc595_st_dr=0;//ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上而且锁存起来
  291. delay_short(1);
  292. dig_hc595_st_dr=1;
  293. delay_short(1);
  294. dig_hc595_sh_dr=0; //拉低,抗干扰就增强
  295. dig_hc595_st_dr=0;
  296. dig_hc595_ds_dr=0;
  297. }
  298. //LED灯的74HC595驱动函数
  299. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
  300. {
  301. unsigned char i;
  302. unsigned char ucTempData;
  303. hc595_sh_dr=0;
  304. hc595_st_dr=0;
  305. ucTempData=ucLedStatusTemp16_09;//先送高8位
  306. for(i=0;i<8;i++)
  307. {
  308. if(ucTempData>=0x80)hc595_ds_dr=1;
  309. else hc595_ds_dr=0;
  310. hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  311. delay_short(1);
  312. hc595_sh_dr=1;
  313. delay_short(1);
  314. ucTempData=ucTempData<<1;
  315. }
  316. ucTempData=ucLedStatusTemp08_01;//再先送低8位
  317. for(i=0;i<8;i++)
  318. {
  319. if(ucTempData>=0x80)hc595_ds_dr=1;
  320. else hc595_ds_dr=0;
  321. hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  322. delay_short(1);
  323. hc595_sh_dr=1;
  324. delay_short(1);
  325. ucTempData=ucTempData<<1;
  326. }
  327. hc595_st_dr=0;//ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上而且锁存起来
  328. delay_short(1);
  329. hc595_st_dr=1;
  330. delay_short(1);
  331. hc595_sh_dr=0; //拉低,抗干扰就增强
  332. hc595_st_dr=0;
  333. hc595_ds_dr=0;
  334. }
  335. void key_scan()//按键扫描函数 放在守时中止里
  336. {
  337. switch(ucKeyStep)
  338. {
  339. case 1: //按键扫描输出第ucRowRecord列低电平
  340. if(ucRowRecord==1)//榜首列输出低电平
  341. {
  342. key_dr1=0;
  343. key_dr2=1;
  344. key_dr3=1;
  345. key_dr4=1;
  346. }
  347. else if(ucRowRecord==2)//第二列输出低电平
  348. {
  349. key_dr1=1;
  350. key_dr2=0;
  351. key_dr3=1;
  352. key_dr4=1;
  353. }
  354. else if(ucRowRecord==3)//第三列输出低电平
  355. {
  356. key_dr1=1;
  357. key_dr2=1;
  358. key_dr3=0;
  359. key_dr4=1;
  360. }
  361. else //第四列输出低电平
  362. {
  363. key_dr1=1;
  364. key_dr2=1;
  365. key_dr3=1;
  366. key_dr4=0;
  367. }
  368. uiKeyTimeCnt=0;//延时计数器清零
  369. ucKeyStep++; //切换到下一个运转过程
  370. break;
  371. case 2: //此处的小延时用来等候方才列输出信号安稳,再判别输入信号。不是去颤动延时。
  372. uiKeyTimeCnt++;
  373. if(uiKeyTimeCnt>1)
  374. {
  375. uiKeyTimeCnt=0;
  376. ucKeyStep++; //切换到下一个运转过程
  377. }
  378. break;
  379. case 3:
  380. if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==1)
  381. {
  382. ucKeyStep=1;//假如没有按键按下,返回到榜首个运转过程从头开端扫描
  383. ucKeyLock=0;//按键自锁标志清零
  384. uiKeyTimeCnt=0; //按键去颤动延时计数器清零,此行十分奇妙
  385. ucRowRecord++;//输出下一列
  386. if(ucRowRecord>4)
  387. {
  388. ucRowRecord=1; //顺次输出完四列之后,持续从榜首列开端输出低电平
  389. }
  390. }
  391. else if(ucKeyLock==0)//有按键按下,且是榜首次触发
  392. {
  393. if(key_sr1==0&&key_sr2==1&&key_sr3==1&&key_sr4==1)
  394. {
  395. uiKeyTimeCnt++;//去颤动延时计数器
  396. if(uiKeyTimeCnt>const_key_time)
  397. {
  398. uiKeyTimeCnt=0;
  399. ucKeyLock=1;//自锁按键置位,防止一向触发,只要松开按键,此标志位才会被清零
  400. if(ucRowRecord==1)//榜首列输出低电平
  401. {
  402. ucKeySec=1;//触发1号键 对应朱兆祺学习板的S1键
  403. }
  404. else if(ucRowRecord==2)//第二列输出低电平
  405. {
  406. ucKeySec=2;//触发2号键 对应朱兆祺学习板的S2键
  407. }
  408. else if(ucRowRecord==3)//第三列输出低电平
  409. {
  410. ucKeySec=3;//触发3号键 对应朱兆祺学习板的S3键
  411. }
  412. else //第四列输出低电平
  413. {
  414. ucKeySec=4;//触发4号键 对应朱兆祺学习板的S4键
  415. }
  416. }
  417. }
  418. else if(key_sr1==1&&key_sr2==0&&key_sr3==1&&key_sr4==1)
  419. {
  420. uiKeyTimeCnt++;//去颤动延时计数器
  421. if(uiKeyTimeCnt>const_key_time)
  422. {
  423. uiKeyTimeCnt=0;
  424. ucKeyLock=1;//自锁按键置位,防止一向触发,只要松开按键,此标志位才会被清零
  425. if(ucRowRecord==1)//榜首列输出低电平
  426. {
  427. ucKeySec=5;//触发5号键 对应朱兆祺学习板的S5键
  428. }
  429. else if(ucRowRecord==2)//第二列输出低电平
  430. {
  431. ucKeySec=6;//触发6号键 对应朱兆祺学习板的S6键
  432. }
  433. else if(ucRowRecord==3)//第三列输出低电平
  434. {
  435. ucKeySec=7;//触发7号键 对应朱兆祺学习板的S7键
  436. }
  437. else //第四列输出低电平
  438. {
  439. ucKeySec=8;//触发8号键 对应朱兆祺学习板的S8键
  440. }
  441. }
  442. }
  443. else if(key_sr1==1&&key_sr2==1&&key_sr3==0&&key_sr4==1)
  444. {
  445. uiKeyTimeCnt++;//去颤动延时计数器
  446. if(uiKeyTimeCnt>const_key_time)
  447. {
  448. uiKeyTimeCnt=0;
  449. ucKeyLock=1;//自锁按键置位,防止一向触发,只要松开按键,此标志位才会被清零
  450. if(ucRowRecord==1)//榜首列输出低电平
  451. {
  452. ucKeySec=9;//触发9号键 对应朱兆祺学习板的S9键
  453. }
  454. else if(ucRowRecord==2)//第二列输出低电平
  455. {
  456. ucKeySec=10;//触发10号键 对应朱兆祺学习板的S10键
  457. }
  458. else if(ucRowRecord==3)//第三列输出低电平
  459. {
  460. ucKeySec=11;//触发11号键 对应朱兆祺学习板的S11键
  461. }
  462. else //第四列输出低电平
  463. {
  464. ucKeySec=12;//触发12号键 对应朱兆祺学习板的S12键
  465. }
  466. }
  467. }
  468. else if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==0)
  469. {
  470. uiKeyTimeCnt++;//去颤动延时计数器
  471. if(uiKeyTimeCnt>const_key_time)
  472. {
  473. uiKeyTimeCnt=0;
  474. ucKeyLock=1;//自锁按键置位,防止一向触发,只要松开按键,此标志位才会被清零
  475. if(ucRowRecord==1)//榜首列输出低电平
  476. {
  477. ucKeySec=13;//触发13号键 对应朱兆祺学习板的S13键
  478. }
  479. else if(ucRowRecord==2)//第二列输出低电平
  480. {
  481. ucKeySec=14;//触发14号键 对应朱兆祺学习板的S14键
  482. }
  483. else if(ucRowRecord==3)//第三列输出低电平
  484. {
  485. ucKeySec=15;//触发15号键 对应朱兆祺学习板的S15键
  486. }
  487. else //第四列输出低电平
  488. {
  489. ucKeySec=16;//触发16号键 对应朱兆祺学习板的S16键
  490. }
  491. }
  492. }
  493. }
  494. break;
  495. }
  496. }
  497. /* 注释三:
  498. *按键服务程序操作的精华在于依据当时体系处于什么窗口下,在此窗口下的运算符处于
  499. *什么状况,然后紧紧围绕着不同的窗口ucWd,不同的ucOperator来履行不同的操作。
  500. */
  501. void key_service() //第三区 按键服务的应用程序
  502. {
  503. switch(ucKeySec) //按键服务状况切换
  504. {
  505. case 1:// 1号键 对应朱兆祺学习板的S1键
  506. number_key_input(1);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  507. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  508. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  509. break;
  510. case 2:// 2号键 对应朱兆祺学习板的S2键
  511. number_key_input(2);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  512. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  513. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  514. break;
  515. case 3:// 3号键 对应朱兆祺学习板的S3键
  516. number_key_input(3);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  517. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  518. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  519. break;
  520. case 4:// 4号键 对应朱兆祺学习板的S4键
  521. number_key_input(4);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  522. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  523. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  524. break;
  525. case 5:// 5号键 对应朱兆祺学习板的S5键
  526. number_key_input(5);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  527. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  528. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  529. break;
  530. case 6:// 6号键 对应朱兆祺学习板的S6键
  531. number_key_input(6);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  532. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  533. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  534. break;
  535. case 7:// 7号键 对应朱兆祺学习板的S7键
  536. number_key_input(7);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  537. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  538. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  539. break;
  540. case 8:// 8号键 对应朱兆祺学习板的S8键
  541. number_key_input(8);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  542. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  543. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  544. break;
  545. case 9:// 9号键 对应朱兆祺学习板的S9键
  546. number_key_input(9);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  547. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  548. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  549. break;
  550. case 10:// 把这个按键专门用来输入数字0 对应朱兆祺学习板的S10键
  551. number_key_input(0);//因为数字按键的代码类似度高,因而把详细代码封装在这个函数里
  552. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  553. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  554. break;
  555. case 11:// 11号键 对应朱兆祺学习板的S11键
  556. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  557. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  558. break;
  559. case 12:// 12号键 对应朱兆祺学习板的S12键
  560. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  561. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  562. break;
  563. case 13:// 13号键 加号按键对应朱兆祺学习板的S13键
  564. switch(ucWd)
  565. {
  566. case 1: //在原始数据和运算成果的窗口下
  567. ucOperator=1; //加法
  568. ulOther=ulSource;//第二个运管用默许等于原始数
  569. ucDisplayUpdate=1;//改写显现窗口
  570. break;
  571. case 2: //在第二个参加运管用据的窗口下
  572. ulResult=ulSource+ulOther;//连加
  573. ulSource=ulResult; //下一次运算的原始数据默许为当时运算成果,便利连加功用
  574. ucWd=1; //切换到榜首个窗口
  575. ucDisplayUpdate=1;//改写显现窗口
  576. break;
  577. }
  578. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  579. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  580. break;
  581. case 14:// 14号键 等于号按键对应朱兆祺学习板的S14键
  582. switch(ucWd)
  583. {
  584. case 1: //在原始数据和运算成果的窗口下
  585. switch(ucOperator)//依据不同的运算符号进行不同的操作
  586. {
  587. case 0://无运算符号
  588. break;
  589. case 1://加法
  590. ulResult=ulSource+ulOther;//连加
  591. ulSource=ulResult; //下一次运算的原始数据默许为当时运算成果,便利连加功用
  592. ucDisplayUpdate=1;//改写显现窗口
  593. break;
  594. case 2://减法本程序没有减法功用,假如读者想增加减法程序,能够按键这个结构增加下去
  595. break;
  596. }
  597. break;
  598. case 2: //在第二个参加运管用据的窗口下
  599. switch(ucOperator)//依据不同的运算符号进行不同的操作
  600. {
  601. case 1://加法
  602. ulResult=ulSource+ulOther;//连加
  603. ulSource=ulResult; //下一次运算的原始数据默许为当时运算成果,便利连加功用
  604. ucWd=1; //切换到榜首个窗口
  605. ucDisplayUpdate=1;//改写显现窗口
  606. break;
  607. case 2://减法本程序没有减法功用,假如读者想增加减法程序,能够按键这个结构增加下去
  608. break;
  609. }
  610. break;
  611. }
  612. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  613. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  614. break;
  615. case 15:// 15号键 对应朱兆祺学习板的S15键
  616. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  617. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  618. break;
  619. case 16:// 16号键 铲除按键 相当于复位的功用。从头输入数据对应朱兆祺学习板的S16键
  620. ulSource=0;
  621. ulOther=0;
  622. ulResult=0;
  623. ucOperator=0;
  624. ucWd=1; //切换到榜首个窗口
  625. ucDisplayUpdate=1;//改写显现窗口
  626. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  627. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  628. break;
  629. }
  630. }
  631. /* 注释四:
  632. * 此处参加运算的输入数字ucWhichKey记得用最大变量类型unsigned long,能够防止数据溢出等过错
  633. */
  634. void number_key_input(unsigned long ucWhichKey)//因为数字按键的代码类似度高,因而封装在这个函数里
  635. {
  636. switch(ucWd)
  637. {
  638. case 1: //在原始数据和运算成果的窗口下
  639. switch(ucOperator)//依据不同的运算符号进行不同的操作
  640. {
  641. case 0://无运算符号按键输入原始数据,比方被加输
  642. if(ulSource<=9999999) //最大只能输入8位数
  643. {
  644. ulSource=ulSource*10+ucWhichKey;//十进制的数值移位办法。
  645. }
  646. break;
  647. default://在现已按下了运算符号的情况下
  648. ulOther=0;//第二个运管用先清零,再输入新的数据,然后立刻切换到第2个窗口下
  649. ulOther=ucWhichKey;
  650. ucWd=2; //立刻切换到第二个窗口下
  651. break;
  652. }
  653. ucDisplayUpdate=1;//改写显现窗口
  654. break;
  655. case 2: //在第二个参加运管用据的窗口下 按键输入第二个参加运算的数据
  656. if(ulOther<=9999999) //最大只能输入8位数
  657. {
  658. ulOther=ulOther*10+ucWhichKey;//十进制的数值移位办法。
  659. }
  660. ucDisplayUpdate=1;//改写显现窗口
  661. break;
  662. }
  663. }
  664. void T0_time() interrupt 1
  665. {
  666. TF0=0;//铲除中止标志
  667. TR0=0; //关中止
  668. key_scan(); //放在守时中止里的按键扫描函数
  669. if(uiVoiceCnt!=0)
  670. {
  671. uiVoiceCnt–; //每次进入守时中止都自减1,直到等于零中止。才中止鸣叫
  672. beep_dr=0;//蜂鸣器是PNP三极管操控,低电平就开端鸣叫。
  673. }
  674. else
  675. {
  676. ; //此处多加一个空指令,想保持跟if括号句子的数量对称,都是两条指令。不加也能够。
  677. beep_dr=1;//蜂鸣器是PNP三极管操控,高电平就中止鸣叫。
  678. }
  679. display_drive();//放在守时中止里的数码管驱动函数
  680. /* 注释五:
  681. *留意,此处的重装初始值不能太大,不然动态扫描数码管的速度就不行。我把本来常用的2000改成了500。
  682. */
  683. TH0=0xfe; //重装初始值(65535-500)=65035=0xfe0b
  684. TL0=0x0b;
  685. TR0=1;//开中止
  686. }
  687. void delay_short(unsigned int uiDelayShort)
  688. {
  689. unsigned int i;
  690. for(i=0;i
  691. {
  692. ; //一个分号相当于履行一条空句子
  693. }
  694. }
  695. void delay_long(unsigned int uiDelayLong)
  696. {
  697. unsigned int i;
  698. unsigned int j;
  699. for(i=0;i
  700. {
  701. for(j=0;j<500;j++)//内嵌循环的空指令数量
  702. {
  703. ; //一个分号相当于履行一条空句子
  704. }
  705. }
  706. }
  707. void initial_myself()//榜首区 初始化单片机
  708. {
  709. led_dr=0;
  710. beep_dr=1; //用PNP三极管操控蜂鸣器,输出高电平时不叫。
  711. hc595_drive(0x00,0x00);
  712. TMOD=0x01;//设置守时器0为工作方式1
  713. TH0=0xfe; //重装初始值(65535-500)=65035=0xfe0b
  714. TL0=0x0b;
  715. }
  716. void initial_peripheral() //第二区 初始化外围
  717. {
  718. EA=1; //开总中止
  719. ET0=1; //答应守时中止
  720. TR0=1; //发动守时中止
  721. }

总结陈词:
这节讲了加法简易计算器的程序项目。为了让读者了解运动,按键,显现是怎么有规则相关起来的,下节会持续讲一个相关的小项目程序。欲知概况,请听下回分解—–数码管作为仪表盘显现跑马灯的方向,速度和运转状况。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/fenxiao/262111.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部