标题:
c51单片机答题计算器Proteus仿真+程序设计
[打印本页]
作者:
Danshans
时间:
2019-4-15 07:48
标题:
c51单片机答题计算器Proteus仿真+程序设计
简易答题计算器
1) 采用LCD1602或者LCD12864液晶屏显示。
2) 预计20道简易加、减、乘、除的运算式,随机显示其中一道运算式进行答题。
3) 使用4*4矩阵键盘输入答案并显示。
4) 判断答案正确与否
5) 发挥部分: 其他创新功能。
单片机答题计算器仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png
(14.69 KB, 下载次数: 21)
下载附件
2019-4-15 13:36 上传
单片机源程序如下:
#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; //持续按键计数
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; //按下键标志清零
}
key_bak = key; //保存此次按键值
Render(); //刷新显示屏
}
}
复制代码
#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', ' ', //键盘对应顺序表
'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] = " "; //显示缓冲区
u8 disp_buf2[16] = " "; //显示缓冲区
//计算器操作
float op_a = 0.0f; //操作数A,数码管显示的都是op_a
float op_b = 0.0f; //操作数B
u8 op_m = 0; //运算方式
//辅助操作
u8 z;
void new_q ();//数学运算
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;
}
////////////////////////////////////////////////////////////////////////////////
//按下数字键
void PressN(unsigned char num)
{
float tmp;
tmp = input * 10 + num;
input = tmp; //保存当前数据
}
//按下等于号,执行运算
void PressEQ()
{
if (input == Calc(op_a, op_b, op_m)) // 计算
{
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); //延时消除抖动
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); //延时消除抖动
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;
}
//查找对应的键值
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!=' ')) // 数字键检测 用于在屏上显示 输入的数字
{
disp_buf[z++]=key; //加载显示值
}
switch(key)
{
case '0': case '1': case '2': case '3': case '4': //0-9 属于数字键进行数字处理
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;
}
}
////////////////////////////////////////////////////////////////////////////////
//把浮点数值转换成字符串形式放到s中,返回小数点位置
void Format(float val, char *s)
{
int dot = 0;
char *p = NULL;//NULL 表示未定义内容
//格式化字符串
sprintf(s, "%-8g", val); //把ual 变成字符存放到S
// 去掉后面的空格
p = strchr(s, ' ');
if(p) *p = 0;
}
//将当前操作数转换成字符形式放到显示缓冲区中
void Update_question()
{
char idata s[16] = "";
int len1,len2;
int i;
memset(disp_buf2, ' ', sizeof(disp_buf2)); //把DISP BUF 内存给' ' sizeof(disp_buf)测量disp_buf 容量
//当前操作数转换成可显示的字符串
Format(op_a, s); //计算小数点位置
len1 = strlen(s); // 计算字符串长度
//可显示的字符串逆序放到显示缓冲区中
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;
}
//当前操作数转换成可显示的字符串
Format(op_b, s); //计算小数点位置
len2 = strlen(s); // 计算字符串长度
for(i=len1+1; i<len2+len1+1; i++)
{
disp_buf2[i]=s[i-len1-1];
}
GotoXY(0,0);
PrintLCD(disp_buf2);
}
//将显示缓冲区的内容显示到数码管上
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();
}
复制代码
0.png
(7.58 KB, 下载次数: 33)
下载附件
2019-4-15 13:38 上传
所有资料51hei提供下载:
基于单片机设计的答题计算器.rar
(217.94 KB, 下载次数: 27)
2019-4-15 07:48 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1