Ⅰ 單片機的簡易計算器
單片機計算器
基本功能介紹:
簡單的加減乘除的運算。
時間顯示功能,而且能實現計算器模塊和時間模塊之間的任意切換。
按鍵音卻換功能。
原理;
多功能單片機計算器是一個實現加減乘除的和時間功能的計算器,主要的硬體組成由,一個AT89s52單片機晶元,一個LED液晶(1602液晶),一個4*4鍵盤,和4個特殊功能按鍵。
一個時鍾晶元(DS1302),一個蜂鳴器。
單個硬體模塊個的介紹
AT89S52:
主要控制晶元,它是由8kflash,256BRAM,6個中斷源,詳情參考AT89S52的技術文檔.
1602液晶
1602液晶模塊內部的字元發生存儲器(CGROM)已經存儲了160個不同的點陣字元圖形,這些字元有:阿拉伯數字、英文字母的大小寫、常用的符號等,每一個字元都有一個固定的代碼,比如大寫的英文字母「A」的代碼是01000001B(41H),顯示時模塊把地址41H中的點陣字元圖形顯示出來,我們就能看到字母「A」,而且可以實現一些復雜的字元操作:1:清顯示,游標復位到地址00H位置,2:游標和顯示模式設置 游標移動方向,高電平右移,低電平左移,屏幕上所有文字是否左移或者右移。高電平表示有效,低電平則無效 3:顯示開關控制,控制整體顯示的開與關,高電平表示開顯示,低電平表示關顯示,控制游標的開與關,高電平表示有游標,低電平表示無游標,控制游標是否閃爍,高電平閃爍,低電平不閃爍4:游標或顯示移位,高電平時移動顯示的文字,低電平時移動游標5:功能設置命令 DL:高電平時為4位匯流排,低電平時為8位匯流排 N:低電平時為單行顯示,高電平時雙行顯示 F: 低電平時顯示5x7的點陣字元,高電平時顯示5x10的點陣字元(高低電平在相應的指令上實現),詳情可參考1602的技術文檔。
1602採用標準的16腳介面: 第1腳:VSS為地電源第2腳:VDD接5V正電源第3腳:V0為液晶顯示器對比度調整端,接正電源時對比度最弱,接地電源時對比度最高,對比度過高時會產生「鬼影」,使用時可以通過一個10K的電位器調整對比度第4腳:RS為寄存器選擇,高電平時選擇數據寄存器、低電平時選擇指令寄存器。第5腳:RW為讀寫信號線,高電平時進行讀操作,低電平時進行寫操作。當RS和RW共同為低電平時可以寫入指令或者顯示地址,當RS為低電平RW為高電平時可以讀忙信號,當RS為高電平RW為低電平時可以寫入數據。第6腳:E端為使能端,當E端由高電平跳變成低電平時,液晶模塊執行命令。 第7~14腳:D0~D7為8位雙向數據線。 第15~16腳:空腳。
1602液晶和單片機的接法
4*4鍵盤,和4個特殊功能按鍵
K(切換鍵) No(復位鍵)
(時間設置鍵) C(清除鍵) +
1 2 3 —
4 5 6 *
7 8 9 %(除)
—/+ 0 。 =
前4個為特殊功能鍵,
後十六個採用鍵盤掃描接法,
掃描原理:
首先給p3口賦11111110(0xfe),然後再讀取p3口的值,如果為11101110(0xee)說明是第一排第一個被按下,如果是11011110(0xde)說明是第一排第二個被按下,如果是10111110(0xbe)說明是第一排第三個被按下,如果是0111110(0x7e)說明是第一排第四個被按下,
判斷二三四排的按鍵,都採用同樣的方法,只要分別給P3口賦不同的值即可,在讀取p3口的值,在判斷。用這樣的方法即可實現4*4鍵盤的掃描,只要有鍵按下,就可以知道是那個鍵按下,通過這種方法可大大節省單片機的io口的資源。詳情可參考網上的鍵盤掃描原理
時鍾晶元(DS1302)
DS1302 是DALLAS 公司推出的涓流充電時鍾晶元內含有一個實時時鍾/日歷和31 位元組靜態RAM ,通過簡單的串列介面與單片機進行通信實時時鍾/日歷電路提供秒分時日日期月年的信息每月的天數和閏年的天數可自動調整時鍾操作可通過AM/PM 指示決定採用24 或12 小時格式DS1302 與單片機之間能簡單地採用同步串列的方式進行通信僅需用到三個口線1 RES 復位2 I/O 數據線3 SCLK串列時鍾時鍾/RAM 的讀/寫數據以一個位元組或多達31 個位元組的字元組方式
實時時鍾具有能計算2100 年之前的秒分時日日期星期月年的能力還有閏年調整的能力(詳情可參考DS1302的技術文檔
管腳描述
X1 X2 32.768KHz 晶振管腳
GND 地
RST 復位腳
I/O 數據輸入/輸出引腳
SCLK 串列時鍾
Vcc1,Vcc2 電源供電管腳
計算器工作大概流程
Ⅱ 超詳細講解,LCD1602電路與驅動
LCD1602是一種字元型液晶顯示器,其主控晶元為HD44780或兼容晶元,初學者常接觸。它有16條引腳,包括電源地VSS、+5V電源VDD、偏壓信號VO、命令/數據選擇引腳RS、讀/寫選擇引腳RW、執行命令使能引腳E、數據輸入/輸出引腳D0-D7、背光電源A和背光負極K。VO可接精密電位器或可調電阻以調整顯示亮度。RS、RW、E連接單片機I/O口,D0-D7連接單片機的I/O口,需接上拉電阻。A接背光正極,K接電源地。LCD1602的讀操作、寫操作時序圖和時序參數圖以及DDRAM、CGROM和CGRAM的定義和作用將在後續章節詳細介紹。
DDRAM(Display Data RAM)用於存儲待顯示的字元代碼,共80個位元組,屏幕僅顯示在指定范圍內的字元代碼。在程序中,通過游標或顯示移動指令,可以實現字元在屏幕上的移動效果。要顯示字元,需將字元代碼寫入DDRAM。例如,顯示字元『A』,則將字元代碼41H寫入DDRAM的00H地址。顯示字元時,需在單片機上用P2=『A』語法編寫程序,編譯後得到的字元代碼與DDRAM地址對應。
CGROM和CGRAM分別內置了192個常用字元的字模數據和8個用戶自定義字元的生成空間。CGROM用於顯示預設的字元,CGRAM用於自定義字元。CGRAM允許用戶定義最多8個字元,定義字元時需設置地址指令,然後寫入字模數據。LCD1602模塊上的字元字模存儲器為CGROM和CGRAM,其中CGROM為只讀存儲器,CGRAM為可讀寫存儲器。
LCD1602指令包括工作方式設置、顯示開關控制、進入模式設置、游標或顯示移動、清屏、游標歸位、設置CGRAM地址、設置DDRAM地址、讀忙信號和地址計數器、寫數據到CGRAM/DDRAM和從CGRAM/DDRAM讀數據等。其中,工作方式設置指令用於設置LCD1602工作模式,顯示開關控制指令用於控制顯示狀態,進入模式設置指令用於設置LCD1602工作模式,游標或顯示移動指令用於實現屏幕滾動顯示效果,清屏和游標歸位指令用於清除屏幕內容和游標位置,設置CGRAM/DDRAM地址指令用於設置存儲器地址,讀忙信號和地址計數器指令用於判斷LCD1602狀態,寫數據/DDRAM和從CGRAM/DDRAM讀數據指令用於數據傳輸。
實例演示:在LCD1602上顯示「I love MCU!」和「LCD1602 Test!」。顯示自定義字元攝氏溫標標志和圓周率(pai)標志。最後,顯示「Welcome to my blog!」,顯示方式為從屏幕右面移入,左面移出。周而復始。
Ⅲ 單片機1602液晶怎樣移屏怎樣設置游標閃爍誰有沒有這樣的C程序
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar data a[ ]="xian zai shi ";
sbit key0= P2^0;//功能鍵,對位進行選擇
sbit key1=P2^1;// 加位
sbit key2= P2^2;// 減位
sbit EN= P3^4; //讀寫段
sbit RS= P3^5; //使能端
uchar miao,fen,shi;
uchar gongleng;//功能鍵中間變數
uchar g,key0sum;
void xunhuan (uint x)
{
int y,z;
for (y=x;y>0;y--)
for (z=120;z>0;z--);
}
void write_e(uchar e ) //寫密命
{
RS=0;
P1=e;
xunhuan(5);
EN=1;//給使能端一個高脈沖, 因為上升源完成指令
xunhuan(5);
EN=0; //晶元停止工作
}
void write_f(uchar f) //寫操作
{
RS=1;
P1=f;
xunhuan(5);
EN=1;
xunhuan(5);
EN=0;
}
void write_wei(uchar wei, uchar shu ) //一個顯示時間,一個現實在液晶屏那個位置
{
uchar shi,ge;
shi=shu/10; //顯示兩位數的高位
ge=shu%10; // 顯示兩位數的高低
write_e(0x80+0x40+wei);
write_f(0x30+shi);
write_f(0x30+ge);
}
void init ()
{
EN=0;//使能端
miao=0;
fen=0;
shi=0;
write_e(0x38);
write_e(0x0c);
write_e(0x06);
write_e(0x01);
//write_e(0x80+0x40);
for (g=0;g<16;g++) //顯示現在時間
{
write_f(a[g]);
xunhuan(10);
}
write_e(0x80+0x40+6 ); //將要顯示的位置
write_f(':');
xunhuan(5);
write_wei(4,shi);// 時的位置
write_e(0x80+0x40+9 );//將要顯示的位置
write_f(':');
xunhuan(5);
write_wei(7,fen);//分的位置
TMOD=0x01;
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void keysan() //按鍵功能端
{
if(key0==0) //判斷功能鍵的按下
{
xunhuan(20);
if(key0==0)
{
(key0sum)++;
while(!key0) ;
if(key0sum==1)
{
TR0=0 ;//關閉定時器終段位
write_e(0x80+0x40+10 );//移動到秒
write_e(0x0f);//游標閃爍,
}
if(key0sum==2)
{
TR0=0 ;//關閉定時器終段位
write_e(0x80+0x40+7 );//移動到分
write_e(0x0f);//游標閃爍,
}
if(key0sum==3)
{
TR0=0 ;//關閉定時器終段位
write_e(0x80+0x40+4 );//移動到時
write_e(0x0f);//游標閃爍,
}
if(key0sum==4)
{
TR0=1 ;//關閉定時器終段位
key0=0 ;//移動到秒
write_e(0x0c);//取消游標閃爍,
}
}
}
/**************/
if (key0!=0 )//判斷功能鍵是否按下去
{
if(key1==0)
{
xunhuan(20);
if(key1==0) //按鍵的加位
{
while(!key1);
/*********************///秒
if(key0sum==1) //若功能鍵按下時一次,說明 游標移到秒
{
miao++;
if(miao==60)
miao=0;
write_wei(10,miao);// 將位和數送到秒
write_e(0x80+0x40+10);
}
/***************************/ //分
if(key0sum==2) //若功能鍵按下時一次,說明移到分
{
fen++;
if(fen==60)
fen=0;
write_wei(7,fen);// 將位和數送到fen
write_e(0x80+0x40+7);
}
/****************/ //時
if(key0sum==3) //若功能鍵按下時一次,說明移到分
{
shi++;
if(shi==60)
shi=0;
write_wei(4,shi);// 將位和數送到fen
write_e(0x80+0x40+4);
}
}
}
}
}
void main()
{
uint m;
init();
write_e(0x80);
for(m=0;m<16;m++)
{
write_f(a[m]);
xunhuan(5);
}
while(1)
{
keysan();
}
}
void T0_timer () interrupt 1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
g++;
if(g==20)
{
g=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
write_wei(4,shi);
}
write_wei(7,fen);
}
write_wei(10,miao);
}
}
Ⅳ 關於單片機液晶屏LCD12864的程序
/*****************************************************************
*程序名稱:帶漢字型檔的12864液晶顯示模塊驅動
*程序功能:顯示字元 、漢字和圖片
*開發工具:Kile
* MCU型號:AT89S52-24PU
*時鍾頻率:11.0592MHZ
*程序作者:yuan
*版權說明:yuan
*****************************************************************/
#include<reg52.h>
#include "lcd.h"
#include "util.h"
sbit E=P1^5;//脈沖使能
sbit RW=P1^6;//讀寫選擇
sbit RS=P1^7;//數據命令選擇
sbit rst=P3^6;//12864復位
// 延時ms函數:
// 12864檢查狀態函數:
void Check12864State(void)
{
P0=0xff;
E=0;//讀狀態前三控制線的狀態
RS=0;
RW=1;
E=1;//拉高,讀狀態
while((P0&0x80)==0x80);//等待空閑
E=0;//寫命令後三控制線的狀態
RS=1;
RW=0;
}
// 12864寫命令函數:
void Write12864Command( unsigned char com)
{
Check12864State();//檢查狀態
P0=com;//賦值
E=0;//寫命令前三控制線的狀態
RS=0;
RW=0;
E=1;//拉高,寫命令
E=0;//寫命令後三控制線的狀態
RS=1;
RW=1;
}
//12864寫數據函數:
void Write12864Data( unsigned char dat)
{
Check12864State();//檢查狀態
P0=dat;//賦值
E=0;//寫數據前三控制線的狀態
RS=1;
RW=0;
E=1;//拉高,寫數據
E=0;//寫數據後三控制線的狀態
RS=0;
RW=1;
}
//在指定的位置顯示字元串(漢字和ASCII碼字元)函數:
void LCD12864DisplayString( unsigned char y,unsigned char x, unsigned char *pstr)
//y-行數值0-3,x-列數值0-7,pstr-字元串指針
//12864可以顯示32個漢字(四行每行8個),一個地址對應一個漢字
//可以顯示64個ASCII碼字元(四行每行16個),一個地址對應兩個字元
//為了實現自動換行功能,這個函數比較繁瑣
{
unsigned char row,n=0;
Write12864Command(0x30);//基本指令
Write12864Command(0x06);//地址計數器自動加以,游標右移
switch(y)//根據行號選擇行地址
{
case 0:row=0x80;break;//第一行首地址
case 1:row=0x90;break;//第二行首地址
case 2:row=0x88;break;//第三行首地址
case 3:row=0x98;break;//第四行首地址
default:;
}
Write12864Command(row+x);//寫地址
while(*pstr!='\0')
{
Write12864Data(*pstr);//寫字元
pstr++;
n++;//計數
if((n+x*2)==16)//如果一行寫完 ,繼續寫第二行
{
if(y==0) Write12864Command(0x90);//寫下一行地址
else if(y==1) Write12864Command(0x88);//寫下一行地址
else if(y==2) Write12864Command(0x98);//寫下一行地址
else ;
}
else if((n+x*2)==32)//如果第二行寫完 ,繼續寫第三行
{
if(y==0) Write12864Command(0x88);//寫下一行地址
else if(y==1) Write12864Command(0x98);//寫下一行地址
else ;
}
else if((n+x*2)==48)//如果第三行寫完 ,繼續寫第四行
{
if(y==0) Write12864Command(0x98);//寫下一行地址
else ;
}
else ;
}
}
//圖片模式清屏函數:
void Clear12864Screen()
{
unsigned char i,j;
Write12864Command(0x34);//功能設定:8位控制方式,使用擴充指令
Write12864Command(0x36);//使用擴充指令,繪圖顯示控制
for(i=0;i<32;i++)
//ST7920可控制256*32點陣(32行256列),而12864液晶實際的行地址只有0-31行,
//12864液晶的32-63行的行是0-31行地址從第128列劃分一半出來的,所以分為上下兩半屏,
//也就是說第0行和第32行同屬一行,行地址相同;第1行和第33行同屬一行,以此類推
{
Write12864Command(0x80|i);//寫行地址(垂直地址)
Write12864Command(0x80);//寫列地址(水平地址)
for(j=0;j<32;j++)
Write12864Data(0x00);//清屏
}
}
//在任意位置顯示任意大小的圖片函數:
void LCD12864DisplayPictrue(unsigned char y,unsigned char x,
unsigned char px,unsigned char py, unsigned char *pp)
//y-起始行(數值0-63),x-起始列(16位寬,數值0-7),
//px-圖片寬度,py-圖片高度,pp-指針指向圖片數組
//因為上下屏的地址不連續,要在任意位置顯示完整的圖像,處理起來比較繁瑣
{
unsigned char i,j,k;
Clear12864Screen();//清屏
if(y<32)//如果起始行在上半屏
{
k=32-y;//算出上半屏的行數
for(i=0;i<k;i++,y++)//上半屏行數
{
Write12864Command(0x80|y);//寫行地址(垂直地址)
Write12864Command(0x80|x);//寫列地址(水平地址)
for(j=0;j<px/8;j++)
Write12864Data(pp[i*px/8+j]);//寫圖片數據
}
y=0;//下半屏起始行,接上半屏繼續寫數據
for(;i<py;i++,y++)//下半屏剩下的行數
{
Write12864Command(0x80|y);//寫行地址(垂直地址)
Write12864Command(0x80|(8+x));//寫列地址(水平地址)
for(j=0;j<px/8;j++)
Write12864Data(pp[i*px/8+j]);//寫圖片數據
}
}
else //如果起始行在下半屏
{
for(i=0;i<py;i++,y++)//行數
{
Write12864Command(0x80|(y-32));//寫行地址(垂直地址)
Write12864Command(0x80|(8+x));//寫列地址(水平地址)
for(j=0;j<px/8;j++)
Write12864Data(pp[i*px/8+j]);//寫圖片數據
}
}
}
void Clear12864Text()
{
Write12864Command(0x34);//清屏
DelayMs(5);
Write12864Command(0x30);//清屏
DelayMs(5);
Write12864Command(0x01);//清屏
DelayMs(5);
}
//12864初始化函數:
void Initialize12864()
{
rst=0;//復位12864
DelayMs(30);
rst=1;
DelayMs(20);
Write12864Command(0x30);//功能設定:8位控制方式,使用基本指令
Write12864Command(0x08);//顯示關
Write12864Command(0x01);//清屏
Write12864Command(0x06);//地址計數器加一、游標右移
Write12864Command(0x0c);//顯示開
}
帶字型檔的驅動
Ⅳ 單片機lcd屏幕的問題 為甚麼整個屏幕一直在閃動
delay大,所以刷新慢。
顯示的時候沒有設置顯示位置,那麼顯示在原位,就不停刷新。
在main函數裡面最後加一句while(1);也就是原地踏步,那麼就不刷新了(也就是顯示完那幾個字元),就不抖動了