目錄
一、設(shè)計(jì)背景
二、實(shí)現(xiàn)功能
三、硬件設(shè)計(jì)
3.1 總體硬件設(shè)計(jì)
?3.2 鍵盤(pán)電路的設(shè)計(jì)
3.3 顯示電路的設(shè)計(jì)
?四、仿真演示
?五、源程序
一、設(shè)計(jì)背景
? ? ? ?隨著社會(huì)的發(fā)展,科學(xué)的進(jìn)步,人們的生活水平在逐步的提高,尤其是微電子技術(shù)的發(fā)展,猶如雨后春筍般的變化。電子產(chǎn)品的更新速度快就不足驚奇了。計(jì)算器在人們的日常中是比較的常見(jiàn)的電子產(chǎn)品之一。如何使計(jì)算器技術(shù)更加的成熟,充分利用已有的軟件和硬件條件,設(shè)計(jì)出更出色的計(jì)算器,使其更好的為各個(gè)行業(yè)服務(wù),成了如今電子領(lǐng)域重要的研究課題。
二、實(shí)現(xiàn)功能
? ? ?本設(shè)計(jì)是以AT89C51單片機(jī)為核心的計(jì)算器模擬系統(tǒng)設(shè)計(jì),輸入采用4×4矩陣鍵盤(pán),可以進(jìn)行加、減、乘、除4位帶符號(hào)數(shù)字運(yùn)算,最大運(yùn)算是可達(dá)9999*9999,可以運(yùn)算負(fù)數(shù),并在LCD1602上顯示操作過(guò)程。
三、硬件設(shè)計(jì)
3.1 總體硬件設(shè)計(jì)
為了更好的實(shí)現(xiàn)系統(tǒng)得功能,硬件電路的設(shè)計(jì)應(yīng)該遵循以下原則:
1、優(yōu)化硬件電路
? ? ? 采用軟件設(shè)計(jì)與硬件設(shè)計(jì)相結(jié)合的方法;盡管采用軟件來(lái)實(shí)現(xiàn)硬件系統(tǒng)的功能時(shí),也許響應(yīng)時(shí)間會(huì)比單純使用硬件時(shí)長(zhǎng),而且還要占用微處理器(MCU)的時(shí)間;但是,用軟件實(shí)現(xiàn)硬件的功能可以簡(jiǎn)化硬件結(jié)構(gòu),提高電路的可靠性。所以,在設(shè)計(jì)本系統(tǒng)得時(shí)候,在滿足可靠性和實(shí)時(shí)性的前提下,盡可能的通過(guò)軟件來(lái)實(shí)現(xiàn)硬件功能。
2、可靠性及抗干擾設(shè)計(jì)
? ? ? 根據(jù)可靠性設(shè)計(jì)理論,系統(tǒng)所用芯片數(shù)量越少,系統(tǒng)的平均無(wú)故障時(shí)間越長(zhǎng)。而且,所用芯片數(shù)量越少,地址和數(shù)據(jù)總線在電路板上受干擾的可能性也就越小。因此,系統(tǒng)的設(shè)計(jì)思想是在滿足功能的情況下力爭(zhēng)使用較少數(shù)量的芯片。
3、靈活的功能擴(kuò)展
? ? ?功能擴(kuò)展是否靈活是衡量一個(gè)系統(tǒng)優(yōu)劣的重要指標(biāo)。一次設(shè)計(jì)往往不能完全考慮到系統(tǒng)的各個(gè)方面,系統(tǒng)需要不斷完善以及進(jìn)行功能升級(jí)。進(jìn)行功能擴(kuò)展時(shí),應(yīng)該在原有設(shè)計(jì)的基礎(chǔ)上,通過(guò)修改軟件程序和少量硬件完成。對(duì)于本系統(tǒng)而言,就是要求在系統(tǒng)硬件不變的情況下,能夠通過(guò)修改軟件程序,完成功能的升級(jí)和擴(kuò)展。
? ? ?根據(jù)第提出的系統(tǒng)設(shè)計(jì)方案,結(jié)合以上三條原則,確定了系統(tǒng)硬件的設(shè)計(jì)。計(jì)算器主要由以下一些功能模塊構(gòu)成:非編碼鍵盤(pán)模塊、LCD液晶顯示屏模塊等。
下圖為總體硬件結(jié)構(gòu)。
3.2 鍵盤(pán)電路的設(shè)計(jì)
? ? ? ?鍵盤(pán)可分為兩類:編碼鍵盤(pán)和非編碼鍵盤(pán)。編碼鍵盤(pán)是較多按鍵(20個(gè)以上)和專用驅(qū)動(dòng)芯片的組合,當(dāng)按下某個(gè)按鍵時(shí),它能夠處理按鍵抖動(dòng)、連擊等問(wèn)題,直接輸出按鍵的編碼,無(wú)需系統(tǒng)軟件干預(yù)。通用計(jì)算機(jī)使用的標(biāo)準(zhǔn)鍵盤(pán)就是編碼鍵盤(pán)。在智能儀器中,使用并行接口芯片8279或串行接口芯片HD7279均可以組成編碼鍵盤(pán),同時(shí)還可以兼顧數(shù)碼管的顯示驅(qū)動(dòng),其相關(guān)的接口電路和接口軟件均可在芯片資料中得到。當(dāng)系統(tǒng)功能比較復(fù)雜,按鍵數(shù)量很多時(shí),采用編碼鍵盤(pán)可以簡(jiǎn)化軟件設(shè)計(jì)。從成本角度出發(fā),本設(shè)計(jì)選用的是非編碼鍵盤(pán)。如下圖所示:
3.3 顯示電路的設(shè)計(jì)
? ? ? ?當(dāng)系統(tǒng)需要顯示少量數(shù)據(jù)時(shí),采用LCD液晶顯示屏進(jìn)行顯示是一種經(jīng)濟(jì)實(shí)用的方法。P0口作為液晶顯示的數(shù)據(jù)端口,P3.5-P3.7口作為其控制端口,控制LCD液晶顯示屏顯示輸出數(shù)據(jù)。如下圖所示:
?四、仿真演示
初始界面
?加運(yùn)算
減運(yùn)算
乘運(yùn)算
除運(yùn)算
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-481489.html
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-481489.html
五、源程序
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
//--------LCD1602-------------------
//P00-07==== D0-7
sbit rs=P2^7; //指令or數(shù)據(jù)
sbit wela=P2^6; //讀or寫(xiě)
sbit lcden=P2^5; //使能信號(hào)
//--------LCD1602-------------------
//--------KEY-----------------------
//P1口
//--------KEY-----------------------
uchar code table[]= " ";
long int data_a,data_b; //第一個(gè)數(shù)和第二個(gè)數(shù)
long int data_c; //計(jì)算結(jié)果
uchar dispaly[10]; //顯示緩沖
//************************************************************************/
// 描述: 延時(shí)t us函數(shù)
//************************************************************************/
void LCD_Delay_us(unsigned int t)
{
while(t--); //t=0,退出
}
//************************************************************************/
// 描述: 延時(shí)t ms函數(shù)
//************************************************************************/
void LCD_Delay_ms(unsigned int t)
{
unsigned int i,j;
for(i=0;i<t;i++) //執(zhí)行t次循環(huán)
for(j=0;j<113;j++) //執(zhí)行113次循環(huán)
;
}
//************************************************************************/
// 描述: 1602液晶寫(xiě)指令
//************************************************************************/
void write_com(uchar com) //1602液晶寫(xiě)指令
{
rs=0; //寫(xiě)指令
lcden=0; //使能1602
P0=com; //寫(xiě)入指令com
LCD_Delay_ms(1); //延時(shí)1ms
lcden=1; //使能1602
LCD_Delay_ms(2); //延時(shí)2ms
lcden=0; //使能1602
}
//************************************************************************/
// 描述:1602液晶寫(xiě)數(shù)據(jù)
//************************************************************************/
void write_date(uchar date) //1602液晶寫(xiě)數(shù)據(jù)
{
rs=1; //寫(xiě)數(shù)據(jù)
lcden=0; //使能1602
P0=date; //寫(xiě)入數(shù)據(jù)date
LCD_Delay_ms(1); //延時(shí)1ms
lcden=1; //使能1602
LCD_Delay_ms(2); //延時(shí)2ms
lcden=0; //使能1602
}
//************************************************************************/
// 描述:指定x,y寫(xiě)入字符函數(shù)
//************************************************************************/
void W_lcd(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0){write_com(0x80 + x);} //第一行
else{write_com(0xc0 + x);} //第二行
write_date( Data); //寫(xiě)入數(shù)據(jù)
}
//指定x,y寫(xiě)入字符串函數(shù)
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0){write_com(0x80 + x);} //第一行
else{write_com(0xC0 + x);} //第二行
while (*s) //
{write_date( *s); s++;} //寫(xiě)入數(shù)據(jù)
}
//************************************************************************/
// 描述:初始化液晶,及畫(huà)面初始化
//************************************************************************/
void init_lcd(void) //初始化液晶,及畫(huà)面初始化
{
wela=0; //寫(xiě)液晶
lcden=0; //使能1602
write_com(0x38); //8 位總線,雙行顯示,5X7 的點(diǎn)陣字符
LCD_Delay_us(100); //延時(shí)100us
write_com(0x0c); //開(kāi)顯示,無(wú)光標(biāo),光標(biāo)不閃爍
write_com(0x06); //光標(biāo)右移動(dòng)
write_com(0x01); //清屏
write_com(0x80); //DDRAM 地址歸0
}
//************************************************************************/
// 描述: 反轉(zhuǎn)法鍵盤(pán)掃描
//************************************************************************/
short keycheckdown() /* 反轉(zhuǎn)法鍵盤(pán)掃描 */
{
short temp1,temp2,temp,a=0xff;
P1=0xf0; /* 輸入行值(或列值) */
LCD_Delay_ms(20); /* 延時(shí) */
temp1=P1; /* 讀列值(或行值) */
P1=0xff;
LCD_Delay_ms(20); /* 延時(shí) */
P1=0x0f; /* 輸入列值(或行值) */
LCD_Delay_ms(20); /* 延時(shí) */
temp2=P1; /* 讀行值(或列值) */
P1=0xff;
temp=(temp1&0xf0)|(temp2&0xf); /* 將兩次讀入數(shù)據(jù)組合 */
switch(temp) /* 通過(guò)讀入數(shù)據(jù)組合判斷按鍵位置 */
{
case 0x77 :a=0x0a;break;// 按鍵+
case 0x7b :a=0x0e; break;// 按鍵=
case 0x7d :a=0; break;// 按鍵0
case 0x7e :a=0x0f; break;// 按鍵CE
case 0xe7 :a=0x0d;break;// 按鍵/
case 0xeb :a=0x9;break; // 按鍵9
case 0xed :a=0x8;break; // 按鍵8
case 0xee :a=0x7;break; // 按鍵7
case 0xd7 :a=0x0c;break;// 按鍵*
case 0xdb :a=0x6;break; // 按鍵6
case 0xdd :a=0x5;break; // 按鍵5
case 0xde :a=0x4;break; // 按鍵4
case 0xb7 :a=0x0b; break;// 按鍵-
case 0xbb :a=3;break; // 按鍵3
case 0xbd :a=2;break; // 按鍵2
case 0xbe :a=1;break; // 按鍵1
default :a=0xff;
}
return a; /* 返回按鍵值 */
}
void display_a() //顯示數(shù)據(jù)a
{
dispaly[3]=data_a%10000/1000; //千
dispaly[2]=data_a%1000/100; //百
dispaly[1]=data_a%100/10; //十
dispaly[0]=data_a%10; //個(gè)
write_com(0x80+0); //顯示數(shù)據(jù)a
if(data_a>999){ write_date('0'+dispaly[3]);} //顯示千位
if(data_a>99){ write_date('0'+dispaly[2]);} //顯示百位
if(data_a>9){ write_date('0'+dispaly[1]);} //顯示十位
write_date('0'+dispaly[0]); //顯示個(gè)位
}
void display_b() //顯示數(shù)據(jù)b
{
write_com(0x80+7); //第一行
dispaly[3]=data_b%10000/1000; //千
dispaly[2]=data_b%1000/100; //百
dispaly[1]=data_b%100/10; //十
dispaly[0]=data_b%10; //個(gè)
if(data_b>999){ write_date('0'+dispaly[3]); } //顯示千位
if(data_b>99) { write_date('0'+dispaly[2]); } //顯示百位
if(data_b>9) { write_date('0'+dispaly[1]); } //顯示十位
write_date('0'+dispaly[0]); //顯示個(gè)位
}
//計(jì)算結(jié)果
void display_c(x)
{
if(data_c<100000000&&data_c>-1)//溢出時(shí)顯示錯(cuò)誤
{
dispaly[8]=data_c%1000000000/100000000; //萬(wàn)萬(wàn)
dispaly[7]=data_c%100000000/10000000; //千萬(wàn)
dispaly[6]=data_c%10000000/1000000; //百萬(wàn)
dispaly[5]=data_c%1000000/100000; //十萬(wàn)
dispaly[4]=data_c%100000/10000; //萬(wàn)
dispaly[3]=data_c%10000/1000; //千
dispaly[2]=data_c%1000/100; //百
dispaly[1]=data_c%100/10; //十
dispaly[0]=data_c%10; //個(gè)
write_com(0x80+6+0x40); //第一行
if(x==4)
{
if(data_c>99999999) { write_date('0'+dispaly[8]);} //顯示萬(wàn)萬(wàn)
if(data_c>9999999) { write_date('0'+dispaly[7]);} //千萬(wàn)
if(data_c>999999) { write_date('0'+dispaly[6]);} //百萬(wàn)
if(data_c>99999) { write_date('0'+dispaly[5]);} //十萬(wàn)
if(data_b!=0) {
write_date('0'+dispaly[4]); //萬(wàn)
write_date('.');
write_date('0'+dispaly[3]); //千
write_date('0'+dispaly[2]); //百
write_date('0'+dispaly[1]); //十
write_date('0'+dispaly[0]); //個(gè)
}
}
else{
if(data_c>99999999) { write_date('0'+dispaly[8]);} //顯示萬(wàn)萬(wàn)
if(data_c>9999999) { write_date('0'+dispaly[7]);} //千萬(wàn)
if(data_c>999999) { write_date('0'+dispaly[6]);} //百萬(wàn)
if(data_c>99999) { write_date('0'+dispaly[5]);} //十萬(wàn)
if(data_c>9999) { write_date('0'+dispaly[4]);} //萬(wàn)
if(data_c>999) { write_date('0'+dispaly[3]);} //千
if(data_c>99) { write_date('0'+dispaly[2]);} //百
if(data_c>9) { write_date('0'+dispaly[1]);} //十
write_date('0'+dispaly[0]); //個(gè)
}
}
// else //溢出時(shí)顯示錯(cuò)誤
// {
// write_com(0x80+11+0x40); //第一行
// write_date('E'); //顯示 E
// write_date('r'); //顯示R
// write_date('r'); //顯示R
// write_date('o'); //顯示O
// write_date('r'); //顯示E
// }
}
void eql(uchar x)//加減乘除運(yùn)算
{
switch(x) /*功能鍵選擇*/
{
case 1:data_c=data_a+data_b;break; //加 /* + S=1 */ /* 數(shù)值轉(zhuǎn)換函數(shù) */
case 2:if(data_a>=data_b){data_c=data_a-data_b;} /* - S=2 *///減
else{data_c=data_b-data_a;W_lcd(5,1,'-');} //負(fù)數(shù)符號(hào)
break;
case 3:data_c=(data_a*data_b);break; /* * S=3 *///乘
case 4:if(data_b==0){LCD_Write_String(0,1,"Error ! ");}else{data_c=(data_a*10000)/data_b;}break; /* / S=4 *///除//溢出時(shí)顯示錯(cuò)誤
case 0:break;
}
}
void main()
{
uchar key=0xff; //鍵值初始化
uchar n=0; //第1個(gè)數(shù)可以按1-4次
uchar m=5; //第2個(gè)數(shù)可以按1-4次
uchar x=0;
data_a=0; //前一個(gè)數(shù)
data_b=0; //后一個(gè)數(shù)
data_c=0; //結(jié)果
init_lcd(); //1602液晶初始化
display_a();
while(1)
{
key=keycheckdown(); /*動(dòng)態(tài)掃描鍵盤(pán),返回按鍵對(duì)應(yīng)值,賦給j key=0到f */
if(0xff!=key) /*若返回值有效,進(jìn)入內(nèi)部處理程序*/
{
if(key<10)
{
if(key==0&&n==0) ;
else
{
if(n<4){data_a=data_a*10+key;m=5;display_a();}n++; //首先輸入第一個(gè)數(shù)
}
if(key==0&&m==0) ;
else
{
if(m<4){data_b=data_b*10+key;n=5;display_b();}m++; //必須按了+-*/才能輸入第二個(gè)數(shù)
}
}
else
{ switch(key) /*功能鍵選擇*/
{
case 0xa:n=5;m=0;x=1;W_lcd(5,0,'+');break; //加 /* + S=1 */ /* 數(shù)值轉(zhuǎn)換函數(shù) */
case 0xb:n=5;m=0;x=2;W_lcd(5,0,'-');break; /* - S=2 *///減
case 0xc:n=5;m=0;x=3;W_lcd(5,0,'*');break; /* * S=3 *///乘
case 0xd:n=5;m=0;x=4;W_lcd(5,0,'/');break; /* / S=4 *///除
case 0xe:n=5;m=5;eql(x);W_lcd(12,0,'=');display_c(x);break; /* = */
case 0xf:n=0;x=0;m=5; data_a=0;data_b=0;data_c=0;LCD_Write_String(0,0,table);LCD_Write_String(0,1,table);W_lcd(0,0,'0');break; /* C*/
}
}
do{P1=0xf0;}while(P1!=0xf0); /*等待按鍵松開(kāi)*/
}//(0xff!=key)
}//while
}//main
到了這里,關(guān)于基于51單片機(jī)的智能計(jì)算器Protues仿真設(shè)計(jì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!