学习笔记:12864液晶模块的…
对12864的所有操作概括起来有4种:
上图只是把2个字符的CGRAM空间画出来,后续还有2个字符。可以看到每个字符都有16行16列,每一行使用2个字节,因此一个字符占用的空间是32字节,地址是6位的,4个字符的地址分别是:00H~0FH、10H~1FH、20H~2FH、30H~3FH。编码使用2个字节,可以看到有2个位是任意的,说明其实这4个字符的编码可以有多个,只是我们常用前面列举的4个编码。
E:使能端
根据时序图可以编写相应的写命令函数、写数据函数、读数据函数、读状态函数。需要的注意的是有效数据出现的那段时间Tc必须合适,不能太短,否则会造成读写失败。
void busychk_12864(void){
E_12864 = 0;
RS_12864 = 0;
RW_12864 = 1;
E_12864 = 1;
while((IO_12864 & 0x80) && ++timeout != 0); //忙状态检测,等待超时时间为60ms
E_12864 = 0;
void wrtcom_12864(unsigned char com){
E_12864 = 0;
RS_12864 = 0;
RW_12864 = 0;
IO_12864 = com;
E_12864 = 1;
delay_12864(50); //50us使能延时!!!注意这里,如果是较快的CPU应该延时久一些
E_12864 = 0;
}
unsigned char reddat_12864(void){
unsigned char temp;
E_12864 = 0;
IO_12864 = 0xff; //IO口置高电平,读引脚
RS_12864 = 1;
RW_12864 = 1;
E_12864 = 1;
delay_12864(50); //使能延时!!!注意这里,如果是较快的CPU应该延时久一些
temp = IO_12864;
return temp;
}
void wrtdat_12864(unsigned char dat){
E_12864 = 0;
RS_12864 = 1;
RW_12864 = 0;
E_12864 = 1;
IO_12864 = dat;
delay_12864(50); //使能延时!!!注意这里,如果是较快的CPU应该延时久一些
E_12864 = 0;
}
可以看到实际上原来第三第四行开始的字符跑到了第一行第二行的末尾,整个DDRAM的结构就是一种循环的结构,发生屏移时DDRAM与显示映射关系不断在改变。但是这不太符合我们的阅读习惯,所以如果需要使用该项功能还需编程校正之。
说明:
wrtcom_12864(0x03); //允许输入卷动地址
wrtcom_12864(0x40 + 地址 //设置卷动地址
wrtcom_12864(0x30); //回到基本指令
wrtcom_12864(0x04); //开启反白显示
delay_12864(60000); //延时
delay_12864(60000); //延时
wrtcom_12864(0x30); //开启基本指令集
初始化函数如下:
void delay_12864(unsigned int del){
unsigned int i;
for(i = 0; i < del; i++){; }
}
void initial_12864(void){
RST_12864 = 1;
RST_12864 = 0; //复位
delay_12864(500);
RST_12864 = 1;
delay_12864(100);
wrtcom_12864(0x30); //设置为基本指令集动作
delay_12864(37);
wrtcom_12864(0x08); //设置显示、光标、闪烁全关。
delay_12864(100);
wrtcom_12864(0x01); //清屏,并且DDRAM数据指针清零
delay_12864(100000);
wrtcom_12864(0x06); //进入模式设置
}
sbit RW_12864 = P2^6;
sbit E_12864 = P2^7;
sbit RST_12864 = P2^2;
void busychk_12864(void){
E_12864 = 0;
RS_12864 = 0;
RW_12864 = 1;
E_12864 = 1;
while((IO_12864 & 0x80) && ++timeout != 0); //忙状态检测,等待超时时间为60ms
E_12864 = 0;
void wrtcom_12864(unsigned char com){
E_12864 = 0;
RS_12864 = 0;
RW_12864 = 0;
IO_12864 = com;
E_12864 = 1;
delay_12864(50); //使能延时!!!注意这里,如果是较快的CPU应该延时久一些
E_12864 = 0;
}
unsigned char reddat_12864(void){
unsigned char temp;
E_12864 = 0;
IO_12864 = 0xff; //IO口置高电平,读引脚
RS_12864 = 1;
RW_12864 = 1;
E_12864 = 1;
delay_12864(50); //使能延时!!!注意这里,如果是较快的CPU应该延时久一些
temp = IO_12864;
return temp;
}
void wrtdat_12864(unsigned char dat){
E_12864 = 0;
RS_12864 = 1;
RW_12864 = 0;
E_12864 = 1;
IO_12864 = dat;
delay_12864(50); //使能延时!!!注意这里,如果是较快的CPU应该延时久一些
E_12864 = 0;
}
void initial_12864(void){
RST_12864 = 1;
RST_12864 = 0; //复位
delay_12864(500);
RST_12864 = 1;
delay_12864(100);
wrtcom_12864(0x30); //设置为基本指令集动作
delay_12864(37);
wrtcom_12864(0x08); //设置显示、光标、闪烁全关。
delay_12864(100);
wrtcom_12864(0x01); //清屏,并且DDRAM数据指针清零
delay_12864(100000);
wrtcom_12864(0x06); //进入模式设置
}
void clnGDR_12864(void) //清空GDRAM
void drawdot_12864(unsigned char y,unsigned char x,unsigned char type) //画点子函数
void clnGDR_12864(void){
for( j = 0 ; j < 32 ; j++ )
{
wrtcom_12864(0x80 + j) ; //写Y 坐标
wrtcom_12864(0x80) ; //写X 坐标
for( k = 0 ; k < 32 ; k++ ) //写一整行数据
{
wrtdat_12864( 0x00 );
}
}
}
//右下角为(63,127),点坐标形式为(行坐标,列坐标)
//参数type用于设置画黑点、白点或取反(黑变白,白变黑)
//type = 0为白色,1 为黑色,2为取反
void drawdot_12864(unsigned char y,unsigned char x,unsigned char type){
unsigned char X,Y,k; //X存储行地址,Y存储列地址
unsigned char DH,DL; //存放读出数据的高字节和低字节
if(y >= 0 && y <= 63 && x >= 0 && x <= 127) {
if(y < 32){ //算法:确定所画点的地址行与列地址
X = 0x80 + (x >> 4);
Y = 0x80 + y;
}else{
X = 0x88 + (x >> 4);
Y = 0x80 + (y - 32);
}
wrtcom_12864(0x34); //开启扩展指令,关闭绘图显示
wrtcom_12864(Y); //写入所确定的点的行位地址
wrtcom_12864(X); //写入所确定的点的列字地址
DH = reddat_12864(); //假读
DH = reddat_12864(); //读高字节
DL = reddat_12864(); //读低字节
k = x % 16; //余数为点在字中的位置
switch(type){ //画点类型,1黑或0白或2取反
case 0:
if(k < 8){ //点在高字节
DH &= ~(0x01 << (7 - k)); //修改该点同时保持其他位不变
}else{ //点在低字节
DL &= ~(0x01 << (7 - (k % 8))); //修改该点同时保持其他位不变
}
break;
case 1:
if(k < 8){
DH |= (0x01 << (7 - k)); //修改该点同时保持其他位不变
}else{
DL |= (0x01 << (7 - (k % 8))); //修改该点同时保持其他位不变
}
break;
case 2:
if(k < 8){
DH ^= (0x01 << (7 - k)); //修改该点同时保持其他位不变
}else{
DL ^= (0x01 << (7 - (k % 8))); //修改该点同时保持其他位不变
}
break;
default:
break;
}
wrtcom_12864(Y); //写行位地址
wrtcom_12864(X); //写列字地址
wrtdat_12864(DH); //将高字节数据写回
wrtdat_12864(DL); //将低字节数据写回
wrtcom_12864(0x30); //转回普通指令
}
}
initial_12864();
drawdot_12864(20,50,1); //画点
wrtcom_12864(0x36); //开绘图显示
}
void drawrec_12864(unsigned char y1,unsigned char x1,unsigned char y2,unsigned char x2,unsigned char type){
unsigned char largex,largey,smallx,smally; //将两点横纵坐标按大小存储
unsigned char i;
largex = x1;
smallx = x2;
}else{
largex = x2;
smallx = x1;
}
if(y1 > y2){
largey = y1;
smally = y2;
}else{
largey = y2;
smally = y1;
}
drawdot_12864(largey,i,type);
}
for(i = largey; i > smally; i--){
drawdot_12864(i,largex,type);
}
for(i = largex; i > smallx; i--){
drawdot_12864(smally,i,type);
}
for(i = smally; i < largey; i++){
drawdot_12864(i,smallx,type);
}
wrtcom_12864(0x30); //返回普通指令
}
initial_12864();
drawrec_12864(20,50,30,120,1); //画矩形
}
此时,屏幕接着滚动,显示内容涉及3行的DDRAM,如下:
第一行DDRAM是空余的,下次就该往第一行写数据,写完后DDRAM内容如下:
unsigned char i,addr,flag,hang,over,*ptdat;
initial_12864();
over = 0; //写入空字符数
for(i = 0; i < 16; i++){
if(*ptdat != ''){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
wrtcom_12864(0x90); //写屏幕第二行字符
if(*ptdat != ''){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
wrtcom_12864(0x88);//写屏幕第三行字符
for(i = 0; i < 16; i++){
if(*ptdat != ''){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
wrtcom_12864(0x98);//写屏幕第四行字符
for(i = 0; i < 16; i++){
if(*ptdat != ''){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
wrtcom_12864(0xa0); //写DDRAM第3行数据
for(i = 0; i < 16; i++){
if(*ptdat != ''){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
for(i = 0; i < 16; i++){
if(*ptdat != ''){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
if(over > 15){;} //显示字符不足4行,不卷动
else //显示字符大于4行,开启卷动
{
flag = 0x01; //初始卷动地址为1
while(1){
switch(hang){ //设置写入DDRAM的地址
case 1: addr = 0x80; break; //往地址变量中写第一行首地址
case 2: addr = 0x90; break; //往地址变量中写第二行首地址
case 3: addr = 0xa0; break; //往地址变量中写第三行首地址
case 4: addr = 0xb0; break; //往地址变量中写第四行首地址
switch(hang){ //指出下一次要写的行地址
case 1: hang = 2; break;//第1行写完了,下一行要写第2行
case 2: hang = 3; break;//第2行写完了,下一行要写第3行
case 3: hang = 4; break;//第3行写完了,下一行要写第4行
case 4: hang = 1; break;//第4行写完了,下一行要写第1行
}
//后续代码为往每一行写数据,卷动一次写一个字。
ptdat = ptdat - 32;
for(i = 0; i < 8; i++){ //写一行中的前8个字符
wrtcom_12864(0x34); //打开扩展指令
wrtcom_12864(0x03); //允许输入卷动地址
wrtcom_12864(0x40 + flag++); //设置卷动地址
wrtcom_12864(0x30); //回到基本指令
wrtcom_12864(addr + i);
delay_12864(20000);
if(*ptdat != ''){
wrtdat_12864(*ptdat++); //写入高字节
}else{
wrtdat_12864(0x20); //字符串结束则写入空字符
}
if(*ptdat != ''){
wrtdat_12864(*ptdat++); //写入低字节
}else{
wrtdat_12864(0x20); //字符串结束则写入空字符
}
}
ptdat = ptdat + 16;
for(i = 8; i < 16; i++){ //写一行中的后8个字符
wrtcom_12864(0x34); //打开扩展指令
wrtcom_12864(0x03); //允许输入卷动地址
if(flag == 64){flag = 0;}
wrtcom_12864(0x40 + flag); //设置卷动地址
flag++;
wrtcom_12864(0x30); //回到基本指令
wrtcom_12864(addr + i);
delay_12864(20000);
if(*ptdat != ''){
wrtdat_12864(*ptdat++); //写入高字节
}else{
over++; //写完最后一行字符,需要再卷动16次才能显示出来。
wrtdat_12864(0x20); //字符串结束则写入空字符
}
if(*ptdat != ''){
wrtdat_12864(*ptdat++); //写入低字节
}else{
wrtdat_12864(0x20); //字符串结束则写入空字符
}
}
else {break;}
}
}
}
学习笔记:12864液晶模块的…相关推荐
- 170504_(读书笔记)ST7920驱动12864液晶模块学习
学习芯片,应该以数据手册为主,书本为辅,学习ST7920驱动芯片手册地址 ST7920手册 先把手册看一遍,不求快,只求弄懂 170514: 1.ST7920数据手册看了两遍,但是还是不太清楚具体操作 ...
- 12864液晶深入学习笔记_1——基于msp430g2553
12864液晶学习笔记 Created on: 2012-8-30 Author: zhang bin 这是我对12864的学习笔记,12864液晶功能很全面,使用起来也很方便,能够满足一般的研究和工 ...
- (实验12)单片机,STM32F4学习笔记,代码讲解【OLED显示实验】【正点原子】【原创】
文章目录 其它文章链接,独家吐血整理 实验现象 主程序 OLED初始化程序 代码讲解 其它文章链接,独家吐血整理 (实验3)单片机,STM32F4学习笔记,代码讲解[按键输入实验][正点原子][原创] ...
- STC15W4K56S4学习笔记——LCD12864滚动显示
STC15W4K56S4学习笔记--LCD12864滚动显示 最近在准备学校的单片机校赛,重新回顾了一遍51单片机,上手了STC15W4K56S4试验箱,写一些笔记来记录一下,水平有限,有错误的希 ...
- PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call
您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...
- 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程
暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...
- 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移
暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...
- 2020年Yann Lecun深度学习笔记(下)
2020年Yann Lecun深度学习笔记(下)
- 2020年Yann Lecun深度学习笔记(上)
2020年Yann Lecun深度学习笔记(上)
最新文章
- 成功导入并运行breeze jar库
- 最新发布丨金融新基建系列报告:银行业六大中期趋势展望
- 机器人实现屠宰自动化
- NHibernate中的SchemaExport
- Iphone 手机如何导入/导出通讯录
- [html] 一个标签上同时出现三个或多个class属性,请问它的渲染顺序是怎样的?
- Material Design实现的美观的登录界面
- 我对软件发展的思考,一个不变却一直在变的话题
- python列表连接_Python连接列表
- nginx+lua+redis实现post请求接口之黑名单(一)
- 显示器信号接口的发展历程
- 数据共享是未来?通用福特丰田联手推进自动驾驶标准制定...
- 国产操作系统之统信UOS安装
- 将文件从ubuntu拷贝到linux开发板
- 关于FTP服务器出现227 Entering Passive Mode错误的解决思路
- php设置北京时间(时区)
- 牛客bfs:工厂流水线
- 手机抢红包助手深陷作弊指责 部分外挂植入木马
- 西部之旅之------相机的选择
- php curl couldnt connect to host,linux curl命令:curl: (7) couldn't connect to host ?