基于51單片機的簡易計算器設計 單片機型號選擇STC89C52RC,讀取16*16矩陣式鍵盤對應的鍵值,可以進行五位數的加、減、乘、除運算,計算結果通過LCD1602顯示,并可通過AT24C02存儲模塊對計算結果進行存儲與調用。
實物演示
單片機源程序如下:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit rs=P2^5; //指令or數據
- sbit wela=P2^6; //讀or寫
- sbit lcden=P2^7; //使能信號
- sbit K1 = P2^3;
- sbit K2 = P2^2;
- sbit I2C_SCL = P2^1;
- sbit I2C_SDA = P2^0;
- uchar code table[]= " ";
- //uchar code XUEHAO[]= "190302051";
- long int data_a,data_b; //第一個數和第二個數
- long int data_c; //計算結果
- uchar dispaly[10]; //顯示緩沖
- //--聲明全局變量--//
- void I2C_Delay10us();
- void I2C_Start(); //起始信號:在I2C_SCL時鐘信號在高電平期間I2C_SDA信號產生一個下降沿
- void I2C_Stop(); //終止信號:在I2C_SCL時鐘信號高電平期間I2C_SDA信號產生一個上升沿
- uchar I2C_SendByte(uchar dat, uchar ack);//使用I2c讀取一個字節
- uchar I2C_ReadByte(); //通過I2C發送一個字節。在I2C_SCL時鐘信號高電平期間,保持發送信號I2C_SDA保持穩定
- void I2C_Delay10us()
- {
- uchar a, b;
- for(b=1; b>0; b--)
- {
- for(a=2; a>0; a--);
- }
- }
- void I2C_Start()
- {
- I2C_SDA = 1;
- I2C_Delay10us();
- I2C_SCL = 1;
- I2C_Delay10us();//建立時間是I2C_SDA保持時間>4.7us
- I2C_SDA = 0;
- I2C_Delay10us();//保持時間是>4us
- I2C_SCL = 0;
- I2C_Delay10us();
- }
- void I2C_Stop()
- {
- I2C_SDA = 0;
- I2C_Delay10us();
- I2C_SCL = 1;
- I2C_Delay10us();//建立時間大于4.7us
- I2C_SDA = 1;
- I2C_Delay10us();
- }
- uchar I2C_SendByte(uchar dat, uchar ack)
- {
- uchar a = 0,b = 0;//最大255,一個機器周期為1us,最大延時255us。
- for(a=0; a<8; a++)//要發送8位,從最高位開始
- {
- I2C_SDA = dat >> 7;
- dat = dat << 1;
- I2C_Delay10us();
- I2C_SCL = 1;
- I2C_Delay10us();
- I2C_SCL = 0;
- I2C_Delay10us();
- }
- I2C_SDA = 1;
- I2C_Delay10us();
- I2C_SCL = 1;
- while(I2C_SDA && (ack == 1))
- {
- b++;
- if(b > 200)
- {
- I2C_SCL = 0;
- I2C_Delay10us();
- return 0;
- }
- }
- I2C_SCL = 0;
- I2C_Delay10us();
- return 1;
- }
- uchar I2C_ReadByte()
- {
- uchar a = 0,dat = 0;
- I2C_SDA = 1; //起始和發送一個字節之后I2C_SCL都是0
- I2C_Delay10us();
- for(a=0; a<8; a++)//接收8個字節
- {
- I2C_SCL = 1;
- I2C_Delay10us();
- dat <<= 1;
- dat |= I2C_SDA;
- I2C_Delay10us();
- I2C_SCL = 0;
- I2C_Delay10us();
- }
- return dat;
- }
- void AT24C02Write(unsigned char addr,unsigned char dat)
- {
- I2C_Start();
- I2C_SendByte(0xa0, 1);//發送寫器件地址
- I2C_SendByte(addr, 1);//發送要寫入內存地址
- I2C_SendByte(dat, 0); //發送數據
- I2C_Stop();
- }
- unsigned char AT24C02Read(unsigned char addr)
- {
- unsigned char num;
- I2C_Start();
- I2C_SendByte(0xa0, 1); //發送寫器件地址
- I2C_SendByte(addr, 1); //發送要讀取的地址
- I2C_Start();
- I2C_SendByte(0xa1, 1); //發送讀器件地址
- num=I2C_ReadByte(); //讀取數據
- I2C_Stop();
- return num;
- }
- void LCD_Delay_us(unsigned int t)
- {
- while(t--); //t=0,退出
- }
- void LCD_Delay_ms(unsigned int t)
- {
- unsigned int i,j;
- for(i=0;i<t;i++) //執行t次循環
- for(j=0;j<113;j++) //執行113次循環
- ;
- }
- void write_com(uchar com) //1602液晶寫指令
- {
- rs=0; //寫指令
- lcden=0; //使能1602
- P0=com; //寫入指令com
- LCD_Delay_ms(1); //延時1ms
- lcden=1; //使能1602
- LCD_Delay_ms(2); //延時2ms
- lcden=0; //使能1602
- }
- void write_date(uchar date) //1602液晶寫數據
- {
- rs=1; //寫數據
- lcden=0; //使能1602
- P0=date; //寫入數據date
- LCD_Delay_ms(1); //延時1ms
- lcden=1; //使能1602
- LCD_Delay_ms(2); //延時2ms
- lcden=0; //使能1602
- }
- 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); //寫入數據
- }
- //指定x,y寫入字符串函數
- 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++;} //寫入數據
- }
- void init_lcd(void) //初始化液晶,及畫面初始化
- {
- wela=0; //寫液晶
- lcden=0; //使能1602
- write_com(0x38); //8 位總線,雙行顯示,5X7 的點陣字符
- LCD_Delay_us(100); //延時100us
- write_com(0x0c); //開顯示,無光標,光標不閃爍
- write_com(0x06); //光標右移動
- write_com(0x01); //清屏
- write_com(0x80); //DDRAM 地址歸0
- }
- short keycheckdown() /* 反轉法鍵盤掃描 */
- {
- short temp1,temp2,temp,a=0xff;
- P1=0xf0; /* 輸入行值(或列值) */
- LCD_Delay_ms(20); /* 延時 */
- temp1=P1; /* 讀列值(或行值) */
- P1=0xff;
- LCD_Delay_ms(20); /* 延時 */
- P1=0x0f; /* 輸入列值(或行值) */
- LCD_Delay_ms(20); /* 延時 */
- temp2=P1; /* 讀行值(或列值) */
- P1=0xff;
- temp=(temp1&0xf0)|(temp2&0xf); /* 將兩次讀入數據組合 */
- switch(temp) /* 通過讀入數據組合判斷按鍵位置 */
- {
- case 0x77 :a=0x0d;break;// 按鍵/
- case 0x7b :a=0x0e; break;// 按鍵=
- case 0x7d :a=0; break;// 按鍵0
- case 0x7e :a=0x0f; break;// 按鍵CE
- case 0xb7 :a=0x0c;break;// 按鍵*
- case 0xbb :a=0x9;break; // 按鍵9
- case 0xbd :a=0x8;break; // 按鍵8
- case 0xbe :a=0x7;break; // 按鍵7
- case 0xd7 :a=0x0b;break;// 按鍵-
- case 0xdb :a=0x6;break; // 按鍵6
- case 0xdd :a=0x5;break; // 按鍵5
- case 0xde :a=0x4;break; // 按鍵4
- case 0xe7 :a=0x0a; break;// 按鍵+
- case 0xeb :a=3;break; // 按鍵3
- case 0xed :a=2;break; // 按鍵2
- case 0xee :a=1;break; // 按鍵1
- default :a=0xff;
- }
- return a; /* 返回按鍵值 */
- }
- void display_a() //顯示數據a
- {
- dispaly[4]=data_a%100000/10000;
- dispaly[3]=data_a%10000/1000; //千
- dispaly[2]=data_a%1000/100; //百
- dispaly[1]=data_a%100/10; //十
- dispaly[0]=data_a%10; //個
- write_com(0x80+0); //顯示數據a
- if(data_a>9999){ write_date('0'+dispaly[4]); }
- 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]); //顯示個位
- }
- void display_b() //顯示數據b
- {
- write_com(0x80+7); //第一行
- dispaly[4]=data_b%100000/10000;
- dispaly[3]=data_b%10000/1000; //千
- dispaly[2]=data_b%1000/100; //百
- dispaly[1]=data_b%100/10; //十
- dispaly[0]=data_b%10; //個
- if(data_b>9999){ write_date('0'+dispaly[4]); }
- 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]); //顯示個位
- }
- void display_c(x)
- {
- if(data_c<100000000&&data_c>-1)//溢出時顯示錯誤
- {
- dispaly[8]=data_c%1000000000/100000000; //萬萬
- dispaly[7]=data_c%100000000/10000000; //千萬
- dispaly[6]=data_c%10000000/1000000; //百萬
- dispaly[5]=data_c%1000000/100000; //十萬
- dispaly[4]=data_c%100000/10000; //萬
- dispaly[3]=data_c%10000/1000; //千
- dispaly[2]=data_c%1000/100; //百
- dispaly[1]=data_c%100/10; //十
- dispaly[0]=data_c%10; //個
- write_com(0x80+6+0x40); //第一行
- if(x==4)
- {
- if(data_c>99999999) { write_date('0'+dispaly[8]);} //顯示萬萬
- if(data_c>9999999) { write_date('0'+dispaly[7]);} //千萬
- if(data_c>999999) { write_date('0'+dispaly[6]);} //百萬
- if(data_c>99999) { write_date('0'+dispaly[5]);} //十萬
- write_date('0'+dispaly[4]); //萬
- write_date('.');
- write_date('0'+dispaly[3]); //千
- write_date('0'+dispaly[2]); //百
- write_date('0'+dispaly[1]); //十
- write_date('0'+dispaly[0]); //個
- }
- else{
- if(data_c>99999999) { write_date('0'+dispaly[8]);} //顯示萬萬
- if(data_c>9999999) { write_date('0'+dispaly[7]);} //千萬
- if(data_c>999999) { write_date('0'+dispaly[6]);} //百萬
- if(data_c>99999) { write_date('0'+dispaly[5]);} //十萬
- if(data_c>9999) { write_date('0'+dispaly[4]);} //萬
- 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]); //個
- }
- }
- else //溢出時顯示錯誤
- {
- 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
- }
- }
復制代碼
原理圖: 無
仿真: 無
代碼:
程序代碼.7z
(34.48 KB, 下載次數: 11)
2023-11-28 10:27 上傳
點擊文件名下載附件
完整程序
|