|
簡易答題計(jì)算器
1) 采用LCD1602或者LCD12864液晶屏顯示。
2) 預(yù)計(jì)20道簡易加、減、乘、除的運(yùn)算式,隨機(jī)顯示其中一道運(yùn)算式進(jìn)行答題。
3) 使用4*4矩陣鍵盤輸入答案并顯示。
4) 判斷答案正確與否
5) 發(fā)揮部分: 其他創(chuàng)新功能。
單片機(jī)答題計(jì)算器仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
單片機(jī)源程序如下:
- #include <reg51.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "key.h"
- #include "delay.h"
- #include "LCD1602.h"
- typedef unsigned char u8;
- typedef unsigned short u16;
- void main()
- {
- u8 key_down = 0; //按鍵是否按下
- u16 key_cnt = 0; //持續(xù)按鍵計(jì)數(shù)
- char key_bak = -1; //上次掃描的按鍵信息
- char key = -1; //此次掃描的按鍵信息
- LCD_Initial();//LCD初始化
- new_q ();
-
- while(1)
- {
- key = ScanKey(); //掃描鍵盤
- if(key) //此次按鍵有效
- {
- if(!key_down) //未曾按下鍵
- {
- key_down = 1;
- PressKey(key);// 處理按鍵值
- }
- }
- else //無按鍵信息
- {
- key_down = 0; //按下鍵標(biāo)志清零
- }
- key_bak = key; //保存此次按鍵值
- Render(); //刷新顯示屏
- }
- }
復(fù)制代碼- #include <reg51.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "LCD1602.h"
- #include "key.h"
- #include "delay.h"
- #include "LCD1602.h"
- typedef unsigned char u8;
- typedef unsigned short u16;
- void Update();
- enum {PLUS = 1, MINUS, TIME, DIVIDE};
- float input;
- //矩陣鍵盤排列
- char code key_map[4][4] =
- {
- '7', '8', '9', ' ', //鍵盤對(duì)應(yīng)順序表
- '4', '5', '6', ' ',
- '1', '2', '3', ' ',
- '0', 'C', '=', ' ',
- };
- u8 code disp_num[10] = {'0','1','2','3','4','5','6','7','8','9',};
- u8 disp_buf[16] = " "; //顯示緩沖區(qū)
- u8 disp_buf2[16] = " "; //顯示緩沖區(qū)
- //計(jì)算器操作
- float op_a = 0.0f; //操作數(shù)A,數(shù)碼管顯示的都是op_a
- float op_b = 0.0f; //操作數(shù)B
- u8 op_m = 0; //運(yùn)算方式
- //輔助操作
- u8 z;
- void new_q ();//數(shù)學(xué)運(yùn)算
- float Calc(float a, float b, u8 op)
- {
- float result = 0.0f;
- switch(op)
- {
- case 1: result = a + b; break;
- case 2: result = a - b; break;
- case 3: result = a * b; break;
- case 4: result = a / b; break;
- }
- return result;
- }
- ////////////////////////////////////////////////////////////////////////////////
- //按下數(shù)字鍵
- void PressN(unsigned char num)
- {
- float tmp;
- tmp = input * 10 + num;
- input = tmp; //保存當(dāng)前數(shù)據(jù)
-
- }
- //按下等于號(hào),執(zhí)行運(yùn)算
- void PressEQ()
- {
- if (input == Calc(op_a, op_b, op_m)) // 計(jì)算
- {
- disp_buf[7]=' ';
- disp_buf[8]='Y';
- disp_buf[9]='E';
- disp_buf[10]='S';
- disp_buf[15]=' ';
- }
- else
- {
- disp_buf[7]='N';
- disp_buf[8]='O';
- }
- }
- //鍵盤掃描,無按鍵返回0
- char ScanKey()
- {
- char ret = 0;
- u8 key;
- u8 line, row;//line行,row列
- do
- {
- P2 = 0x0f; //掃描列
- key =P2;
- if(key == 0x0f) break; //沒有鍵按下
- //有鍵按下
- delay(10); //延時(shí)消除抖動(dòng)
- key = P2; //再次讀端口值
- if(key == 0x0f) break; //沒有鍵按下
- switch(key) //有鍵按下,記錄行值
- {
- case 0x07: line = 0; break;
- case 0x0b: line = 1; break;
- case 0x0d: line = 2; break;
- case 0x0e: line = 3; break;
- }
- P2 = 0xf0; //掃描行
- key = P2;
- if(key == 0xf0) break; //沒有鍵按下
- //有鍵按下
- delay(10); //延時(shí)消除抖動(dòng)
- key = P2; //再次讀端口值
- if(key == 0xf0) break; //沒有鍵按下
- switch(key) //有鍵按下,記錄列值
- {
- case 0x70: row = 3; break;
- case 0xb0: row = 2; break;
- case 0xd0: row = 1; break;
- case 0xe0: row = 0; break;
- }
- //查找對(duì)應(yīng)的鍵值
- ret = key_map[line][row]; // 行列
- } while(0);
- return ret;
- }
- void clear ()
- {
- u8 i;
- input = 0.0f;
- z=0;
- for(i=0;i<16;i++)
- disp_buf[i] =' ';
- }
- //按鍵操作
- void PressKey(char key)
- {
- if((key!='=') && (key!=' ')) // 數(shù)字鍵檢測 用于在屏上顯示 輸入的數(shù)字
- {
- disp_buf[z++]=key; //加載顯示值
- }
- switch(key)
- {
- case '0': case '1': case '2': case '3': case '4': //0-9 屬于數(shù)字鍵進(jìn)行數(shù)字處理
- case '5': case '6': case '7': case '8': case '9':
- PressN(key - '0');
- break;
- case '=': PressEQ(); break;
- case ' ': new_q(); break;
-
- case 'C': clear(); break;
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- //把浮點(diǎn)數(shù)值轉(zhuǎn)換成字符串形式放到s中,返回小數(shù)點(diǎn)位置
- void Format(float val, char *s)
- {
- int dot = 0;
- char *p = NULL;//NULL 表示未定義內(nèi)容
- //格式化字符串
- sprintf(s, "%-8g", val); //把ual 變成字符存放到S
- // 去掉后面的空格
- p = strchr(s, ' ');
- if(p) *p = 0;
- }
- //將當(dāng)前操作數(shù)轉(zhuǎn)換成字符形式放到顯示緩沖區(qū)中
- void Update_question()
- {
- char idata s[16] = "";
- int len1,len2;
- int i;
- memset(disp_buf2, ' ', sizeof(disp_buf2)); //把DISP BUF 內(nèi)存給' ' sizeof(disp_buf)測量disp_buf 容量
- //當(dāng)前操作數(shù)轉(zhuǎn)換成可顯示的字符串
- Format(op_a, s); //計(jì)算小數(shù)點(diǎn)位置
- len1 = strlen(s); // 計(jì)算字符串長度
-
- //可顯示的字符串逆序放到顯示緩沖區(qū)中
- for(i=0; i<len1; i++)
- {
- disp_buf2[i]=s[i];
- }
- switch (op_m)
- {
- case 1:
- disp_buf2[len1] = '+';
- break;
- case 2:
- disp_buf2[len1] = '-';
- break;
- case 3:
- disp_buf2[len1] = '*';
- break;
- case 4:
- disp_buf2[len1] = '/';
- break;
- }
- //當(dāng)前操作數(shù)轉(zhuǎn)換成可顯示的字符串
- Format(op_b, s); //計(jì)算小數(shù)點(diǎn)位置
- len2 = strlen(s); // 計(jì)算字符串長度
- for(i=len1+1; i<len2+len1+1; i++)
- {
- disp_buf2[i]=s[i-len1-1];
- }
- GotoXY(0,0);
- PrintLCD(disp_buf2);
- }
- //將顯示緩沖區(qū)的內(nèi)容顯示到數(shù)碼管上
- void Render()
- {
- GotoXY(0,1);
- PrintLCD(disp_buf);
- }
- int code question[20][3] =//題目
- {
- 2,3,PLUS,//+
- 6,8,PLUS,//+
- 36,24,PLUS,//+
- 32,2,PLUS,//+
- 16,20,PLUS,//+
- 20,15,MINUS,//-
- 40,5,MINUS,//-
- 10,5,MINUS,
- 30,6,MINUS,//-
- 50,25,MINUS,//-
- 12,2,TIME,//*
- 6,5,TIME,//*
- 7,7,TIME,//*
- 4,9,TIME,//*
- 12,8,TIME,//*
- 10,2,DIVIDE,//÷
- 16,4,DIVIDE,//÷
- 50,25,DIVIDE,//÷
- 99,33,DIVIDE,//÷
- 64,16,DIVIDE,//÷
- };
- void new_q ()
- {
- char i = rand()%20;
- op_a = question[i][0];
- op_b = question[i][1];
- op_m = question[i][2];
- Update_question();
- clear();
- }
復(fù)制代碼
所有資料51hei提供下載:
基于單片機(jī)設(shè)計(jì)的答題計(jì)算器.rar
(217.94 KB, 下載次數(shù): 27)
2019-4-15 07:48 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|