标题:
液晶MINI12864串行接口的单片机源码(不带字库)
[打印本页]
作者:
xiaoyuahan110
时间:
2018-5-8 22:35
标题:
液晶MINI12864串行接口的单片机源码(不带字库)
串行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 上传
点击文件名下载附件
测试程序
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1