LCD12864初始化流程图

合集下载

LCD12864-并口调试分享

LCD12864-并口调试分享

12864并口调试一、查技术手册得读时序图和指令表如下1、当模块在接受指令前,微处理顺必须先确认模块内部处于非忙碌状态,即读取BF 标志时BF 需为0,方可接受新的指令;如果在送出一个指令前并不检查BF 标志,那么在前一个指令和这个指令中间必须延迟一段较长的时间,即是等待前一个指令确实执行完成,指令执行的时间请参考指令表中的个别指令说明。

2、“ RE”为基本指令集与扩充指令集的选择控制位元,当变更“ RE”位元后,往后的指令集将维持在最后的状态,除非再次变更“RE”位元,否则使用相同指令集时,不需每次重设“ RE”位元。

由上,读程序如下:二、查技术手册得写时序图和指令表如下由上,写程序如下:三、LCD初始化由数据手册,以上写指令注释:Wr_Command(0x30,0); //执行基本指令集动作Wr_Command(0x0C,1); //开显示及光标设置Wr_Command(0x01,1); //显示清屏Wr_Command(0x06,1); //显示光标移动设置四、GPIO并行输出数据在STM32操作一个IO口有下面四种方式:1、位带操作#define busy PAin(11)2、寄存器操作#define busy ((GPIOA->IDR)&(1<<11)?1:0)3、标准库函数操作#define busy GPIO_SetBits(GPIOA, GPIO_Pin_11) 4、HAL库操作#define busy HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11)根据包装线硬件原理图,LCD部分IO口分配如下:可见,IO分配是比较杂乱的,先对各GPIO进行初始化。

本例采用寄存器方式开发,GPIO 数据输出程序如下:总结下来,寄存器操作有以下特点:“与1相‘&’、与0相‘|’、不影响原值”例:#define LED0 (1<<10)#define LED0_SET(x) GPIOB->ODR=(GPIOB->ODR&~LED0)|(x ? LED0:0) ‘GPIOB->ODR&~LED0’ 把第10位”&0清0”;把其余位“与1相&,不影响原值”。

LCD12864绘图之KS0108(5)

LCD12864绘图之KS0108(5)

LCD12864绘图之KS0108(5)Ampire 12864显示指针时钟贵州省凯里市第一中等职业技术学校机电部电子应用专业高级教师杨正富仿真局部大图:仿真全图:/***************************************************************************************说明:1、程序共分六部分。

一个主C程序,五个头文件程序。

2、构成:AT89C52 + DS1302 + DS18B20 + Ampire128x64 + Speaker3、显示:日期,星期,时间,气温4、调整:设置三个按键,用于调节日期,星期,时间。

5、程序不够完善,请有志者自行修改补充。

***************************************************************************************/////////////////////////////////////////////////////////////// 1 //////////////////////////////////////////////////////////////////////////////////C程序:负责调用与整合其他程序模块功能#include"Hzimo.h" //字模头文件#include"DS1302.h" //时钟读写头文件#include"DS18B20.h" //温度传感器操作头文件#include"KS0108.h" //液晶显示操作头文件#include"keyscan.h" //键盘调整操作头文件void pointer_Update() //指针的绘制与擦除(等比分点){uchar S,M,H; //定义秒分时寄存变量,用于时间判断if(S!=DT[0]) //秒时间跳变{CLKpointer_show(31,31,S,25,0); //秒针线擦除S=DT[0]; //指向下一次的时间}CLKpointer_show(31,31,S,25,1);if(M!=DT[1]) //分时间跳变{CLKpointer_show(31,31,M,20,0); //分针线擦除M=DT[1]; //指向下一次的时间}CLKpointer_show(31,31,M,20,1);if(DT[2]<12)DT[2]=DT[2]*5+DT[1]/12; //用于计算时针的终点坐标else{DT[2]=DT[2]-12;DT[2]=DT[2]*5+DT[1]/12;}if(H!=DT[2]) //时间是否跳变{CLKpointer_show(31,31,H,15,0); //时针线擦除H=DT[2]; //指向下一次的时间}CLKpointer_show(31,31,H,15,1);}void fixed_display() //固定显示(按页,列,字码,字数定位) {sz_Disp1(2,0,16,num[11],1); //右屏0页第16列显示'-'sz_Disp1(2,0,40,num[11],1); //右屏0页第40列显示'-'hz_Disp16(2,2,0,HZ[8],2); //右屏2页第0列显示"星期"sz_Disp1(2,2,32,num[10],2); //右屏2页第32列填充黑块"■" 2个sz_Disp1(2,4,16,num[12],1); //右屏4页第16列显示':'sz_Disp1(2,4,40,num[12],1); //右屏4页第40列显示':'hz_Disp16(2,6,0,HZ[10],2); //右屏6页第0列显示"气温"hz_Disp16(2,6,48,HZ[0],1); //右屏6页第48列显示"℃"picture_disp12(1,0,0,&clock); //左屏显示表盘与刻度}void dynamic_display() //动态显示(随时更新的数值){sz_Disp1(2,0, 0,num[DT[6]/10],1); //右屏0页第 0列显示'年十位'sz_Disp1(2,0, 8,num[DT[6]%10],1); //右屏0页第 8列显示'年个位'sz_Disp1(2,0,24,num[DT[4]/10],1); //右屏0页第24列显示'月十位'sz_Disp1(2,0,32,num[DT[4]%10],1); //右屏0页第32列显示'月个位'sz_Disp1(2,0,48,num[DT[3]/10],1); //右屏0页第48列显示'日十位'sz_Disp1(2,0,56,num[DT[3]%10],1); //右屏0页第56列显示'日个位'hz_Disp16(2,2,48,HZ[DT[5]],1); //右屏2页第48列显示"星期值"sz_Disp1(2,4, 0,num[DT[2]/10],1); //右屏4页第 0列显示'时十位'sz_Disp1(2,4, 8,num[DT[2]%10],1); //右屏4页第 8列显示'时个位'sz_Disp1(2,4,24,num[DT[1]/10],1); //右屏4页第24列显示'分十位'sz_Disp1(2,4,32,num[DT[1]%10],1); //右屏4页第32列显示'分个位'sz_Disp1(2,4,48,num[DT[0]/10],1); //右屏4页第48列显示'秒十位'sz_Disp1(2,4,56,num[DT[0]%10],1); //右屏4页第56列显示'秒个位'if(key1n==0) //如果K1键计次值为 0{ //注:此位置兼作调整提示显示sz_Disp1(2,6,32,num[Temp/10],1); //右屏6页第32列显示'温度十位'sz_Disp1(2,6,40,num[Temp%10],1); //右屏6页第40列显示'温度个位' }pointer_Update(); //左右屏指针显示与擦除}void main(void){init_lcd(0); //LCD初始化// Set_1302(DT); //设置DS1302初始时间fixed_display(); //固定显示(无须改变的内容)while(1) //无限循环{Get_1302(DT); //读取DS1302实时数据值Temp=ReadTemperature(); //获取DS18B20实时温度dynamic_display(); //动态显示(随时更新的数值)keyscan(); //键盘扫描程序调用}}////////////////////////////////////////////////////////////// 2 ///////////////////////////////////////////////////////////////////////////////LCD-KS0108.h#include<reg52.h> //52系列单片机头文件#include "math.h"#define uint unsigned int //无符号整型变量宏定义#define uchar unsigned char //无符号字符变量宏定义#define PI 3.1415926 //圆周率//LCD端口定义#define DATA P0 //数据线为P0口sbit lcd_RS=P2^0; //数据/命令选择(RS)sbit lcd_RW=P2^1; //读/写选择sbit lcd_EN=P2^2; //读写使能sbit lcd_CS1=P2^3; //当lcd_CS1=0左半屏可操作sbit lcd_CS2=P2^4; //当lcd_CS2=0右半屏可操作sbit lcd_RST=P2^5; //复位脚//基本操作://程序延时,用于LCD读写数据,以及初始化void delay_us(uint t) //us级延时程序{for( ;t>0;t--);}//状态检查,LCD是否忙void check_busy(){uchar dat; //状态信息(判断是否忙)lcd_RS=0; //选择指令寄存器lcd_RW=1; //选择读取方式do //按以下操作{DATA=0x00; //数据总线置0lcd_EN=1; //使能读出,状态值送总线delay_us(2); //延时,等待数据稳定dat=DATA; //读取总线并赋予变量lcd_EN=0; //停止读取dat=0x80 & dat; //仅当第7位为0时才可操作(判别busy信号) }while(!(dat==0x00)); //若busy不为0,则循环;为0则结束}//写命令cmdcode到LCD程序void write_com(uchar cmdcode){check_busy(); //检测LCD是否忙lcd_RS=0; //选择指令寄存器lcd_RW=0; //选择写入方式P0=cmdcode; //指令送总线delay_us(2); //延时,待指令数据稳定lcd_EN=1; //使能写入delay_us(2); //延时以确保写入完整lcd_EN=0; //停止写入}//写数据到LCD程序void write_data(uchar lcddata){check_busy(); //检测LCD是否忙lcd_RS=1; //选择数据寄存器lcd_RW=0; //选择写入方式P0=lcddata; //数据送总线delay_us(2); //延时,待数据稳定lcd_EN=1; //使能写入delay_us(2); //延时,确保写入完整lcd_EN=0; //停止写入}//从LCD读数据uchar read_data(){uchar lcdat; //定义读数变量check_busy(); //检测LCD是否忙lcd_RS=1; //选择数据寄存器lcd_RW=1; //选择读取方式lcd_EN=0; //准备读lcd_EN=1; //使能输出delay_us(2); //延时,待数据稳定lcdat=DATA; //读取端口值delay_us(2); //延时,确保读完整lcd_EN=0; //停止Y读取return lcdat; //返回数据值}//左右屏选择,void select_scr(uchar ss){switch(ss) //依据选屏参数判断{case 0: lcd_CS1=0;lcd_CS2=0;break; //选中全屏操作case 1: lcd_CS1=0;lcd_CS2=1;break; //选中左屏操作case 2: lcd_CS1=1;lcd_CS2=0;break; //选中右屏操作case 3: lcd_CS1=1;lcd_CS2=1;break; //左右屏无操作}}//清除LCD内存程序,void Clr_Scr(uchar ss) //清理屏幕显示{uchar j,k; //定义页,列变量select_scr(ss); //选择屏幕for(k=0;k<8;k++) //控制页数0-7,共8页{write_com(0xb8+k); //写入页地址for(j=0;j<64;j++) //控制列数0-63,列地址自动加1{write_com(0x40+j); //写入列地址write_data(0x00); //写入空白内容,}}}//初始化LCD(不同的应用,初始化方法不同)void init_lcd(uchar ss) //LCD初始化程序{check_busy(); //检测LCD是否忙select_scr(ss); //选择屏幕Clr_Scr(ss); //LCD清屏幕显示write_com(0x3e); //关显示write_com(0xb8+0); //设置:起始页地址write_com(0xc0+0); //设置:起始行地址write_com(0x40+0); //设置:起始列地址write_com(0x3f); //开显示}//显示操作://指定地址按行显示编码数组hzk[][32]中连续的1~4个汉字(16*16)//参数: ss=0~2; page=0~7; col=0~63; hzk——hzk[][32]; n=1~4void hz_Disp16(uchar ss,uchar page,uchar column,uchar hzk[][32],uchar n){uchar k,p,c; //变量:汉字数,页,列select_scr(ss); //选择屏幕for(k=0;k<n;k++) //按汉字个数循环写入{for(p=0;p<2;p++) //每个字符占 2 页,所以写2次{write_com(0xb8+page+p); //写入显示页地址(page,page+1)write_com(0x40+column+16*k); //写入显示列地址(起始列,0~16~32~48)for(c=0;c<16;c++) //连续16次(上,下半字各16个编码)write_data(hzk[k][16*p+c]); //每页写入16个字节的汉字编码数据}}}//重复显示二维数组szk[][16]中相同字符1~8次void sz_Disp1(uchar ss,uchar page,uchar column,uchar szk[][16],uchar n){ //参数: 屏,页、列、码、字符数uchar i=0,j=0,k=0; //变量: 页,列,字符数select_scr(ss); //选择屏幕for(k=0;k<n;k++){for(i=0;i<2;i++) //每个字符占 2 页,所以写2次{write_com(0xb8+page+i); //写入显示页地址(pag,pag+1)write_com(0x40+column+8*k); //写入显示列地址(起始列)for(j=0;j<8;j++) //连续8次write_data(szk[0][8*i+j]); //写入8个字节数据}}}//半屏图像显示函数(带参数:屏,页,列,数据)void picture_disp12(uchar ss,uchar page,uchar column,uchar table[8][64]){uchar i,j; //页,列变量select_scr(ss); //选择屏if(column>=64) //如果列地址大于等于64column=column-64; //列首地址仍从0x40开始显示for(i=0;i<8;i++) //分8页写入{write_com(0xb8+page+i); //写页地址write_com(0x40+column); //写列地址for(j=0;j<64;j++) //依次写入0~63列{write_data(table[i][j]); //写图像数据}}}//绘图操作://反白功能打点函数,任意指定坐标画点 color=1,黑;color=0,白void LCD_DrawDot(uchar x,uchar y,uchar color)//x水平坐标,y垂直坐标,color显示颜色{char dat[8],Byte[8]; //定义列字节数组uchar j; //循环变量for(j=0;j<8;j++) dat[j]=0x00; //数组元素赋初值 0x00if(x<64) //列坐标小于64select_scr(1); //选择左半屏else //列坐标大于等于64{select_scr(2);x-=64;} //选择右半屏,列坐标调整为0~63for(j=1;j<7;j++) //每屏8页(0~7),8个字节{write_com(0xb8+j); //写页地址write_com(0x40+x); //写列地址read_data(); //空读一次Byte[j]=read_data(); //读出一字节数据if(color) //如果要显示点{dat[y>>3]|=0x01<<(y&0x07); //y值所在页对应字节位置 1Byte[j]|=dat[j]; //修正原读数("或"运算)}else //如果要擦除点{dat[y>>3]&=~(0x01<<(y&0x07)); //y值所在页对应字节位置 0Byte[j]&=dat[j]; //修正原读数("与"运算)}write_com(0x40+x); //重写列地址(因读数而改变)write_data(Byte[j]); //写入修正后的字节数据}}//在指定位置上画线(x0,y0)——(x1,y1);color——0白,1黑void LCD_DrawLine_R(uchar x0,uchar y0,uchar x1,uchar y1,uchar color){//在bresenham算法当中,全部以整数来运算,提升运算速度int temp;int dx,dy; //定义起点到终点的横、纵坐标增加值int s1,s2,status,i; //x轴步长,y轴步长,偏移状态,循环变量int Dx,Dy,sub; //sub用于判断下一个点的位置dx=x1-x0; //计算横坐标差值if(dx>=0)s1=1; //如果dx>=0,从x0到x1是增加的,步长值取+1 else s1=-1; //如果dx<0, 从x0到x1是减小的,步长值取-1dy=y1-y0; //计算纵坐标差值if(dy>=0)s2=1; //如果dy>=0,从y0到y1是增加的,步长值取+1 else s2=-1; //如果dx<0, 从y0到y1是减小的,步长值取-1//纵坐标增加的多,直线偏向Y轴,横坐标增加的多则偏向X轴//以45度角为分界线,靠进Y轴是status=1,靠近X轴是status=0Dx=abs(x1-x0); //计算横坐标增加值的绝对值Dy=abs(y1-y0); //计算纵坐标增加值的绝对值if(Dy>Dx) //如果dy>dx{temp=Dx;Dx=Dy;Dy=temp; //交换DX,DY的值status=1; //靠近Y轴,偏移状态置 1}else status=0; //如果dx>dy,靠近X轴,偏移状态置 0//Bresenham算法画任意两点间的直线sub=Dy+Dy-Dx; //计算sub,首次判断下个点的位置for(i=0;i<Dx;i++) //循环dx次{if(sub>=0) //如果下个点在起点下方{if(status==1)x0+=s1; //在靠近Y轴区,x值加1else y0+=s2; //在靠近X轴区,y值加1sub-=(Dx+Dx); //再判断下一个点的位置}if(status==1)y0+=s2; //在靠近Y轴区,y值加1else x0+=s1; //在靠近X轴区,x值加1LCD_DrawDot(x0,y0,color); //根据x0,y0的变化逐个画点sub+=Dy+Dy; //再次判断下一个点的位置}}//指针显示与擦除: time 表示 hour、min、sec 参量,L为时分秒指针各自长度void CLKpointer_show(uchar a,b,time,L,color){float x,y;x=sin(time*2*PI/60);y=cos(time*2*PI/60);LCD_DrawLine_R(a,b,a+L*x,b-L*y,color);}//////////////////////////////////////////////////////////////////// 3 ////////////////////////////////////////////////////////////////////////////DS1302.H//------------------------------ds1302寄存器地址-----------------------------------------------------------------------//// 秒分时日月星期年[写保护]//写: 0x80 0x82 0x84 0x86 0x88 0x8a 0x8c 0x8e//读: 0x81 0x83 0x85 0x87 0x89 0x8b 0x8d (写0x00,关闭保护)// (写0x80,开启保护)//--------------------------------------------------------------------------------------------------------------------------------#include"reg52.h" //52单片机头文件#define uchar unsigned char //无符号字符变量宏定义#define uint unsigned int //无符号整型变量宏定义sbit T_IO=P3^5; //实时时钟数据线引脚sbit T_CLK=P3^6; //实时时钟时钟线引脚sbit T_RST=P3^7; //实时时钟复位线引脚sbit ACC0=ACC^0; //加法器最低位sbit ACC7=ACC^7; //加法器最高位void RTI_1302_1Byte(uchar d) //往DS1302写入1Byte数据(内部函数) {uchar i; //循环变量ACC=d; //数据送累加器Afor(i=8;i>0;i--) //循环8次,{T_IO=ACC0; //将ACC0位值(先低位,后高位)送数据端口T_CLK=1; //拉高时钟线电平写入数值T_CLK=0; //拉低时钟线电平停止写入ACC=ACC>>1; //将A中数据右移 1 位}}uchar RTO_1302_1Byte() //从DS1302读取1Byte数据(内部函数){uchar i; //变量定义for(i=8;i>0;i--) //循环8次{ACC=ACC>>1; //将ACC中数据右移 1 位ACC7=T_IO; //读取一位值(先低位,后高位)送到ACC7位T_CLK=1; //停止读取T_CLK=0; //释放总线}return(ACC); //返回ACC值}void Write_1302(uchar ucAddr,uchar ucDa) //往DS1302写入数据,先地址后数据{T_RST=0; //复位引脚为低电平,所有数据传送终止T_CLK=0; //清时钟总线T_RST=1; //复位引脚为高电平,逻辑控制有效RTI_1302_1Byte(ucAddr); //写实时时钟地址,命令RTI_1302_1Byte(ucDa); //写实时时钟写1Byte数据T_CLK=1; //时钟上升沿,发送数据有效T_RST=0; //逻辑操作完毕,清 RST}uchar Read_1302(uchar ucAddr) //读取DS1302中指定地址数据{uchar ucData; //定义数据变量T_RST=0; //复位引脚为低电平,所有数据传送终止T_CLK=0; //拉低时钟电平,清时钟总线T_RST=1; //复位引脚为高电平,逻辑控制有效RTI_1302_1Byte(ucAddr); //写入指定地址,命令ucData=RTO_1302_1Byte(); //读取1Byte数据T_CLK=1; //时钟上升沿,传送数据有效T_RST=0; //逻辑操作完毕,清 RSTreturn(ucData); //返回数据值}/*//初始化设置仅限第一次使用DS1302,之后即可正常运行,故屏蔽此程序段void Set_1302(uchar *pClock) //设置DS1302初始时间{uchar i; //循环变量定义uchar ucAddr=0x80; //地址变量定义(初值0x80)Write_1302(0x8e,0x00); //“写控制”命令,WP=0,允许写操作//说明:命令字0X8E 为写控制,命令字0x8F 为读控制,//当写入0x00,最高位为WP=0,允许读写;当写入0X80,最高位为WP=1,禁止读写。

任务八 LCD12864液晶显示

任务八 LCD12864液晶显示

• (7) Z地址计数器
• Z地址计数器是一个6位计数器,此计数器具备循环记数功能, 它是用于显示行扫描同步。当一行扫描完成,此地址计数器自动 加1,指向下一行扫描数据,RST复位后Z地址计数器为0。Z地址 计数器可以用指令DISPLAY START LINE预置。因此,显示屏幕的起 始行就由此指令控制,即DDRAM的数据从哪一行开始显示在屏幕 的第一行。此模块的DDRAM共64行,屏幕可以循环滚动显示64行。
00 1 0 1 1 1
页号(0~7)
功能:显示RAM共64行,分8页,每页8行。从DB3到 DB7的值可 以看出,用指令“0xb8+add”表示,该指令设置后面续写得页地址, LCD12864一个字节数据对应纵向8个点,因此页号(add)为0~7。
④ 列地址(Y Address)设置指令
R/W RS 00
表8-3 RAM地址映像表
⑤ 读状态指令
R/W RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
1 0 BUSY 0 ON/OFF REST 0 0
00
功能:该指令用来查询液晶显示模块内部控制器的状态,各参量含义如下:
BUSY:1-内部在工作0-正常状态 ON/OFF:1-显示关闭0-显示打开 RESET:1-复位状态0-正常状态 在BUSY和RESET状态时,除读状态指令外,其它指令均不对液晶显 示模块产生作用。在对液晶显示模块操作之前要查询BUSY状态,以确定是 否可以对液晶显示模块进行操作。
0
0
0
0
DB5 DB4 DB3 DB2 DB1 DB0
1
1
1
1
1 1/0
功能:当DB0=1时,LCD显示RAM中的内容,即指令0X3F,开显示;DB0=0 时, 关闭显示[不影响显示RAM(DD RAM)中的内容],即指令‘‘0x3E”。

lcd12864简单例程

lcd12864简单例程
ClearScreen(0);
Set_line(0);
}
/****************************************************/
/*
函数名:Display,Display_Photo_Panda
功能:写入显示数据
特点:
列行式
逆向
阴码
{
reg0 = 2;
//P3 = 0x0d;
}
}
P1 = 0x0b;
if((P1 & 0x0f)!=0x0f)
{
if((P1&0x0f) == 0x0b)
{
reg0 = 3;
//P3 = 0x0b;
{
if((P1&0x0f) == 0x0e)
{
reg0 = 1;
//P3 = 0x0e;
}
}
P1 = 0x0d;
if((P1 & 0x0f)!=0x0f)
{
if((P1&0x0f) == 0x0d)
}
}
P1 = 0x07;
if((P1 & 0x0f)!=0x0f)
{
if((P1&0x0f) == 0x07)
{
reg0 = 4;
//P3 = 0x07;
}
}
}
P1 = 0x0f;
if((P1&0x0f)==0x0f)
}
void Set_line(uchar startline)
{
startline = 0xc0 | startline;

单片机学习项目 (18) LCD12864的原理与应用

单片机学习项目 (18) LCD12864的原理与应用

单片机学习项目项目18-LCD12864的原理与应用一:电路原理图液晶12864和单片机的连接电路见图图6-2-3所示,其中12864的数据端D0~D7分别接单片机的P0口,需加上啦电阻;/WR接P24,/RD接P2.3,/CE接P2.2,/CD接P2.1,/RST接P2.0;12864的第4脚接多圈电位器,用来调节12864显示的对比度。

二:12864液晶显示器驱动程序12864的驱动程序中主要有系统配置预处理、基本操作函数和应用操作函数,基本操作函数有:向12864中写一个一字节数据,写一个一字节命令,写一个数据一个命令,写两个数据两个命令和12864基本设置函数、清屏函数以及延时函数,由于写过程中采用了延时,所以程序中省去了读状态操作;应用操作包含的函数有显示字符、显示汉字、显示图形等函数,因此12864中包含了字库和图形的文件。

基本操作类函数和应用操作类函数是12864的基本程序,保存在f12864.c文件中,所使用的字库、图形文件实例分别存放在ziku.c和tuxing.c中。

#include<reg51.h>#include<f12864.c>/*主函数*/void main(void){ucharsec,min = 30,hour = 12;F12864_init();F12864_clear();dispay_tuxing();delay(50000);delay(50000);delay(50000);delay(50000);F12864_clear();display_hanzi(2,0,0,6);display_hanzi(2,1,6,12);display_string(0,4,"----------------");display_string(2,5,"HelloWorld!");display_string(0,6,"0123456789ABCDEF");delay(50000);delay(50000);delay(50000);delay(50000);F12864_clear();while(1){display_hanzi(0,0,12,14);display_num(4,1,hour);display_num(7,1,min);display_num(10,1,sec);sec++;display_string(6,1,":");display_string(9,1,":");delay(50000);display_string(6,1,"");display_string(9,1," ");delay(50000);if(sec>= 60){sec= 0;min++;}if(min>= 60){min= 0;hour++;}if(hour>= 24)hour =0;}}(1)基本操作/*预处理*/#include<reg51.h>#include<ziku.c>#include<tuxing.c>#define uchar unsigned char#define uint unsigned intuchar num[] ="0123456789";sbit rest = P2^0; //复位信号,低电平有效sbit _cd = P2^1; //命令和数据控制口(高为命令,低为数据)sbit _ce = P2^2; //片选信号,低电平有效sbit _rd = P2^3; //读信号,低电平有效sbit _wr = P2^4; //写信号,低电平有效/*延迟函数*/void delay(uint i){while(i--);}/*写命令*/void write_commond(uchar com){_ce = 0;_cd = 1; //高电平,写指令_rd = 1;P0 = com;_wr = 0; _nop_();_wr = 1;_ce = 1;_cd = 0;}/*对写一个数据*/void write_date(uchar dat){_ce = 0;_cd = 0; //低电平,写指令_rd = 1;P0 = dat;_wr = 0;_nop_();_wr= 1;_ce = 1;_cd= 1;}/*写一个指令和一个数据*/void write_dc(uchar com,uchar dat){write_date(dat); //先写数据write_commond(com); //后写指令}/*写一个指令和两个数据*/voidwrite_ddc(uchar com,uchar dat1,uchar dat2){write_date(dat1); //先写数据write_date(dat2); //先写数据write_commond(com); //后写指令}/*LCD12864初始化函数*/voidf12864_init(void){rest = 0;delay(300);rest = 1;write_ddc(0x40,0x00,0x00); //设置文本显示区首地址0x0000write_ddc(0x41,128 / 8,0x00); //设置文本显示区宽度8点阵write_ddc(0x42,0x00,0x08); //设置图形显示区首地址0x0800write_ddc(0x43,128 / 8,0x00); //设置图形显示区宽度write_commond(0x81); //显示方式设置,文本与图形异或显示write_commond(0x9e); //显示开关设置,文本开,图形开,光标闪烁关}/*清屏函数*/void f12864_clear(void){unsigned int i;write_ddc(0x24,0x00,0x00); //置地址指针为从零开始write_commond(0xb0); //自动写for(i = 0;i <128 * 64 ;i++) write_date(0x00); //清一屏write_commond(0xb2); // 自动写结束write_ddc(0x24,0x00,0x00); //重置地址指针}(2) 应用操作/*显示一个ASCII码函数*/void write_char(uchar x,uchary,uchar Charbyte){uint adress;adress = 16 * y + x; //文本显示write_ddc(0x24,(uchar)(adress),(uchar)(adress >> 8)); //地址指针位置write_dc(0xC4,Charbyte - 32); //数据一次读写方式,查字符rom}/*显示字符串函数,8*8点阵,x:左右字符间隔,y:上下字符间隔*/void display_string(ucharx,uchar y,uchar *p){while(*p != 0){write_char(x,y,*p);x++;p++;if(x > 15 ) //自动换行 128*64 //共16行0~15{x= 0;y++;}}}/*显示1个汉字,x:左右点阵间距(8点阵倍数),y:上下点阵间距(16点阵倍数)*/void write_hanzi(ucharx,uchar y,uchar z){unsigned int address;uchar m,n = 0;address = 16 * 16 * y + x + 0x0800; //显示图形for(m = 0;m < 16;m++)//1个汉字占上下16行{write_ddc(0x24,(uchar)(address),(uchar)(address>>8));write_dc(0xc0,ziku[z][n++]);write_dc(0xc0,ziku[z][n++]);//一个汉字横向取模为两个字节address =address + 16; //换行}}/*显示多个汉字,x:左右点阵间距(8点阵倍数),y:上下点阵间距(16点阵倍数),从第i个汉字开始显示,显示j- i个*/void display_hanzi(ucharx,uchar y,uchar i,uchar j){for(i;i < j;i++){write_hanzi(x,y,i);x = x + 2;}}/*显示两位数字,每一个8*8点阵,x:左右字符间隔,y:上下字符间隔*/void display_num(ucharx,uchar y,uchar i){uint adress;adress = 16 * y + x; //文本显示,每行16字符write_ddc(0x24,(uchar)(adress),(uchar)(adress >> 8)); //地址指针位置write_dc(0xc0,num[i / 10] -32);write_dc(0xc0,num[i % 10] - 32); //写两个数字}/*显示128*64图形*/void dispay_tuxing(void){uchar i,j;uint address,x;address = 0x0800; //首地址,图形显示for(i = 0;i < 64;i++)//64行{write_ddc(0x24,(uchar)(address),(uchar)(address>>8));for(j =0;j < 16;j++)//每行16字节{write_dc(0xc0,tuxing[x]);x++;}address =address + 16;//换行}}uchar code ziku[][32] ={/*-- 文字: 好 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x10,0x00,0x11,0xFC,0x10,0x08,0x10,0x10,0xFC,0x20,0x24,0x20,0x24,0x20,0x27,0xFE,0x44,0x20,0x64,0x20,0x18,0x20,0x08,0x20,0x14,0x20,0x26,0x20,0x44,0xA0,0x80,0x40,/*-- 文字: 人 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x01,0x00,0x01,0x80,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x80,0x02,0x80,0x04,0x80,0x04,0x40,0x08,0x60,0x08,0x30,0x10,0x18,0x20,0x0E,0x40,0x04,0x00,0x00, /*-- 文字: 一 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x7F,0xFE, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*-- 文字: 生 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x80,0x10,0xC0,0x10,0x80,0x10,0x88,0x1F,0xFC,0x20,0x80,0x20,0x80,0x40,0x88, 0x9F,0xFC,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x84,0x7F,0xFE,0x00,0x00, /*-- 文字: 平 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x7F,0xFC,0x01,0x00,0x21,0x10,0x11,0x18,0x09,0x10,0x0D,0x20,0x09,0x40,0x01,0x00, 0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, /*-- 文字: 安 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x02,0x00,0x01,0x00,0x3F,0xFE,0x20,0x04,0x44,0x08,0x06,0x00,0x04,0x00,0xFF,0xFE, 0x08,0x20,0x08,0x20,0x08,0x40,0x06,0x80,0x01,0x00,0x06,0xC0,0x18,0x38,0xE0,0x10, /*-- 文字: 祝 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x20,0x00,0x11,0xF8,0x11,0x08,0xFD,0x08,0x05,0x08,0x09,0x08,0x11,0x08,0x39,0xF8, 0x54,0x90,0x94,0x90,0x10,0x90,0x10,0x90,0x11,0x12,0x11,0x12,0x12,0x12,0x14,0x0E, /*-- 文字: 您 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x08,0x00,0x09,0x00,0x11,0xFE,0x12,0x04,0x34,0x40,0x32,0x50,0x52,0x48,0x94,0x44, 0x11,0x44,0x10,0x80,0x00,0x00,0x29,0x04,0x28,0x92,0x68,0x12,0x07,0xF0,0x00,0x00, /*-- 文字: 一 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x7F,0xFE, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*-- 文字: 帆 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x10,0x00,0x11,0xF0,0x11,0x10,0x7D,0x10,0x55,0x10,0x55,0x10,0x55,0x90,0x55,0x50, 0x55,0x70,0x55,0x50,0x5D,0x10,0x11,0x12,0x11,0x12,0x12,0x12,0x12,0x0E,0x14,0x00, /*-- 文字: 风 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x1F,0xF8,0x10,0x08,0x10,0x48,0x14,0x68,0x12,0x48,0x11,0x48,0x10,0x88, 0x10,0x88,0x11,0x48,0x12,0x6A,0x24,0x2A,0x28,0x26,0x40,0x06,0x80,0x02,0x00,0x00, /*-- 文字: 顺 --*//*-- Times New Roman12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x45,0xFE,0x54,0x20,0x54,0x40,0x55,0xFC,0x55,0x04,0x55,0x04,0x55,0x24, 0x55,0x24,0x55,0x24,0x55,0x24,0x54,0x20,0x44,0x50,0x84,0x8C,0x05,0x04,0x00,0x00, /*-- 文字: 时 --*//*-- 楷体_GB23129; 此字体下对应的点阵为:宽x高=12x12 --*//*-- 宽度不是8的倍数,现调整为:宽度x高度=16x12 --*/0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xCE,0xFF,0xAE,0xFF,0xAE,0x1F,0xA0,0xFF,0x8E,0xFF,0xA A,0xFF,0x8A,0xFF,0xAE,0xFF,0xFC,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*-- 文字: 间 --*//*-- 楷体_GB23129; 此字体下对应的点阵为:宽x高=12x12 --*//*-- 宽度不是8的倍数,现调整为:宽度x高度=16x12 --*/0xFF,0xFF,0xFF,0xFF,0xDE,0x7F,0xE9,0xBF,0xBF,0xBF,0xA1,0xBF,0xAD,0xBF,0xA1,0xBF, 0xAD,0xBF,0xA1,0xBF,0xBF,0xBF,0xBE,0xBF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, };。

单片机LCD12864介绍及设计实例

单片机LCD12864介绍及设计实例

R
R
W
S
2
1
1
1
1
1
1
1
1
3
2
3
1
1
0
7
6
5
4
3
2
1
0
0
9
1
9 8 9
VSS
P3.7/RD
P3.6/WR
P3.5/T1
P3.4/T0
P3.3/INT1
P3.2/INT0
P3.1/TxD
P3.0/RxD
ALE/PROG
PSEN
EA/VPP
RST
XTAL2
XTAL1
8
0
5
1
P1.7/CEX4
P1.6/CEX3
;将要操作的指令通过数据口发送
并口写指令时注意时序,RS拉低。注意写指令时不同指令的延时时间不同。
写数据:
LCDWD: LCALL NOP SETB CLR SETBE MOV CLRE NOP RET CHK_BUSY RS RW P2,A ;将要写入的数据通过数据口发送 ;并口写数据子程序 ;判忙子程序
P3.5/T1
P3.4/T0
P3.3/INT1
P3.2/INT0
P3.1/TxD
P3.0/RxD
ALE/PROG
PSEN
EA/VPP
RST
XTAL2
XTAL1
12.4串行模式
1
P1.7/CEX4
P1.6/CEX3
P1.5/CEX2
P1.4/CEX1
P1.3/CEX0
P1.1/T2EX
P0.7/AD7
72us
0
0

LCD12864程序文档

LCD12864程序文档

LCD12864串口显示使用详解LCD12864点阵液晶显示模块(LCM)就是由128*64个液晶显示点组成的一个128列*64行的阵列。

每个显示点对应一位二进制数,1表示亮,0表示灭。

存储这些点阵信息的RAM称为显示数据存储器,要显示某个图形或汉字就是将相应的点阵信息写入到相应的存储单元中。

LCD12864控制芯片:ST7920A 带中文字库MCU:STM32F103源程序下载地址:/detail/wylloong/8538839根据串行连接时序图所示,串行数据传送共分三个字节完成:第一字节:串口控制指令——格式 11111ABC 其中,A为数据传送方向控制:H表示数据从LCD到MCU,L表示数据从MCU到LCD;B为数据类型选择:H表示数据是显示数据,L表示数据是控制指令;C固定为0第二字节:(并行)8位数据的高4位——格式 DDDD0000第三字节:(并行)8位数据的低4位——格式 0000DDDD,发送时将低四位移至发送数据的高四位,即DDDD0000方能正确。

绘图RAM(GDRAM):绘图显示RAM提供128*8个字节的记忆空间,在更改绘图RAM时,先连续写入水平与垂直的坐标值,再写入两个字节的数据到绘图RAM,而地址计数器(AC)会自动加1;在写入绘图RAM的期间,绘图显示必须关闭。

整个写入绘图RAM的步骤如下:1、关闭绘图显示功能。

2、先将水平的位元组坐标(X)写入绘图RAM地址,再将垂直的坐标(Y)写入绘图RAM地址;将D15——D8写入到RAM中;将D7——D0写入到RAM 中;3、打开绘图显示功能。

带中文字库的128X64显示模块时应注意以下几点:①欲在某一个位置显示中文字符时,应先设定显示字符位置,即先设定显示地址,再写入中文字符编码。

②显示ASCII字符过程与显示中文字符过程相同。

不过在显示连续字符时,只须设定一次显示地址,由模块自动对地址加1指向下一个字符位置,否则,显示的字符中将会有一个空ASCII字符位置。

LCD12864液晶驱动编程指南

LCD12864液晶驱动编程指南

二、显示图片
显示图片和显示汉字的原理是一样的, 只不过是大小的问题! 现在我们就以一张 128*64 分辨率的图片进行取模。 取模图片:
现在我们主要看一下显isplay_BMP(uchar a[][64])//显示图形的左边部分 { uchar i,j; for(j=0;j<8;j++) { SelectScreen(1); Set_page(j); Set_column(0); for(i=0;i<64;i++) //显示左屏 { write_LCD_data(a[2*j][i]);//每隔一行取一次数组中的数据 } SelectScreen(2); Set_page(j); Set_column(0); for(i=0;i<64;i++) //显示右屏 { write_LCD_data(a[2*j+1][i]);//每隔一行取一次数组中的数据 } } } 取出图片的数据是二维数组形式!注意,液晶是先显示左半屏,再显示右半屏, 但 是取数组中的元素是逐个往下取出的, 所以是对于一个半屏而言, 每隔一行取数组中的元素, 而隔去的那一行是另一个半屏要取的数据!这一点一定要注意。 还有一点要补充的就是,这个取模软件只能识别 BMP 和 ICO 格式的单色图片,如果我 们选择的图片不是 128*64 大小的话, 可以通过软件将其改成 128*64 大小的, 如果我们直接 用软件取模的话,显示的会是乱码,解决办法是我们可以通过 windows 自带的画图工具, 什么也不做修改,将大小设置好的图片另存为 BMP 单色文件就行了,然后再用取模软件取 模就 OK 了,=^_^ = !算了,给大家截个图
LCD_databusrite_LCD_command(column);//列位置 } void SetOnOff(uchar onoff) //显示开关 函数:0x3E 是关显示,0x3F 是开显示 { onoff=0x3e|onoff; //0011 111x,onoff 只能为 0 或者 1 write_LCD_command(onoff); } void SelectScreen(uchar screen) //选屏 { switch(screen) { case 0: CS1=0;CS2=0;break; //全屏 case 1: CS1=0;CS2=1;break;//左半屏 case 2: CS1=1;CS2=0;break;//右半屏 default:break; } } void ClearScreen(uchar screen) { uchar i,j; SelectScreen(screen); for(i=0;i<8;i++)//控制页数 0-7,共 8 页 { Set_page(i); Set_column(0); for(j=0;j<64;j++) //控制列数 0-63,共 64 列 { write_LCD_data(0x00); //写入 0,地址指针自加 1 } } } void InitLCD() { Read_busy(); SelectScreen(0); SetOnOff(0); //关显示 SelectScreen(0); SetOnOff(1); //开显示 SelectScreen(0); //LCD 的初始化 } void main() { InitLCD(); ClearScreen(0); Set_line(0); Display(1,0,2*16,huan);//欢 Display(1,0,3*16,ying);//迎 Display(2,0,0*16,fang);//访 Display(2,0,1*16,wen);//问 Display(1,2,0*16,da);//大 Display(1,2,1*16,hai);//海 Display(1,2,2*16,xiang);//橡 Display(1,2,3*16,shu);//树 Display(2,2,0*16,bai);//百 Display(2,2,1*16,du);//度 Display(2,2,2*16,kong);//空 Display(2,2,3*16,jian);//间 While(1); } //初始化 //清屏 //显示开始行 } //清屏 据输出 { write_LCD_data(p[i+16]); //汉字的下半部分 上半部分 } Set_page(page+1); //写下半页 Set_column(column); for(i=0;i<16;i++) //控制列 //控制 16 列的数 } void Display(uchar ss,uchar page,uchar column,uchar *p) { uchar i; SelectScreen(ss); Set_page(page); for(i=0;i<16;i++) 的数据输出 { write_LCD_data(p[i]); //汉字的 //写上半页 //控制 16 列 Set_column(column); //控制列 //显示汉字 ClearScreen(0);//清屏 Set_line(0); //开始行:0
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档