❶ 關於單片機液晶屏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);//顯示開
}
帶字型檔的驅動
❷ 51單片機雙機串口通信 一個單片機控制12864顯示程序模板
我這里只有RS-485在單片機多機通信中的應用的,不過讀懂程序就可以控制12864,不是很難,我同學都有做成功。
1、RS-485在單片機多機通信中的應用
主機程序
#include"reg52.h"
#define uint unsigned int
#define uchar unsigned char
sbit p10=P1^0;
sbit p11=P1^1;
void main(void)
{
uchar i=0;
TMOD=0X20;//設置定時器1工作模式2
TH1=0XFF;
TL1=0XFF; //這里是假設晶振是11。0592的 波特率設置57600
SCON=0X40; //設置方式1 只能發送 不能接受
PCON=0X80;
TR1=1; // 啟動T1
while(1)
{
if(p10==0)
{
SBUF=0x11; //次LED單片機的針頭
while(TI==0);
TI=0;
while(p10==0);
}
if(p11==0)
{
SBUF=0x12; //次閃單片機的針頭
while(TI==0);
TI=0;
while(p11==0);
}
}
}
從機2
#include"reg51.h"
#define uint unsigned int
#define uchar unsigned char
bit flag=0;
sbit p20=P2^0;
void main(void)
{ uchar i=0;
TMOD=0X20;
TH1=0XFF;
TL1=0XFF; //這里晶振頻率同主機是11。0592的波特率設置57600
SCON=0X50; //設置方式1 只能發送 不能接受
PCON=0X80;
TR1=1; // 啟動T1
while(1)
{
while(RI==0);//採用查詢的方法判斷時候接受到數據
RI=0;
i=SBUF;
if(i==0x12)
p20=~p20;
i=0x00;
}
}
從機1
RS BIT P1.7
RW BIT P1.6
E BIT P1.5
KOU EQU P2
ORG 0030H
LOP: MOV SP,#5fH
MOV TMOD,#20H
MOV 40H,#00H
MOV TH1,#0FFH
MOV TL1,#0FFH
MOV SCON,#50H
MOV PCON,#80H
SETB TR1
ACALL LCD_MODEL ;初始化的模塊
MOV KOU,#81H
ACALL READY
MOV DPTR,#TAB
ACALL WRITE ;顯示的模塊
MOV P2,#0C1H
ACALL READY
MOV DPTR,#TAB1
ACALL WRITE
xt: jnb RI,$
CLR RI
x: MOV A,SBUF
CJNE A,#11H,rel
INC 40H
MOV A,40H
CJNE A,#10,XTG
MOV 40H,#0
XTG: MOV P2,#0C9H
ACALL READY
MOV DPTR,#TAB2
ACALL WRITEx
AJMP xt
rel: ajmp xt
WRITEx:MOV A,40H
MOVC A,@A+DPTR
MOV KOU,A
ACALL WRITE1
RET
WRITE: MOV A,#00H
MOVC A,@A+DPTR
CJNE A,#0FFH,s
AJMP EXIT
S: MOV KOU,A
ACALL WRITE1
INC DPTR
AJMP WRITE
EXIT: RET
WRITE1:SETB RS
CLR RW
CLR E
ACALL DELAY
SETB E
RET
LCD_MODEL: MOV KOU,#01H
ACALL READY
MOV KOU,#03H
ACALL READY
MOV KOU,#00000110B
ACALL READY
MOV KOU,#00001100B
ACALL READY
MOV KOU,#38H
ACALL READY
RET
READY: CLR RS
CLR RW
CLR E
ACALL DELAY
SETB E
RET
DELAY: MOV KOU,#0FFH
CLR RS
SETB RW
CLR E
NOP
SETB E
JB KOU.7,DELAY
RET
TAB: DB "Proteus 7.1" ,0FFH ;顯示字型檔
TAB1: DB "Count:" ,0FFH
TAB2: DB "0123456789"
END
模擬圖
❸ c51單片機控制12864程序(c語言),顯示幾個字,或一些簡單的圖片就行!先謝謝了!
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit CS=P2^5; //片選信號
sbit SID=P2^6; //數據信號
sbit SCLK=P2^7; //時鍾信號
sbit RST=P2^2; //復位信號
sbit CH = P2^4; //並行、串列選擇信號
/********************************************************************
* 名稱 : delay()
* 功能 : 延時,延時時間為 100us * t。這是通過軟體延時,有一定誤差。
* 輸入 : t
* 輸出 : 無
***********************************************************************/
void delay(unsigned int t)
{
unsigned int i,j;
for(i=0; i<t; i++)
for(j=0; j<10; j++);
}
/********************************************************************
* 名稱 : sendbyte()
* 功能 : 按照液晶的串口通信協議,發送數據
* 輸入 : zdata
* 輸出 : 無
***********************************************************************/
void sendbyte(unsigned char zdata)
{
unsigned int i;
for(i=0; i<8; i++)
{
if((zdata << i) & 0x80)
{
SID = 1;
}
else
{
SID = 0;
}
SCLK = 0;
SCLK = 1;
}
}
/********************************************************************
* 名稱 : write_com()
* 功能 : 寫串口指令
* 輸入 : cmdcode
* 輸出 : 無
***********************************************************************/
void write_com(unsigned char cmdcode)
{
CS = 1;
sendbyte(0xf8);
sendbyte(cmdcode & 0xf0);
sendbyte((cmdcode << 4) & 0xf0);
delay(2);
}
/********************************************************************
* 名稱 : write_data()
* 功能 : 寫串口指令
* 輸入 : cmdcode
* 輸出 : 無
***********************************************************************/
void write_data(unsigned char Dispdata)
{
CS = 1;
sendbyte(0xfa);
sendbyte(Dispdata & 0xf0);
sendbyte((Dispdata << 4) & 0xf0);
delay(2);
}
/********************************************************************
* 名稱 : lcdinit()
* 功能 : 初始化函數
* 輸入 : cmdcode
* 輸出 : 無
***********************************************************************/
void lcdinit()
{
RST = 0;
delay(100);
RST = 1;
delay(20000);
write_com(0x30);
delay(50);
write_com(0x0c);
delay(50);
}
/********************************************************************
* 名稱 : hzkdis()
* 功能 : 顯示字元串
* 輸入 : *s
* 輸出 : 無
***********************************************************************/
void hzkdis(unsigned char code *s)
{
while(*s > 0)
{
write_data(*s);
s++;
delay(50);
}
}
/********************************************************************
* 名稱 : Test()
* 功能 : 顯示子函數
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void Test()
{
write_com(0x03);
delay(50);
write_com(0x81);
hzkdis(" HOT-51");
write_com(0x91);
hzkdis("單片機開發板");
write_com(0x89);
hzkdis(" ");
write_com(0x98);
hzkdis(" 東流電子");
}
/********************************************************************
* 名稱 : Main()
* 功能 : 主函數
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void Main()
{
CH = 0;
delay(1);
lcdinit();
delay(10);
while(1)
{
Test();
delay(5000);
}
}
❹ 有個51單片機關於12864串口顯示讀寫程序求助(c語言)
if(a&(1<<(i-1))) RW_SID=1;
表示1左移i-1位再於a進行與運算,i=8的情況下i-1=7,1左移7位就是0x80。再跟a與運算(全1出1有0出0)即可獲得a的最高位。以此類推可以取出a的所有位。
if(RW_SID==1) dat|=(1<<(i-1));
當RW_SID埠為1時把1左移i-1位跟dat或運算。i=8的情況下1左移i-1位正好是0x80,再經過與運算保存最高位,循環移位再或運算就能讀取到全部位保存在dat裡面
可以寫成
//寫部分
if(a&0x80)//取出a的最高位
RW_SID=1;//如果是1則輸出1
else
RW_SID=0;//否則輸出0
a<<=1;//a整體左移,讓第7位補到最高位的位置,循環取出
E_CLK=1;
delay(100);
E_CLK=0;
delay(100);
//讀部分
E_CLK=1;
delay(100);
dat<<=1;//接收1次數據後左移。第一次為0的情況影響數據
if(RW_SID)//當埠為高的時候
dat++;//dat+1相當於dat|=1 當埠為0的時候默認左移最低位是補零的,所以不用管
E_CLK=0;//循環8次後第一次接受到的數據就在最高位了
delay(100);
效果是一樣的相對來說比較好理解
❺ 誰有用51單片機控制12864顯示數字時鍾的程序!急求!不用ds1302;簡單一點就好。有好的答案加分!
裡面有128564顯示漢字的程序,自己研究下,不過是用msp430控制的,你改改埠i就可以了。
#include "msp430x26x.h"
#define uchar unsigned char
#define uint unsigned int
#define iDat 1 //數據標志
#define iCmd 0 //指令標志
#define LCDb_RS 0x20 //定義四個控制引腳
#define LCDb_RW 0x40
#define LCDb_E 0x80
#define LCDb_RST 0x04
#define LCDb_L1 0x80 //第一行的地址
#define LCDb_L2 0x90 //第二行的地址
#define LCDb_L3 0x88 //第三行的地址
#define LCDb_L4 0x98 //第四行的地址
#define LCDb_SET_RS P1OUT|=LCDb_RS //四個控制管腳的控制操作
#define LCDb_SET_RW P1OUT|=LCDb_RW
#define LCDb_SET_E P1OUT|=LCDb_E
#define LCDb_SET_RST P8OUT|=LCDb_RST
#define LCDb_CLR_RS P1OUT&=~LCDb_RS
#define LCDb_CLR_RW P1OUT&=~LCDb_RW
#define LCDb_CLR_E P1OUT&=~LCDb_E
#define LCDb_CLR_RST P8OUT&=~LCDb_RST
#define LCDb_DO P4OUT //輸出數據匯流排埠定義
#define LCDb_FUNCTION 0x38 // 液晶模式為8位,2行,5*8字元
#define LCDb_BASCMD 0x30 // 基本指令集
#define LCDb_CLS 0x01 // 清屏
#define LCDb_HOME 0x02 // 地址返回原點,不改變DDRAM內容
#define LCDb_ENTRY 0x06 // 設定輸入模式,游標加,屏幕不移動
#define LCDb_C2L 0x10 // 游標左移
#define LCDb_C2R 0x14 // 游標右移
#define LCDb_D2L 0x18 // 屏幕左移
#define LCDb_D2R 0x1C // 屏幕又移
#define LCDb_ON 0x0C // 打開顯示
#define LCDb_OFF 0x08 // 關閉顯示
unsigned char RXData;
unsigned char Seg_Data[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //數碼管編碼
unsigned char Result[5]; //整數轉化成字元串,給LCD顯示
void Delayms(uint MS)
{
uint i,j;
for( i=0;i<MS;i++)
for(j=0;j<1141;j++);
}
void Delayus(uint US)
{
uint i;
US=US*5/4;
for( i=0;i<US;i++);
}
void LCD12864_portini()
{
P1DIR=0xFF;
P4DIR=0xFF;
P5DIR=0xFF;
P8DIR=0xFF;
P8OUT |=LCDb_RST;
// P1OUT=0xFF;
}
/*函數名稱: LCD12864_sendbyte
功 能: 向12864液晶寫入一個位元組數據或者指令
*/
void LCD12864_sendbyte(uchar DatCmd, uchar dByte)
{
if (DatCmd == iCmd) //指令操作
LCDb_CLR_RS;
else
LCDb_SET_RS;
LCDb_CLR_RW; //寫操作
LCDb_SET_E;
LCDb_DO = dByte; //寫入數據
//Delayus(500);
Delayms(1);
LCDb_CLR_E;
}
/*函數名稱: LCD12864_sendstr
功 能: 向12864液晶寫入一個字元串
參 數: ptString--字元串指針
返回值 : 無
*/
void LCD12864_sendstr(uchar *ptString)
{
while((*ptString)!='\0') //字元串未結束一直寫
{
LCD12864_sendbyte(iDat, *ptString++);
}
}
/*函數名稱: LCD12864_clear
功 能: 12864液晶清屏
參 數: 無
返回值 : 無
*/
void LCD12864_clear(void)
{
LCD12864_sendbyte(iCmd,LCDb_CLS);
Delayms(2);// 清屏指令寫入後,2ms 的延時是很必要的!!!
}
/*
函數名稱: LCD12864_gotoXY
功 能: 移動到指定位置
參 數: Row--指定的行
Col--指定的列
返回值 : 無
*/
void LCD12864_gotoXY(uchar Row, uchar Col)
{
switch (Row) //選擇行
{
case 2:
LCD12864_sendbyte(iCmd, LCDb_L2 + Col); break; //寫入第2行的指定列
case 3:
LCD12864_sendbyte(iCmd, LCDb_L3 + Col); break; //寫入第3行的指定列
case 4:
LCD12864_sendbyte(iCmd, LCDb_L4 + Col); break; //寫入第4行的指定列
default:
LCD12864_sendbyte(iCmd, LCDb_L1 + Col); break; //寫入第1行的指定列
}
}
/*
函數名稱: LCD12864_initial
功 能: 12864液晶初始化
*/
void LCD12864_initial(void)
{
Delayms(100); // 等待內部復位
LCD12864_portini(); //埠初始化
LCD12864_sendbyte(iCmd, LCDb_FUNCTION); //功能、模式設定
LCD12864_sendbyte(iCmd, LCDb_ON); //打開顯示
LCD12864_clear(); //清屏
LCD12864_sendbyte(iCmd, LCDb_ENTRY); // 輸入模式設定
}
void Int_char(int data)
{
if(data/1000)
{
Result[0]=data/1000+'0';
Result[1]=data/100%10+'0';
Result[2]=data/10%10+'0';
Result[3]=data%10+'0';
Result[4]=0;
}
else if(data/100)
{
Result[0]=data/100+'0';
Result[1]=data/10%10+'0';
Result[2]=data%10+'0';
Result[3]=0;
}
else if(data/10)
{
Result[0]=data/10%10+'0';
Result[1]=data%10+'0';
Result[2]=0;
}
else
{
Result[0]=data%10+'0';
Result[1]=0;
}
}
unsigned char Key_Press(void)
{
P7OUT=0xF0;
if((P7IN&0x10)&&(P7IN&0x20)&&(P7IN&0x40)&&(P7IN&0x80)) return 0x00;
else return 0xFF;
}
unsigned char Get_Keycode(void)
{
while(1)
{
P7OUT=0xFE; //掃描第一列
if((P7IN&0x10)==0) return 0;
else if((P7IN&0x20)==0) return 4;
else if((P7IN&0x40)==0) return 8;
else if((P7IN&0x80)==0) return 12;
P7OUT=0xFD; //掃描第二列
if((P7IN&0x10)==0) return 1;
else if((P7IN&0x20)==0) return 5;
else if((P7IN&0x40)==0) return 9;
else if((P7IN&0x80)==0) return 13;
P7OUT=0xFB; //掃描第三列
if((P7IN&0x10)==0) return 2;
else if((P7IN&0x20)==0) return 6;
else if((P7IN&0x40)==0) return 10;
else if((P7IN&0x80)==0) return 14;
P7OUT=0xF7; //掃描第四列
if((P7IN&0x10)==0) return 3;
else if((P7IN&0x20)==0) return 7;
else if((P7IN&0x40)==0) return 11;
else if((P7IN&0x80)==0) return 15;
}
}
void Init_compa()
{
CACTL1 = CAON+CAREF_2+CARSEL; // Enable Comp, ref = 0.5*Vcc = Vin-
CACTL2 = P2CA0; // Pin to CA0
P1DIR |= 0x01; // P1.0 = o/p direction(CAOUT - LED)
P1SEL |= 0x01; // P1.0 - CAOUT, option select
}
/*
** 函數名稱:初始化函數
*/
void Init_IIC(void)
{
P3SEL |= 0x06; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x50; // Slave Address is 048h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0RXIE; // Enable RX interrupt
_BIS_SR(GIE);
// RXCompare = 0x0; // Used to check incoming data
}
/** 函數名稱:位元組寫函數
*/
void EEPROM_Write(unsigned char high_Address,unsigned char low_Address,unsigned char Word)
{
while (UCB0CTL1 & UCTXSTP); // 確定匯流排空閑
UCB0CTL1 |= UCTXSTT + UCTR; // 發送起始位,確定為發送模式
UCB0TXBUF = high_Address; // 發送高位地址
while((IFG2 & UCB0TXIFG)==0); // 判斷是否發送完畢
UCB0TXBUF = low_Address; // 發送低位地址
while((IFG2 & UCB0TXIFG)==0); // 判斷是否發送完畢
UCB0TXBUF = Word; // 發送數據
while((IFG2 & UCB0TXIFG)==0); // 判斷是否發送完畢
UCB0CTL1 |= UCTXSTP; // 發送停止位
while((UCB0CTL1 & UCTXSTP)==1); // 判斷停止位是否發送完畢
}
/**
** 函數名稱:位元組讀函數
*/
void EEPROM_readmore()
{
UCB0CTL1 &= ~UCTR; // 確定為讀
while (UCB0CTL1 & UCTXSTP); // 匯流排是否空閑
UCB0CTL1 |= UCTXSTT; // 發送開始位
}
/*
** 函數名稱:位元組寫函數
**/
void EEPROM_read(unsigned char high_Address,unsigned char low_Address)
{
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTXSTT + UCTR; // 發送起始位,確定為寫
UCB0TXBUF = high_Address; // 發送地址位高位
while((IFG2 & UCB0TXIFG)==0); // 判斷是否發送完畢
UCB0TXBUF = low_Address; // 發送地址位低位
while((IFG2 & UCB0TXIFG)==0); // 判斷是否發送完畢
UCB0CTL1 &= ~UCTR; // 確定為接收
while (UCB0CTL1 & UCTXSTP); //
UCB0CTL1 |=UCTXSTT ;
while((UCB0CTL1 & UCTXSTT)==1);
for(unsigned char i=0x0;i<0x2f;i++); // 延時確定數據已經被發送出去
UCB0CTL1 |=UCTXSTP + UCTXNACK; // 發送停止位和NACK位
}
/*
** 函數名稱:接收中斷函數
**/
// USCI_B0 Data ISR
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
RXData = UCB0RXBUF; // Get RX data
Int_char(RXData);
LCD12864_gotoXY(2,0); //第2行,第1列顯示
LCD12864_sendstr(Result);
/*
key_code[0]=RXData%10+'0';
key_code[1]=0;
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr(key_code);
*/
// __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
void Init_UART()
{
P3OUT &= ~(BIT4+BIT5+BIT6+BIT7);
P3SEL = 0xF0; // P3.4,5,6,7 = USCI_A0 TXD/RXD USCI_A1 TXD/RXD
UCA0CTL1 |= UCSSEL_1; // CLK = ACLK
UCA0BR0 = 0x03; // 32kHz/9600 = 3.41
UCA0BR1 = 0x00; //
UCA0MCTL = UCBRS1 + UCBRS0; // Molation UCBRSx = 3
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
UCA1CTL1 |= UCSSEL_1; // CLK = ACLK
UCA1BR0 = 0x03; // 32kHz/9600 = 3.41
UCA1BR1 = 0x00; //
UCA1MCTL = UCBRS1 + UCBRS0; // Molation UCBRSx = 3
UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UC1IE |= UCA1RXIE; // Enable USCI_A0 RX interrupt
_BIS_SR(GIE); //使能中斷
}
void Init_ADC()
{
ADC12CTL0 = SHT0_2 + ADC12ON; // Set sampling time, turn on ADC12
ADC12CTL1 = SHP; // Use sampling timer
ADC12IE = 0x01; // Enable interrupt
ADC12CTL0 |= ENC; // Conversion enabled
P6DIR &= 0x01; // P6.0, i/p
P6SEL |= 0x01; // P6.0-ADC option select
_BIS_SR(GIE); //使能中斷
}
void Start_ADC()
{
ADC12CTL0 |= ADC12SC; // Start convn, software controlled
}
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = UCA0RXBUF; // TX -> RXed character
LCD12864_sendbyte(iDat,UCA0RXBUF);
}
#pragma vector=USCIAB1RX_VECTOR
__interrupt void USCI1RX_ISR(void)
{
while (!(UC1IFG&UCA1TXIFG)); // USCI_A0 TX buffer ready?
UCA1TXBUF = UCA1RXBUF; // TX -> RXed character
LCD12864_sendbyte(iDat,UCA0RXBUF);
//UCA1TXBUF = 'z';
}
// ADC12 interrupt service routine
#pragma vector=ADC12_VECTOR
__interrupt void ADC12_ISR (void)
{
int i=ADC12MEM0;
Int_char(i);
LCD12864_gotoXY(2,0); //第1行,第1列顯示
LCD12864_sendstr(Result);
/*
key_code[0] =i/1000+'0';
key_code[1] =i/100%10+'0';
key_code[2] =i/10%10+'0';
key_code[3] =i%10+'0';
key_code[4] =0;
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr(key_code);
*/
}
void Init_all()
{
LCD12864_initial(); //LCD初始化,包含了數碼管和LED燈初始化
P7DIR=0x0F; //鍵盤掃描初始化
P7REN=0xF0; //輸入上下拉電阻使能,輸出上下拉不使能
P7OUT=0xF0; //輸入上拉
Init_UART(); //串口初始化
Init_compa(); //比較器初始化
Init_ADC(); //ADC初始化
Init_IIC(); //IIC初始化
}
void Test_Led()
{
unsigned char i=0;
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr("1.Test_LED");
for(;i<16;i++)
{
P8OUT=0xF0|i;
Delayms(50);
}
}
void Test_Seg()
{
int i;
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr("2.Test_SEG");
for(i=0;i<500;i++)
{
//4,3,2,1
P1OUT&=~0x02;
P1OUT|=0x10|0x08|0x04;
P5OUT=Seg_Data[9]; //清楚數碼管顯示
Delayms(1);
P1OUT&=~0x04;
P1OUT|=0x10|0x08|0x02;
P5OUT=Seg_Data[8]; //清楚數碼管顯示
Delayms(1);
P1OUT&=~0x08;
P1OUT|=0x10|0x04|0x02;
P5OUT=Seg_Data[7]; //清楚數碼管顯示
Delayms(1);
P1OUT&=~0x10;
P1OUT|=0x08|0x04|0x02;
P5OUT=Seg_Data[6]; //清楚數碼管顯示
Delayms(1);
}
P5OUT=0x00; //熄滅所有數碼管
}
void Test_Key()
{
unsigned char i=0;
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr("3.Test_KEY");
LCD12864_gotoXY(2,0); //第2行,第1列顯示
LCD12864_sendstr("按鍵:");
for(;i<16;i++)
{
Int_char(Get_Keycode());
LCD12864_gotoXY(2,3);
LCD12864_sendstr(" ");
LCD12864_gotoXY(2,3);
LCD12864_sendstr(Result);
Delayms(100); //防抖
}
}
void Test_Uart()
{
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr("4.Test_UART");
LCD12864_gotoXY(2,0); //第2行,第1列顯示
}
void Test_Compa()
{
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr("5.Test_COMPA");
}
void Test_ADC()
{
int i=0;
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr("6.Test_ADC");
for(;i<200;i++)
{
Start_ADC();
Delayms(10);
}
}
void Test_IIC()
{
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr("7.Test_IIC");
EEPROM_Write(0x00,0x40,7); // 位元組寫
Delayms(10);
EEPROM_read(0x00,0x40);
}
void main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;//關閉看門狗
Init_all();
while(1){
Test_Led(); //1.測試LED
LCD12864_gotoXY(2,0); //第1行,第1列顯示
LCD12864_sendstr("請按16鍵!");
while(!(Get_Keycode()==15)); //按下最後一鍵測試下一個例子
LCD12864_clear();
Test_Seg(); //2.測試數碼管
LCD12864_gotoXY(2,0); //第1行,第1列顯示
LCD12864_sendstr("請按16鍵!");
while(!(Get_Keycode()==15)); //按下最後一鍵測試下一個例子
LCD12864_clear();
Test_Key(); //3.測試按鍵掃描
LCD12864_gotoXY(2,0); //第1行,第1列顯示
LCD12864_sendstr("請按16鍵!");
while(!(Get_Keycode()==15)); //按下最後一鍵測試下一個例子
LCD12864_clear();
LCD12864_gotoXY(3,0); //第3行,第1列顯示
LCD12864_sendstr("請按16鍵!");
Test_Uart(); //4.測試串口
while(!(Get_Keycode()==15)); //按下最後一鍵測試下一個例子
LCD12864_clear();
Test_Compa(); //5.測試比較器
LCD12864_gotoXY(2,0); //第2行,第1列顯示
LCD12864_sendstr("請按16鍵!");
while(!(Get_Keycode()==15)); //按下最後一鍵測試下一個例子
LCD12864_clear();
Test_ADC(); //6.測試ADC
LCD12864_gotoXY(3,0); //第3行,第1列顯示
LCD12864_sendstr("請按16鍵!");
while(!(Get_Keycode()==15)); //按下最後一鍵測試下一個例子
LCD12864_clear();
Test_IIC(); //7.測試IIC
Delayms(100);
LCD12864_gotoXY(3,0); //第3行,第1列顯示
LCD12864_sendstr("測試完成");
while(!(Get_Keycode()==15)); //按下最後一鍵測試下一個例子
LCD12864_clear();
}
}
❻ 求個51單片機控制KNY12864M液晶屏的簡單程序
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define Nop() _nop_()
/*引腳埠定義*/
sbit LCD12864_RS_PORT = P1^7; /*LCD12864引腳定義*/
sbit LCD12864_RW_PORT = P1^6;
sbit LCD12864_E_PORT = P2^3;
#define LCD12864_DA_PORT P0
sbit led_en_port = P2^5; /*發光二極體寄存器LE引腳*/
sbit sled_en_port = P3^6; /*數碼管寄存器LE引腳*/
uchar hanzi_buff1[]={" 液晶顯示 "};
//////////////////以下是LCD12864驅動程序////////////////
void LCD12864_WaitIdle()
//LCD12864 忙 信號檢測
{
LCD12864_DA_PORT = 0xff;
LCD12864_RS_PORT = 0;
LCD12864_RW_PORT = 1;
LCD12864_E_PORT = 1;
while((LCD12864_DA_PORT&0x80)==1); /*等待BF 不為1*/
LCD12864_E_PORT = 0;
}
void LCD12864_COM_Write( uchar com_da)
/* 檢測忙信號寫入命令字
com_da 為待寫入的命令字*/
{
LCD12864_WaitIdle();
LCD12864_RS_PORT = 0;
LCD12864_RW_PORT = 0;
LCD12864_DA_PORT = com_da;
LCD12864_E_PORT = 1;
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
LCD12864_E_PORT = 0;
}
void LCD12864_NoWaitIdle_COM_Write(uchar com_da)
/* 不檢測忙信號寫入命令字
com_da 為待寫入的命令字*/
{
LCD12864_RS_PORT = 0;
LCD12864_RW_PORT = 0;
LCD12864_DA_PORT = com_da;
LCD12864_E_PORT = 1;
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
LCD12864_E_PORT = 0;
}
void LCD12864_Data_Write(uchar da)
/* 數據寫入
da 為待寫入的8位數據*/
{
LCD12864_WaitIdle(); /*檢測忙信號*/
LCD12864_RS_PORT = 1;
LCD12864_RW_PORT = 0;
LCD12864_DA_PORT = da;
LCD12864_E_PORT = 1;
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
LCD12864_E_PORT = 0;
}
void lcd_delay_ms(uchar x)
{
uchar j;
while(x--){
for(j=0;j<125;j++)
{;}
}
}
void LCD12864_Reset()
/*LCD12864初始化*/
{
lcd_delay_ms(100); /*適當延時待LCD自動復位完成*/
LCD12864_NoWaitIdle_COM_Write(0x30); /*使用8位並口通訊*/
lcd_delay_ms(10);
LCD12864_NoWaitIdle_COM_Write(0x30); /*使用8位並口通訊*/
lcd_delay_ms(10);
LCD12864_NoWaitIdle_COM_Write(0x0c); /*顯示開及游標設置*/
lcd_delay_ms(10);
LCD12864_NoWaitIdle_COM_Write(0x01); /*顯示清屏*/
lcd_delay_ms(30);
LCD12864_NoWaitIdle_COM_Write(0x06); /*DDRAM的地址計數器(AC)加1*/
lcd_delay_ms(30);
}
void LCD12864_HANZI_WRITE(uchar xpos,uchar ypos,uchar daH,uchar daL)
//ST7920 漢字字元寫入
//參數說明: xpos 待寫入的X位置
//ypos 待寫入的Y位置
//daH 待寫入的漢字的高八位 daL待寫入的漢字的低八位
{
uchar xy_pos;
if((xpos>=8)||(ypos>=4) ) return; /*X位置超出顯示範圍退出*/
if(ypos==0) xy_pos = 0x80 + xpos;
else if(ypos==1) xy_pos = 0x90 + xpos; /*計算轉換地址*/
else if(ypos==2) xy_pos = 0x88 + xpos;
else if(ypos==3) xy_pos = 0x98 + xpos;
LCD12864_COM_Write(xy_pos); /*寫地址*/
lcd_delay_ms(1);
LCD12864_Data_Write(daH); /*寫高八位數據*/
lcd_delay_ms(1);
LCD12864_Data_Write(daL); /*寫低八位數據*/
lcd_delay_ms(1);
}
//////////////////以上是LCD12864驅動程序////////////////
void main()
{
uchar i;
LCD12864_Reset(); /*LCD初始化*/
LCD12864_DA_PORT = 0xff; /*釋放P0埠*/
led_en_port = 0;/*關閉發光二極體顯示*/
sled_en_port = 0;/*關閉數碼管顯示*/
while(1)
{
for (i=0;i<6;i++)
LCD12864_HANZI_WRITE(i,0,hanzi_buff1[i*2],hanzi_buff1[i*2+1]);
}
}
❼ 如何在12864(帶子庫)編寫顯示變化數字的子程序中文顯示程序已會。
#define uchar unsigned char
#define uint unsigned int
#define iDat 1 //數據標志
#define iCmd 0 //指令標志
#define LCDb_RS 0x20 //定義四個控制引腳
#define LCDb_RW 0x40
#define LCDb_E 0x80
#define LCDb_RST 0x04
#define LCDb_L1 0x80 //第一行的地址
#define LCDb_L2 0x90 //第二行的地址
#define LCDb_L3 0x88 //第三行的地址
#define LCDb_L4 0x98 //第四行的地址
#define LCDb_SET_RS P1OUT|=LCDb_RS //四個控制管腳的控制操作
#define LCDb_SET_RW P1OUT|=LCDb_RW
#define LCDb_SET_E P1OUT|=LCDb_E
#define LCDb_SET_RST P8OUT|=LCDb_RST
#define LCDb_CLR_RS P1OUT&=~LCDb_RS
#define LCDb_CLR_RW P1OUT&=~LCDb_RW
#define LCDb_CLR_E P1OUT&=~LCDb_E
#define LCDb_CLR_RST P8OUT&=~LCDb_RST
#define LCDb_DO P4OUT //輸出數據匯流排埠定義
#define LCDb_FUNCTION 0x38 // 液晶模式為8位,2行,5*8字元
#define LCDb_BASCMD 0x30 // 基本指令集
#define LCDb_CLS 0x01 // 清屏
#define LCDb_HOME 0x02 // 地址返回原點,不改變DDRAM內容
#define LCDb_ENTRY 0x06 // 設定輸入模式,游標加,屏幕不移動
#define LCDb_C2L 0x10 // 游標左移
#define LCDb_C2R 0x14 // 游標右移
#define LCDb_D2L 0x18 // 屏幕左移
#define LCDb_D2R 0x1C // 屏幕又移
#define LCDb_ON 0x0C // 打開顯示
#define LCDb_OFF 0x08 // 關閉顯示
unsigned char RXData;
unsigned char Result[5]; //整數轉化成字元串,給LCD顯示
/*******************************************
函數名稱: Delayms
功 能: 延時指定毫秒(8M晶振)
參 數: MS--延時的毫秒數
返回值 : 無
********************************************/
void Delayms(uint MS)
{
uint i,j;
for( i=0;i<MS;i++)
for(j=0;j<1141;j++);
}
/*******************************************
函數名稱: Delayus
功 能: 延時指定微秒(8M晶振)
參 數: US--延時的微秒數(大約,不是很精確,MS越大越准確)
返回值 : 無
********************************************/
void Delayus(uint US)
{
uint i;
US=US*5/4;
for( i=0;i<US;i++);
}
void LCD12864_portini()
{
P1DIR=0xFF;
P4DIR=0xFF;
P8DIR=0xFF; //Trig =P8^3輸出;
P8OUT |=LCDb_RST;
// P1OUT=0xFF;
}
/******************************************
函數名稱: LCD12864_sendbyte
功 能: 向12864液晶寫入一個位元組數據或者指令
參 數: DatCmd--為iDat時是數據,為iCmd時是指令
dByte--為寫入12864的數據或者指令
返回值 : 無
********************************************/
void LCD12864_sendbyte(uchar DatCmd, uchar dByte)
{
if (DatCmd == iCmd) //指令操作
LCDb_CLR_RS;
else
LCDb_SET_RS;
LCDb_CLR_RW; //寫操作
LCDb_SET_E;
LCDb_DO = dByte; //寫入數據
//Delayus(500);
Delayms(1);
LCDb_CLR_E;
}
/*******************************************
函數名稱: LCD12864_sendstr
功 能: 向12864液晶寫入一個字元串
參 數: ptString--字元串指針
返回值 : 無
********************************************/
void LCD12864_sendstr(uchar *ptString)
{
while((*ptString)!='\0') //字元串未結束一直寫
{
LCD12864_sendbyte(iDat, *ptString++);
}
}
/*******************************************
函數名稱: LCD12864_clear
功 能: 12864液晶清屏
參 數: 無
返回值 : 無
********************************************/
void LCD12864_clear(void)
{
LCD12864_sendbyte(iCmd,LCDb_CLS);
Delayms(2);// 清屏指令寫入後,2ms 的延時是很必要的!!!
}
/*******************************************
函數名稱: LCD12864_gotoXY
功 能: 移動到指定位置
參 數: Row--指定的行
Col--指定的列
返回值 : 無
********************************************/
void LCD12864_gotoXY(uchar Row, uchar Col)
{
switch (Row) //選擇行
{
case 2:
LCD12864_sendbyte(iCmd, LCDb_L2 + Col); break; //寫入第2行的指定列
case 3:
LCD12864_sendbyte(iCmd, LCDb_L3 + Col); break; //寫入第3行的指定列
case 4:
LCD12864_sendbyte(iCmd, LCDb_L4 + Col); break; //寫入第4行的指定列
default:
LCD12864_sendbyte(iCmd, LCDb_L1 + Col); break; //寫入第1行的指定列
}
}
/*******************************************
函數名稱: LCD12864_initial
功 能: 12864液晶初始化
參 數: 無
返回值 : 無
********************************************/
void LCD12864_initial(void)
{
Delayms(100); // 等待內部復位
LCD12864_portini(); //埠初始化
LCD12864_sendbyte(iCmd, LCDb_FUNCTION); //功能、模式設定
LCD12864_sendbyte(iCmd, LCDb_ON); //打開顯示
LCD12864_clear(); //清屏
LCD12864_sendbyte(iCmd, LCDb_ENTRY); // 輸入模式設定
}
void Int_char(int data)
{
if(data/1000)
{
Result[0]=data/1000+'0';
Result[1]=data/100%10+'0';
Result[2]=data/10%10+'0';
Result[3]=data%10+'0';
Result[4]=0;
}
else if(data/100)
{
Result[0]=data/100+'0';
Result[1]=data/10%10+'0';
Result[2]=data%10+'0';
Result[3]=0;
Result[4]=0;
}
else if(data/10)
{
Result[0]=data/10%10+'0';
Result[1]=data%10+'0';
Result[2]=0;
Result[3]=0;
Result[4]=0;
}
else
{
Result[0]=data%10+'0';
Result[1]=0;
Result[2]=0;
Result[3]=0;
Result[4]=0;
}
}
這使msp430單片機的程序,只要在主函數中調用函數,就是調用這個函數Int_char(tmp);每一次循環調用一次,這樣可以實時顯示這個變化溫度數值
LCD12864_gotoXY(2,4);
LCD12864_sendstr(" ");
LCD12864_gotoXY(1,0); //第1行,第1列顯示
LCD12864_sendstr("正在檢測");
LCD12864_gotoXY(2,0); //第2行,第1列顯示
LCD12864_sendstr("距離是:");
Int_char(tmp);