当前位置:网站首页>【Proteus仿真】51单片机+LCD1602+外置存储器计算器
【Proteus仿真】51单片机+LCD1602+外置存储器计算器
2022-06-10 00:52:00 【perseverance52】
【Proteus仿真】51单片机+LCD1602+外置存储器计算器
- Proteus仿真演示

工程重要说明
- 本实例包含
Keil工程和VSM Studio工程 - LCD驱动和按键实现的驱动代码为
汇编代码。
- 本示例从Proteus示例修改而来。
仿真器件说明
- AT89C52、Intel 6264容量8KB、LM016(兼容LM020)、74ls737、与非门、
主程序代码
#include <intrins.h>
#include <reg51.h>
#include "main.h"
//Variables
static data long lvalue;
static data long rvalue;
static data char currtoken;
static data char lasttoken;
static data char lastpress;
static xdata char outputbuffer[MAX_DISPLAY_char];
void main (void)
{
lvalue = 0;
rvalue = 0;
currtoken = '=';
lasttoken = '0';
initialise(); // 汇编,初始化液晶显示器。
calc_output(OK);
calc_evaluate();
}
void calc_evaluate()
{
char data key;
int data i;
char xdata number[MAX_DISPLAY_char];
char xdata *bufferptr;
// Clear the buffer before we start.
for (i = 0; i <= MAX_DISPLAY_char; i++)
{
number[i] = ' ';
}
bufferptr = number;
for (;;)
{
key = calc_getkey();
if (calc_testkey(key))
// Key test positive for digit so we read it into the
// buffer and then write the buffer to the screen/LCD.
// Size limit the number of digits - allow for termination
// and possible negative results.
{
if (bufferptr != &number[MAX_DISPLAY_char - 2])
{
*bufferptr = key;
calc_display(number);
bufferptr++;
}
}
else
// Key is an operator so pass it to the function handlers.
// If we are just after startup or cancel then assign to lvalue
// otherwise assign to rvalue.
{
//Assign the value.
if (lasttoken == '0')
{
lvalue = calc_asciidec (number);}
else
{
rvalue = calc_asciidec (number);}
//Clear the number buffer.
bufferptr = number;
for (i = 0;i <= MAX_DISPLAY_char; i++)
{
number[i] = ' '; }
//Process the Operator.
currtoken = key;
if (currtoken == 'C')
{
calc_opfunctions(currtoken); }
else
{
calc_opfunctions(lasttoken); }
// Clear the outputbuffer for reuse on next operation.
for (i = 0;i <= MAX_DISPLAY_char;i++)
{
outputbuffer[i] = ' ';}
bufferptr = number;
// Handle the equals operation here for brevity.
// All we need do is preserve the previous operator in
// lasttoken.
if (currtoken != 0x3D) lasttoken = currtoken;
}
lastpress = key;
}
}
void calc_opfunctions (char token)
// Handle the operations. Lvalue holds the result and we test for
// consecutive operator presses.
{
char data result;
switch(token)
// Add.
{
case '+' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress <=0x39)))
{
lvalue += rvalue;
result = calc_chkerror(lvalue);
}
else
{
result = SLEEP; } break;
// Subtract.
case '-' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress <=0x39)))
{
lvalue -= rvalue;
result = calc_chkerror(lvalue);
}
else
{
result = SLEEP;} break;
// Multiply.
case '*' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress <=0x39)))
{
lvalue *= rvalue;
result = calc_chkerror(lvalue);
}
else
{
result = SLEEP;} break;
// Divide.
case '/' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress <=0x39)))
{
if (rvalue)
{
lvalue /= rvalue;
result = calc_chkerror(lvalue);
}
else
{
result = ERROR;}
}
else
{
result = SLEEP;} break;
// Cancel.
case 'C' : lvalue = 0;
rvalue = 0;
currtoken = '0';
lasttoken = '0';
result = OK; break;
default : result = SLEEP;
}
calc_output(result);
}
/************************************************************************ ***** Utility Routines ***** ***************************/
int calc_chkerror (long num)
// Check upper and lower bounds for the display.
// i.e. 99999999 and -99999999.
{
if ((num >= -9999999) && (num <= 9999999))
return OK;
else
return ERROR;
}
void calc_output (int status)
// Output according to the status of the operation.
// *Sleep* is used for the first op press after a full cancel
// or on startup.
{
switch (status)
{
case OK : calc_display(calc_decascii(lvalue)); break;
case SLEEP : break;
case ERROR : calc_display("Exception "); break;
default : calc_display("Exception "); break;
}
}
long calc_asciidec (char *buffer)
// Convert the ASCII string into the floating point number.
{
long data value;
long data digit;
value = 0;
while (*buffer != ' ')
{
digit = *buffer - 48;
value = value*10 + digit;
buffer++;
}
return value;
}
char *calc_decascii (long num)
// A rather messy function to convert a floating
// point number into an ASCII string.
{
long data temp = num;
char xdata *arrayptr = &outputbuffer[MAX_DISPLAY_char];
long data divisor = 10;
long data result;
char data remainder,asciival;
int data i;
// If the result of the calculation is zero
// insert a zero in the buffer and finish.
if (!temp)
{
*arrayptr = 48;
goto done;
}
// Handle Negative Numbers.
if (temp < 0)
{
outputbuffer[0] = '-';
temp -= 2*temp;
}
for (i=0 ; i < sizeof(outputbuffer) ; i++)
{
remainder = temp % divisor;
result = temp / divisor;
// If we run off the end of the number insert a space into
// the buffer.
if ((!remainder) && (!result))
{
*arrayptr = ' ';}
// We're in business - store the digit offsetting
// by 48 decimal to account for the ascii value.
else
{
asciival = remainder + 48;
*arrayptr = asciival;
}
temp /= 10;
// Save a place for a negative sign.
if (arrayptr != &outputbuffer[1]) arrayptr--;
}
done: return outputbuffer;
}
char calc_testkey (char key)
// Test whether the key is a digit or an operator. Return 1 for digit, 0 for op.
{
if ((key >= 0x30) && (key <= 0x39))
{
return 1;}
else
{
return 0;}
}
/************************************************************************ ***** I/O Routines ***** ***********************/
char calc_getkey (void)
// Use the input routine from the *Keypad_Read* assembly file to
// Scan for a key and return ASCII value of the Key pressed.
{
char data mykey;
do mykey = input();
while (mykey == 0);
return mykey;
}
void calc_display (char buf[MAX_DISPLAY_char])
// Use the Output and Clearscreen routines from the
// *LCD_Write* assembly file to output ASCII values to the LCD.
{
int data i = 0;
clearscreen();
for (i ; i <= MAX_DISPLAY_char ; i++)
{
if (buf[i] != ' ')
{
output(buf[i]); }
}
}
程序源码和仿真资源
本实验基于
Proteus8.12平台。
链接:https://pan.baidu.com/s/1pD4H8_-J7i1dIdmbxD3Tbw
提取码:rc71
| 不经一番寒彻骨,怎得梅花扑鼻香。--黄蘖禅师《上堂开示颂》 |
|---|
边栏推荐
- Sword finger offer II 016 Longest substring without duplicate characters
- 把 GPL 视作“病毒”?请停止污名化 GPL
- 剑指 Offer II 014. 字符串中的变位词
- 洛谷P2657 [SCOI2009]windy数 题解 数位DP
- How to implement complex SQL such as distributed database sub query and join?
- Asia's premier Web3 event "token2049 Singapore" announced its title sponsor
- 依赖自动装配
- 总结——》【JVM】
- Sword finger offer II 019 Delete at most one character to get a palindrome
- JVM——》类编译过程
猜你喜欢

Cocoscreator old, live and new - synthetic large zongzi

为什么程序员干两年就跑路?

Sword finger offer II 014 Anagrams in strings

How to implement complex SQL such as distributed database sub query and join?

余压监控系统在某高层住宅的应用方案

A junior college programmer in hupiao, he worked out with liuzhenhong while taking 22K offers

Node-RED系列(二六):使用dashboard节点开发常见的表格搜索布局

第6章域控制器安全

星环科技科创板IPO过会:毛利率维持较高水平,腾讯等为主要股东

MySQL - separate database and table
随机推荐
xargs命令详解,xargs与管道的区别
Can the online security of futures account opening be guaranteed? Which futures company is good?
shell eval用法详解 命令替换
剑指 Offer II 013. 二维子矩阵的和
FPGA-VGA显示
MySQL transaction
我的创作纪念日
Unity technology - 2D project experience
Mysql——》如何解决数据的读一致性问题
Spanning tree protocol summary
Dependent auto assembly
Fpga-vga display
MySQL - view index size
Pycharm 2022 permanently activated version download, valid for personal test
Wyn enterprise, an embedded business intelligence software, has officially entered the V5.0 era!
Source code analysis of Tencent libco collaboration open source library (I) -- download libco compilation and installation and try to run the sample code
[GoogleCTF2019 Quals]Bnv -S
Sword finger offer II 019 Delete at most one character to get a palindrome
Sword finger offer II 014 Anagrams in strings
洛谷P1220 关路灯 题解 区间DP