串行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)
|