串行LCD12864程序 驗證過可用
單片機源程序如下:
- /****************************************************************
- 通用頭文件
- ****************************************************************/
- #include <reg52.h>
- #include <intrins.h>
- #include "i2c.h"
- #define MAIN_Fosc 11059200UL //宏定義主時鐘HZ
- /****************************************************************
- 已有數據類型重新定義
- ****************************************************************/
- typedef signed char int8; //8位有符號型
- typedef unsigned char INT8U;
- typedef signed int int16; //16位有符號型
- typedef unsigned char uint8; //8位無符號型
- typedef unsigned char uchar; //8位無符號型
- typedef unsigned int uint16; //16位無符號型
- typedef unsigned int INT16U;
- typedef unsigned int uint; //16位無符號型
- typedef unsigned long uint32; //32位無符號型
- /****************************************************************
- 硬件接口定義
- ****************************************************************/
- /*LCD12864液晶引腳*/
- sbit LCD12864_CS = P0^3; //片選使能腳, L:使能片選
- sbit LCD12864_RST= P0^4; //系統復位選擇腳
- sbit LCD12864_RS = P0^5; //命令/數據選擇腳,L:命令 H:數據
- sbit LCD12864_SCL= P0^6; //命令/數據選擇腳,L:命令 H:數據
- sbit LCD12864_SDA= P0^7; //串行數據輸入/輸出腳
- /*數碼管*/
- sbit WE = P2^7; //數碼管位選
- sbit DU = P2^6; //數碼管段選
- sbit LED=P1^7;
- sbit beep=P2^3; //蜂鳴器引腳定義
- sbit FUN=P2^2;//風扇引腳定義 風扇接 + D 通過4IN接到P22控制
- uchar code ascii_table_8x16[95][16]; //8*16字符
- uchar code ascii_table_5x7[95][5]; //5*7字符
- //PCF
- #define AddWr 0x90 //寫數據地址
- #define AddRd 0x91 //讀數據地址
- extern bit ack;
- bit ReadADFlag;
- uchar MQ[4];
- unsigned char dispos;//設置指針
- unsigned char setflag;//設置標志位
- unsigned char Q4H,Q4L,Q6H,Q6L,Q7H,Q7L;
- unsigned char ReadADC(unsigned char Chl);//讀取對應通道的ADC值函數聲明
- /*------------------------------------------------
- 讀AD轉值程序
- 輸入參數 Chl 表示需要轉換的通道,范圍從0-3
- 返回值范圍0-255
- ------------------------------------------------*/
- unsigned char ReadADC(unsigned char Chl)
- {
- unsigned char Val;
- Start_I2c(); //啟動總線
- SendByte(AddWr); //發送器件地址
- if(ack==0)return(0);
- SendByte(Chl); //發送器件子地址
- if(ack==0)return(0);
- Start_I2c();
- SendByte(AddRd);
- if(ack==0)return(0);
- Val=RcvByte();
- NoAck_I2c(); //發送非應位
- Stop_I2c(); //結束總線
- return(Val);
- }
- /*====================================
- 函數名 :void delay(INT16U ms)
- 參數 :ms,毫秒延時形參
- 返回值 :無
- 描述 :12T 51單片機自適應主時鐘毫秒級延時函數
- ====================================*/
- void delay(INT16U ms)
- {
- INT16U i;
- do{
- i = MAIN_Fosc / 96000;
- while(--i); //96T per loop
- }while(--ms);
- }
- /*====================================
- 函數 :LcdSendCmd(uchar DAT)
- 參數 :DAT需要發送的命令
- 返回值 :無
- 描述 :mini12864發送命令
- ====================================*/
- void LcdSendCmd(uchar DAT)
- {
- uchar i;
- LCD12864_CS = 0; //片選使能腳, L:使能片選
- LCD12864_RS = 0; //命令/數據選擇腳,L:命令 H:數據
- for(i=0; i<8; i++) //分別寫8次,每次寫1位
- {
- LCD12864_SCL = 0;//拉低時鐘總線,允許SDA變化
- if(DAT & 0x80)//先寫數據最高位
- LCD12864_SDA = 1; //寫1
- else
- LCD12864_SDA = 0; //寫0
- LCD12864_SCL = 1; //拉高時鐘,讓從機讀SDA
- DAT <<= 1; //為發送下一位左移1位
- }
- }
- /*====================================
- 函數 :LcdSendData(uchar DAT)
- 參數 :DAT需要發送的數據
- 返回值 :無
- 描述 :mini12864發送數據
- ====================================*/
- void LcdSendData(uchar DAT)
- {
- uchar i;
- LCD12864_CS = 0; //片選使能腳, L:使能片選
- LCD12864_RS = 1; //命令/數據選擇腳,L:命令 H:數據
- for(i=0; i<8; i++) //分別寫8次,每次寫1位
- {
- LCD12864_SCL = 0;//拉低時鐘總線,允許SDA變化
- if(DAT & 0x80)//先寫數據最高位
- LCD12864_SDA = 1; //寫1
- else
- LCD12864_SDA = 0; //寫0
- LCD12864_SCL = 1; //拉高時鐘,讓從機讀SDA
- DAT <<= 1; //為發送下一位左移1位
- }
- }
- /*====================================
- 函數 :LcdAddr
- 參數 :page設置顯示頁地址,column設置顯示列地址
- 返回值 :無
- 描述 :mini12864顯示數據地址
- ====================================*/
- void LcdAddr(uchar page, uchar column)
- {
- LCD12864_CS = 0; //使能片選
- column = column - 1; //我們平常所說的第1 列,在LCD 驅動IC 里是第0 列。所以在這里減去1.
- /*設置頁地址。每頁是8 行。一個畫面的64 行被分成8 個頁。我們平常所說的第1 頁,
- 在LCD 驅動IC 里是第0 頁,所以在這里減去1*/
- page = page - 1;
- LcdSendCmd(0xb0+page); //設置頁地址
- LcdSendCmd( ( (column >> 4) & 0x0f ) + 0x10 );//設置列地址的高4 位
- LcdSendCmd(column & 0x0f);//設置列地址的低4 位
- }
- /*====================================
- 函數 :LcdCls
- 函數 :Disp_Picture
- 參數 :page顯示區頁地址,column顯示區行地址,x清除顯示區域寬,y清除顯示區域高
- 描述 :mini12864清屏
- ====================================*/
- void LcdCls(uchar page, uchar column,uchar x,uchar y)
- {
- uchar i,j;
- LCD12864_CS = 0; //使能片選
- y = y / 8;//頁設置
- for(j=0; j<y; j++)
- {
- LcdAddr(page+j, column);
- for (i=0; i<x; i++)
- {
- LcdSendData(0); /*寫數據到LCD,每寫完一個8 位的數據后列地址自動加1*/
- }
- }
- LCD12864_CS = 1; //片選關閉
- }
- /*====================================
- 函數 :Disp_16x16
- 參數 :page顯示頁地址,column顯示行地址, dp顯示內容
- 返回值 :無
- 描述 :mini12864顯示16x16 點陣圖像、漢字、生僻字或16x16 點陣的其他圖標
- 顯示坐標設置說明16*16的字體占16行16列 對應占2頁 16列
- ====================================*/
- void Disp_16x16(uchar page, uchar column, uchar *dp)
- {
- uchar i,j;
- LCD12864_CS = 0; //使能片選
- for(j=0; j<2; j++)
- {
- LcdAddr(page+j, column);
- for (i=0; i<16; i++)
- {
- LcdSendData(*dp); /*寫數據到LCD,每寫完一個8 位的數據后列地址自動加1*/
- dp++;
- }
- }
- LCD12864_CS = 1; //片選關閉
- }
- /*====================================
- 函數 :Disp_String_8x16
- 參數 :page顯示頁地址,column顯示行地址, text顯示內容
- 返回值 :無
- 描述 :mini12864顯示8x16 數字,字符或8x16 點陣的其他圖標
- 顯示坐標設置說明8*16的字體占8行16列 對應占1頁 16列
- ====================================*/
- void Disp_String_8x16(uchar page, uchar column, uchar *text)
- {
- uint i=0,j,k,n;
- LCD12864_CS = 0; //使能片選
- while(text[i]>0x00)
- {
- if((text[i]>=0x20)&&(text[i]<=0x7e))
- {
- j=text[i]-0x20;
- for(n=0;n<2;n++)
- {
- LcdAddr(page+n, column);
- for(k=0;k<8;k++)
- {
- LcdSendData(ascii_table_8x16[j][k+8*n]);/*顯示8x16 的ASCII 字到LCD 上*/
- }
- }
- i++;
- column+=8;
- }
- else
- i++;
- }
- LCD12864_CS = 1; //片選關閉
- }
- /*====================================
- 函數 :Disp_String_5x7
- 參數 :page顯示頁地址,column顯示行地址, text顯示內容
- 返回值 :無
- 描述 :mini12864顯示5x7 數字,字符或5x7 點陣的其他圖標
- 顯示坐標設置說明5*7的字體占5行7列 對應占1頁 7列
- ====================================*/
- void Disp_String_5x7(uchar page, uchar column, uchar *text)
- {
- uint i=0,j,k;
- LCD12864_CS = 0; //使能片選
- while(text[i]>0x00)
- {
- if((text[i]>=0x20)&&(text[i]<0x7e))
- {
- j=text[i]-0x20;
- LcdAddr(page, column);
- for(k=0;k<5;k++)
- {
- LcdSendData(ascii_table_5x7[j][k]);/*顯示5x7 的ASCII 字到LCD 上*/
- }
- i++;
- column+=6;
- }
- else
- i++;
- }
- LCD12864_CS = 1; //片選關閉
- }
- /*====================================
- 函數 :Disp_Picture
- 參數 :page顯示頁地址,column顯示行地址,x圖片寬,y圖片高, dp顯示內容
- 返回值 :無
- 描述 :mini12864顯示圖片
- ====================================*/
- void Disp_Picture(uchar page, uchar column,uchar x,uchar y, uchar *dp)
- {
- uchar i,j;
- LCD12864_CS = 0; //使能片選
- y = y / 8;//頁設置
- for(j=0; j<y; j++)
- {
- LcdAddr(page+j, column);
- for (i=0; i<x; i++)
- {
- LcdSendData(*dp); /*寫數據到LCD,每寫完一個8 位的數據后列地址自動加1*/
- dp++;
- }
- }
- LCD12864_CS = 1; //片選關閉
- }
- /*====================================
- 函數 :InitLcd()
- 參數 :無
- 返回值 :無
- 描述 :mini12864初始化
- ====================================*/
- void InitLcd()
- {
- LCD12864_CS = 0; //使能片選
- LCD12864_RST= 0; //系統復位
- delay(1);
- LCD12864_RST= 1; //系統復位完成
- delay(1);
- LcdSendCmd(0xe2); //軟件復位,執行這條指令之后,電路進入軟件復位狀態,各寄存器值詳見復位狀態寄存器表。
- LcdSendCmd(0x2f); //為液晶屏升壓,提供所需電壓
- LcdSendCmd(0x23); //粗調對比度,可設置范圍0x20~0x27
- LcdSendCmd(0x81); //雙行指令 設置EV微調對比度的值
- LcdSendCmd(0x2f); //EV可設置范圍0x00~0x3f
- LcdSendCmd(0xa2); //1/9 偏壓比(bias)全屏顯示
- LcdSendCmd(0xc8); //行掃描順序:從上到下
- LcdSendCmd(0xa0); //列掃描順序:從左到右
- LcdSendCmd(0x40); //起始行:第一行開始
- LcdSendCmd(0xaf); //開顯示
- LCD12864_CS = 1; //片選關閉
- }
- void keyfun(void) //鍵盤掃描
- {
- unsigned char key;
- key = P3&0X0F; //按鍵掃描
- if(key != 0X0F)
- { LED=0;
- delay(10); //去抖動
-
- if(key == 0X0e) //加鍵
- {
- switch (dispos)
- {
- case 0: if(Q4H<250)Q4H=Q4H+10;else Q4H=255; break;
-
- case 1: if(Q6H<250)Q6H=Q6H+10;else Q6H=255; break;
-
- case 2: if(Q7H<250)Q7H=Q7H+10;else Q7H=255; break;
-
- default:break;
- }
- }else if(key == 0X0d) //減鍵
- {
- switch (dispos)
- {
- case 0: if(Q4H>30)Q4H=Q4H-10;else Q4H=20; break;
-
- case 1: if(Q6H>130)Q6H=Q6H-10;else Q6H=128; break;
-
- case 2: if(Q7H>130)Q7H=Q7H-10;else Q7H=128; break;
-
- default:break;
- }
- }
- else if(key == 0X0b) //選擇設置位
- {
- dispos++;
- dispos=dispos%3;
- }
- //else if(key == 0X08) //選擇設置位
- // {
- // dispos--;
- // dispos=dispos%3;
- // }
- while((P3&0X0F) != 0X0F); //等待按鍵釋放
- LED=1;
- }
- }
- /*------------------------------------------------
- 定時器初始化子程序
- ------------------------------------------------*/
- void Init_Timer0(void)
- {
- TMOD |= 0x01; //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響
- EA=1; //總中斷打開
- ET0=1; //定時器中斷打開
- TR0=1; //定時器開關打開
- }
- void main()
- {
- unsigned char num=0;
- unsigned char error=0;
- P0 = 0XFF;
- WE = 1;
- WE = 0;//關閉數碼管顯示
- InitLcd();//mini12864初始化
- LcdCls( 1, 1, 128, 64); //清屏指定區域
- Disp_String_5x7( 1, 5, "Gas detection system");
- Disp_String_5x7( 4, 1, "MQ4:");//顯示5*7字符
- Disp_String_5x7( 6, 1, "MQ6:");//顯示5*7字符
- Disp_String_5x7( 8, 1, "MQ7:");//顯示5*7字符
- Disp_String_5x7( 4, 55, "ppm");//顯示5*7字符
- Disp_String_5x7( 6, 55, "ppm");//顯示5*7字符
- Disp_String_5x7( 8, 55, "ppm");//顯示5*7字符
- Disp_String_5x7( 4, 112, "ppm");//顯示5*7字符
- Disp_String_5x7( 6, 112, "ppm");//顯示5*7字符
- Disp_String_5x7( 8, 112, "ppm");//顯示5*7字符
- Disp_String_5x7( 2, 34, "real");//顯示5*7字符
- Disp_String_5x7( 2, 90, "set");//顯示5*7字符
-
- Init_Timer0();
- Q4H=50; //閾值初始值
- Q6H=150;
- Q7H=150;
- beep=1;
- FUN=0;
- while(1)
- {
- keyfun() ;
- if(ReadADFlag==1) //定時AD采樣和屏幕掃描
- {
- ReadADFlag=0;
- num=ReadADC(0);
- if(num<Q4H) //在范圍內
- error=error&0Xfe;
- else
- error=error|0X01;
- MQ[0]= 0X30+num/100;
- MQ[1]= 0X30+num%100/10;
- MQ[2]= 0X30+num%10;
- MQ[3]= '\0';
- Disp_String_5x7( 4, 34, MQ);//顯示5*7字符
- //delay(10);//延時
- num=ReadADC(1);
- if(num<Q6H)
- error=error&0XfD;
- else
- error=error|0X02;
- MQ[0]= 0X30+num/100;
- MQ[1]= 0X30+num%100/10;
- MQ[2]= 0X30+num%10;
- MQ[3]= '\0';
-
- Disp_String_5x7( 6, 34, MQ);//顯示5*7字符
- //delay(10);//延時
- num=ReadADC(2);
- if(num<Q7H)
- error=error&0XfB;
- else
- error=error|0X04;
- MQ[0]= 0X30+num/100;
- MQ[1]= 0X30+num%100/10;
- MQ[2]= 0X30+num%10;
- MQ[3]= '\0';
- Disp_String_5x7( 8, 34, MQ);//顯示5*7字符
- delay(10);//延時
-
- /////////////////////////////////////
-
- MQ[0]= 0X30+Q4H/100;
- MQ[1]= 0X30+Q4H%100/10;
- MQ[2]= 0X30+Q4H%10;
- MQ[3]= '\0';
- Disp_String_5x7( 4, 90, MQ);//顯示5*7字符
- // delay(10);//延時
- MQ[0]= 0X30+Q6H/100;
- MQ[1]= 0X30+Q6H%100/10;
- MQ[2]= 0X30+Q6H%10;
- MQ[3]= '\0';
- Disp_String_5x7( 6, 90, MQ);//顯示5*7字符
- //delay(10);//延時
- MQ[0]= 0X30+Q7H/100;
- MQ[1]= 0X30+Q7H%100/10;
- MQ[2]= 0X30+Q7H%10;
- MQ[3]= '\0';
- Disp_String_5x7( 8, 90, MQ);//顯示5*7字符
- //delay(10);//延時
- }
- if((error&0x07)!=0)
- {
- beep=0;// 開蜂鳴器
- FUN=1;//開風扇
- }else
- {
- beep=1;// 關蜂鳴器
- FUN=0; //關風扇
- }
- }
- }
- /*------------------------------------------------
- 定時器中斷子程序
- ------------------------------------------------*/
- void Timer0_isr(void) interrupt 1
- {
- static unsigned int count;
- TH0=(65536-2000)/256; //重新賦值 2ms
- TL0=(65536-2000)%256;
-
- count++;
- if(count==50) //大致100ms
- {
- count=0;
- ReadADFlag=1; //讀標志位置1
- }
- }
- uchar code ascii_table_5x7[95][5]={
- /*全體ASCII 列表:5x8 點陣*/
- 0x00,0x00,0x00,0x00,0x00,//- - //space
- 0x00,0x00,0x4f,0x00,0x00,//-!-
- 0x00,0x07,0x00,0x07,0x00,//-"-
- 0x14,0x7f,0x14,0x7f,0x14,//-#-
- 0x24,0x2a,0x7f,0x2a,0x12,//-$-
- 0x23,0x13,0x08,0x64,0x62,//-%-
- 0x36,0x49,0x55,0x22,0x50,//-&-
- 0x00,0x05,0x07,0x00,0x00,//-'-
- 0x00,0x1c,0x22,0x41,0x00,//-(-
- 0x00,0x41,0x22,0x1c,0x00,//-)-
- 0x14,0x08,0x3e,0x08,0x14,//-*-
- 0x08,0x08,0x3e,0x08,0x08,//-+-
- 0x00,0x50,0x30,0x00,0x00,//-,-
- 0x08,0x08,0x08,0x08,0x08,//---
- 0x00,0x60,0x60,0x00,0x00,//-.-
- 0x20,0x10,0x08,0x04,0x02,//-/-
- 0x3e,0x51,0x49,0x45,0x3e,//-0-
- 0x00,0x42,0x7f,0x40,0x00,//-1-
- 0x42,0x61,0x51,0x49,0x46,//-2-
- 0x21,0x41,0x45,0x4b,0x31,//-3-
- 0x18,0x14,0x12,0x7f,0x10,//-4-
- 0x27,0x45,0x45,0x45,0x39,//-5-
- 0x3c,0x4a,0x49,0x49,0x30,//-6-
- 0x01,0x71,0x09,0x05,0x03,//-7-
- 0x36,0x49,0x49,0x49,0x36,//-8-
- 0x06,0x49,0x49,0x29,0x1e,//-9-
- 0x00,0x36,0x36,0x00,0x00,//-:-
- 0x00,0x56,0x36,0x00,0x00,//-;-
- 0x08,0x14,0x22,0x41,0x00,//-<-
- 0x14,0x14,0x14,0x14,0x14,//-=-
- 0x00,0x41,0x22,0x14,0x08,//->-
- 0x02,0x01,0x51,0x09,0x06,//-?-
- 0x32,0x49,0x79,0x41,0x3e,//-@-
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
1、MINI12864測試程序.rar
(57.11 KB, 下載次數: 48)
2018-5-8 22:34 上傳
點擊文件名下載附件
測試程序
|