LCD12864串行传输程序.docx
《LCD12864串行传输程序.docx》由会员分享,可在线阅读,更多相关《LCD12864串行传输程序.docx(23页珍藏版)》请在冰豆网上搜索。
![LCD12864串行传输程序.docx](https://file1.bdocx.com/fileroot1/2023-2/5/5fbd91ba-e473-4136-8608-eab252c29469/5fbd91ba-e473-4136-8608-eab252c294691.gif)
LCD12864串行传输程序
说明:
LCD12864-串行传输程序只要四位IO口线就可以控制LCD12864;当然液晶LCD12864背面的0欧电阻要拿掉要不然是不能使用串行数据传输模式的
/**********************************
**头文件:
LCD12864_Suart.h
**文件名:
LCD12864_Suart.c
**创建人:
动车组
**日期:
2012-6-17
**功能描述:
用串行数据传输方式控制液晶显示
**占用资源:
5根控制线
***********************************/
#include"LCD12864_Suart.h"
/*用穿行方式写一个字节数据*/
staticvoiddelay(uintx)
{
uinty;
for(;x>0;x--)
for(y=114*8;y>0;y--);
}
staticvoidwrite_byte(uchardate)
{
uchari;
for(i=0;i<8;i++)
{
SCLK=1;//一个高脉冲
NOP();
date<<=1;//高位先发送延时一下
SID=CY;//把数据给数据口
NOP();
SCLK=0;//下降沿读走数据
NOP();
}
}
/*读出一个字节该字节高四位是第一个字节temp1高四位,低四位是temp2的高四位*/
staticucharread_byte()
{
uchari,temp1,temp2;
for(i=0;i<8;i++)//第一个字节中是读取数据的高四位
{
//SID=1;//将数据口置为输入口为什么这里不能将IO口设置成输入?
?
?
temp1<<=1;
SCLK=1;//脉冲上升沿输出数据
NOP();
if(SID)//如果数据是1则最低位置一
temp1++;
NOP();
SCLK=0;
NOP();
}
for(i=0;i<8;i++)//第二个字节中是读取数据的低四位
{
//SID=1;将数据口置为输入口为什么这里不能将IO口设置成输入?
?
?
temp2<<=1;
SCLK=1;//脉冲上升沿输出数据
NOP();
if(SID)//如果数据是1则最低位置一
temp2++;
NOP();
SCLK=0;
NOP();
}
return((temp1&0xf0)|(0x0f&(temp2>>4)));
}
/*LCD12864忙检测*/
voidcheck_busy()
{
ucharsbuff;
do
{
CS=1;//使能液晶
write_byte(0xfc);//11111RWRS0读指令RW=1;RS=0
sbuff=read_byte();
CS=0;//关闭使能
}while(sbuff&0x80);
}
/*向LCD12864写入一个指令或者数据*/
voidwrite_12864_byte(bitC_D,uchardate)
{
check_busy();//读忙
CS=1;//使能液晶
if(C_D)//C_D为1时写数据
write_byte(0xfa);//11111010
else//C_D为0时写指令
write_byte(0xf8);//11111000
write_byte(0xf0&date);//写数据的高四位
write_byte(0xf0&(date<<4));//写数据的低四位
CS=0;//关闭使能
check_busy();//写完直接查忙不容易出错特别对1T单片机来说
}
/*液晶LCD12864初始化*/
voidInit_12864()
{
uchari;
CS=0;
SID=0;
SCLK=0;
RST=0;
for(i=250;i>0;i--);//液晶复位延时一下
RST=1;
//PSB=0;//选择串行数据传输
//********************************************************************************************************
/*以下是基本指令(即RE=0时,)的功能说明*/
write_12864_byte(0,0x30);//先确定使用8位总线
write_12864_byte(0,0x01);//00000001清零将DDRAM填满“20H”(空格)代码,并且设定DDRAM的地址计数器(AC)为00H;
//更新设置进入设定点将I/D设为1,游标右移AC加1。
write_12864_byte(0,0x02);//0000001X设定DDRAM的地址寄存器为00H,并且将游标移到开头原点位置;
//这个指令并不改变DDRAM的内容。
write_12864_byte(0,0x06);//000001I/DSS为0,I/D为1(0)是游变右(左)移DDRAM地址计数器(AC)加(减)1
//S为1,I/D为1(0)时画面整体左(右)移
write_12864_byte(0,0x0c);//00001DCBD=1(0)整体显示开(关),但是不改变DDRAM内容
//C=1(0)游标开(关),B=1(0)游标位置显示反白开(关)
//write_12864_byte(0,0x14);//0001S/CR/LXX这条指令不改变DDRAM的内容
/*S/CR/L方向AC的值
LL游标向左移动AC=AC-1
LH游标向右移动AC=AC+1
HL显示向左移动,游标跟着移动AC=AC
HH显示向右移动,游标跟着移动AC=AC*/
write_12864_byte(0,0x30);//001DLXREXX
/*DL=1,8位MPU接口;DL=0,4位MPU接口
RE=1,扩充指令集;RE=0,基本指令集
同一指令的动作不能同时改变DL和RE,需先改变DL再改变RE才能确保设置正确*/
//write_12864_byte(0,0x30);//01A5A4A3A2A1A0
/*设定CGRAM地址到地址计数器(AC),AC范围为00H~3FH需确认扩充指令中SR=0
(卷动位置或RAM地址选择)*/
//********************************************************************************************************
/*******************************************************************************************************
/*以下是扩充指令(即RE=1时)详细说明
write_12864_byte(0,0x01);//00000001进入待命模式,执行如何其它指令都可以结束待命模式;
该指令不能改变RAM的内容。
write_12864_byte(0,0x02);//0000001SR当SR=1时,允许输入垂直卷动地址
当SR=0时,允许输入IRAM地址(扩充指令)及允许设定CGRAM地址(基本指令)
write_12864_byte(0,0x04);//000001R1R0选择R1R0行反白
write_12864_byte(0,0x04);//00001SL00SL=1(0),脱离(进入)睡眠模式
write_12864_byte(0,0x30);//001DLXREGXDL=1,8位MPU接口;DL=0,4位MPU接口
RE=1,扩充指令集;RE=0,基本指令集
G=1,绘图显示开;G=0,绘图显示关
同一指令的动作不能同时改变RE及DL、G,需先改变DL或G再改变RE才能确保设置正确
write_12864_byte(0,0x40);//01A5A4A3A2A1A0SR=1,A5~A0为垂直卷动地址;SR=0,A3~A0为IRAM地址
//设定绘图RAM地址,设定先设置垂直位置再设置水平位置(连续写入2字节数据来完成垂直与水平坐标的设置)
write_12864_byte(0,0x80);//10A5A4A3A2A1A0设置垂直位置(以位为单位)
write_12864_byte(0,0x80);//1000A3A2A1A0设置水平位置(以字节单位)指针可自增
分两屏:
低八个字节为上半屏高八个字节为下半屏
**********************************************************************************************************/
}
/*LCD12864清屏*/
voidLCD12864_Clear()
{
write_12864_byte(0,0x01);//清屏指令
delay
(1);//延时1.6ms
}
/*在1602第hang行第lie列开始显示*s字符串*/
voidLCD12864_str(ucharhang,ucharlie,uchar*s)
{
ucharadd,i;
switch(hang)
{
case1:
add=0x80;break;
case2:
add=0x90;break;
case3:
add=0x88;break;
case4:
add=0x98;break;
default:
return;break;
}
if(lie>16)
return;
write_12864_byte(0,add+((lie+1)/2)-1);//液晶一行中只有八个地址可是显示字符可以有16个
if((lie%2)==0)//判断是否为偶数列若是则要先写一个“20H”
write_12864_byte(1,'');
for(i=1;;i++)
{
write_12864_byte(1,*s++);
if((lie+i>16)||(*s=='\0'))//判断这行是否写满或者字符串结束
break;
}
}
/*在1602第hang行第lie列开始显示*s汉字*/
voidLCD12864_Chian(ucharhang,ucharlie,uchar*s)
{
ucharadd,i;
switch(hang)
{
case1:
add=0x80;break;
case2:
add=0x90;break;
case3:
add=0x88;break;
case4:
add=0x98;break;
default:
return;break;
}
if(lie>8)
return;
write_12864_byte(0,add+lie-1);//选择显示的地址
for(i=1;;i++)
{
write_12864_byte(1,*s++);//一个汉字有两个字节
write_12864_byte(1,*s++);
if((lie+i>8)||(*s=='\0'))//判断这行是否写满或者字符串结束
break;
}
}
/*在12864第hang行第lie列开始显示Uint数据*/
voidLCD12864_Uint(ucharhang,ucharlie,uintzs)//123
{
ucharsz[6]={0x20,0x20,0x20,0x20,0x20,'\0'},i;
uintcs=zs;
for(;;i++)
{
if(cs/10==0)
break;
cs=cs/10;
}
for(;;i--)
{
sz[i]=zs%10+0x30;
if(zs/10==0)
break;
zs=zs/10;
}
LCD12864_str(hang,lie,sz);
}
/*在12864第hang行第lie列开始显示long数据*/
voidLCD12864_Long(ucharhang,ucharlie,longdws)
{
longcs=dws;
ucharsz1[11]={0x20,0x20,0x20,0x20,0x20,0x20,\
0x20,0x20,0x20,0x20,'\0'},i;
for(;;i++)
{
if(cs/10==0)
break;
cs=cs/10;
}
//sz1[i+1]='\0';
for(;i>=0;i--)
{
sz1[i]=dws%10+0x30;
if(dws/10==0)
break;
dws=dws/10;
}
LCD12864_str(hang,lie,sz1);
}
/*在12864第hang行第lie列开始显示Float数据*/
voidLCD12864_Float(ucharhang,ucharlie,floatft)//123
{
ucharsz[12],i=0;
longdd,ff;
if(ft<1.0)
{
sz[0]='0';
sz[1]='.';
dd=(long)(ft*1000);
sz[2]=dd/100+0x30;
sz[3]=dd%100/10+0x30;
sz[4]=dd%10+0x30;
sz[5]='\0';
}
else//12.678
{
dd=(long)ft;
ff=dd;
for(i=0;;i++)
{
if(dd/10==0)
break;
dd=dd/10;
}
sz[i+1]='.';
dd=(long)(ft*1000)%1000;
sz[i+2]=dd/100+0x30;
sz[i+3]=dd%100/10+0x30;
sz[i+4]=dd%10+0x30;
sz[i+5]='\0';
for(;;i--)
{
sz[i]=ff%10+0x30;
if(ff/10==0)
break;
ff=ff/10;
}
}
LCD12864_str(hang,lie,sz);
}
/*画图128*64的*/
voidLCD_12864_P(uchar*a)//显示图片函数(a的长度一定要大于64*16)
{
uchari,j,k,temp;
write_12864_byte(0,0x34);//扩充指令
write_12864_byte(0,0x36);//绘图显示开
delay
(1);//对于1T单片机来说这条延时很关键普通单片机可以不加这条
for(i=0;i<2;i++)
{
if(i==0)//画上半屏
temp=0;
else
temp=8;//画下半屏
for(j=0;j<32;j++)
{
write_12864_byte(0,(0x80+j));//设置垂直地址(以位为单位,对应的行号)
write_12864_byte(0,(0x80+temp));//设置水平地址(以字节单位,对应的列号)指针可自增
for(k=0;k<16;k++)
{
write_12864_byte(1,*a++);
}
}
}
write_12864_byte(0,0x30);//基本指令
}
/*******************************************************/
/**********************************
**文件名:
LCD12864_Suart.c
**创建人:
动车组
**日期:
2012-6-17
**功能描述:
用串行数据传输方式控制液晶显示
**占用资源:
5根控制线CS:
片选SID:
穿行数据线SCLK:
串行时钟
**PSB:
并口/串口选择(可以直接接地)RST:
复位(不用时可以直接接高电平)
***********************************/
#ifndef__LCD12864_SUART_H__
#define__LCD12864_SUART_H__
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#define_1T//如果是1T单片机就写"_1T";否则就写"_12T"
#ifdef_1T
#defineNOP()_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();\
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()//1T单片机使用的延时
#else
#defineNOP()_nop_()//普通单片机使用的延时
#endif
sbitCS=P2^5;//RS寄存器选择端:
H数据;L指令(CS片选,低有效)
sbitSID=P2^6;//R/W读写控制端:
H读;L写(SID串行数据线)
sbitSCLK=P2^7;//E使能信号(SCLK串行时钟输入)
//sbitPSB=P2^4;//并口/串口选择:
H并口L串口
sbitRST=P2^4;//复位信号,低电平有效如果不用复位直接接高电平
voidInit_12864();/*液晶LCD12864初始化*/
voidLCD12864_Clear();/*LCD12864清屏*/
voidwrite_12864_byte(bitR_S,ucharcom);/*向LCD12864写入一个指令或者数据*/
//externucharread_12864_byte(bitR_S,ucharadd);/*从12864中地址add读出数据或者指令*/
voidLCD12864_str(ucharhang,ucharlie,uchar*s);/*在1602第hang行第lie列开始显示*s字符串*/
voidLCD12864_Chian(ucharhang,ucharlie,uchar*s);/*在1602第hang行第lie列开始显示*s汉字*/
voidLCD12864_Uint(ucharhang,ucharlie,uintzs);/*在1602第hang行第lie列开始显示Uint数据*/
voidLCD12864_Long(ucharhang,ucharlie,longdws);/*在12864第hang行第lie列开始显示long数据*/
voidLCD12864_Float(ucharhang,ucharlie,floatft);/*在12864第hang行第lie列开始显示Float数据*/
voidLCD_12864_P(uchar*a);//显示图片函数128*64
#endif
/*****************************************/
/**********************************
**文件名:
LCD12864_Suart.c
**创建人:
动车组
**日期:
2012-6-17
**功能描述:
用串行数据传输方式控制液晶显示
**占用资源:
5根控制线CS:
片选SID:
穿行数据线SCLK:
串行时钟
**PSB:
并口/串口选择(可以直接接地)RST:
复位(不用时可以直接接高电平)
***********************************/
#ifndef__LCD12864_SUART_H__
#define__LCD12864_SUART_H__
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#define_1T//如果是1T单片机就写"_1T";否则就写"_12T"
#ifdef_1T
#defineNOP()_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();\
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()//1T单片机使用的延时
#else
#defineNOP()_nop_()//普通单片机使用的延时
#endif
sbitCS=P2^5;//RS寄存器选择端:
H数据;L指令(CS片选,低有效)
sbitSID=P2^6;//R/W读写控制端:
H读;L写(SID串行数据线)
sbitSCLK=P2^7;//E使能信号(SCLK串行时钟输入)
//sbitPSB=P2^4;//并口/串口选择:
H并口L串口
sbitRST=P2^4;//复位信号,低电平有效如果不用复位直接接高电平
voidInit_12864();/*液晶LCD12864初始化*/
voidLCD12864_Clear();/*LCD12864清屏*/
voidwrite_12864_byte(bitR_S,ucharcom);/*向LCD12864写入一个指令或者数据*/
//externucharread_12864_byte(bitR_S,ucharadd);/*从12864中地址add读出数据或者指令*/
voidLCD12864_str(ucharhang,ucharlie,uchar*s);/*在1602第hang行第lie列开始显示*s字符串*/
voidLCD12864_Chian(ucharhang,ucharlie,uchar*s);/*在1602第hang行第lie列开始显示*s汉字*/