HD44780http://blog.sina.com.cn/s/blog_61b6e08b01016xif.html
学习笔记:12864液晶模块的详细使用
(2012-10-17 09:23:32)
标签:
杂谈 |
分类: 电子学 |
对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 != '\0'){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
wrtcom_12864(0x90); //写屏幕第二行字符
if(*ptdat != '\0'){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
wrtcom_12864(0x88);//写屏幕第三行字符
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
wrtcom_12864(0x98);//写屏幕第四行字符
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
wrtcom_12864(0xa0); //写DDRAM第3行数据
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
wrtdat_12864(*ptdat++);
}else{
wrtdat_12864(0x20);
over++;
}
}
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
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 != '\0'){
wrtdat_12864(*ptdat++); //写入高字节
}else{
wrtdat_12864(0x20); //字符串结束则写入空字符
}
if(*ptdat != '\0'){
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 != '\0'){
wrtdat_12864(*ptdat++); //写入高字节
}else{
over++; //写完最后一行字符,需要再卷动16次才能显示出来。
wrtdat_12864(0x20); //字符串结束则写入空字符
}
if(*ptdat != '\0'){
wrtdat_12864(*ptdat++); //写入低字节
}else{
wrtdat_12864(0x20); //字符串结束则写入空字符
}
}
else {break;}
}
}
}
HD44780http://blog.sina.com.cn/s/blog_61b6e08b01016xif.html相关推荐
- http://blog.sina.com.cn/s/blog_5bd6b4510101585x.html
http://blog.sina.com.cn/s/blog_5bd6b4510101585x.html 转载于:https://www.cnblogs.com/longshiyVip/p/59333 ...
- http://blog.sina.com.cn/s/blog_6145ed810102vr8k.html
http://blog.sina.com.cn/s/blog_6145ed810102vr8k.html 转载于:https://www.cnblogs.com/toSeeMyDream/p/5801 ...
- http://blog.sina.com.cn/s/blog_4aae007d0100inxi.html
http://blog.sina.com.cn/s/blog_4aae007d0100inxi.html 转载于:https://www.cnblogs.com/qxql2016/p/4693885. ...
- http://blog.sina.com.cn/s/blog_5007d1b10100ltwh.html
http://blog.sina.com.cn/s/blog_5007d1b10100ltwh.html
- http://blog.sina.com.cn/s/blog_6364150101018hby.html
http://blog.sina.com.cn/s/blog_6364150101018hby.html
- http://blog.sina.com.cn/s/blog_5da93c8f0102w86x.html
转至:http://blog.sina.com.cn/s/blog_5da93c8f0102w86x.html 参考:http://droidyue.com/blog/2015/04/12/avoid ...
- http://blog.sina.com.cn/s/blog_49867dc00100zj7t.html
http://blog.sina.com.cn/s/blog_49867dc00100zj7t.html JSON-lib框架,转换JSON.XML不再困难 Json-lib可以将Java对象转成js ...
- 我在新浪的微博: http://blog.sina.com.cn/wenxy1
我在新浪的微博: http://blog.sina.com.cn/wenxy1 从今以后, 技术性文章在CSDN发布, 生活见闻在sina微博发布,不知道CSDN和sina的微博可不可以同步?
- Get more...go to my another blog...http://blog.sina.com.cn/qqlove163
Get more...go to my another blog...http://blog.sina.com.cn/qqlove163
最新文章
- 【Python金融量化 8- 100 】八、计算投资组合风险
- OpenCV+yolov2-tiny实现目标检测(C++)
- 3.0 go mod之远程仓库搭建-代码示例
- Java工作笔记-发送SOAP协议请求
- 干货:12个案例教你用Python玩转数据可视化(建议收藏)
- Linux 下查看线程信息
- 主板和cpu搭配表_主板和CPU如何搭配?主板和处理器搭配方法
- php环境informix,在Nginx + php-fpm(fastcgi)环境下配置informix的连接
- vue 实现文本的拖拽_Vue-实现简单拖拽(自定义属性)
- python怎么学比较有技巧_Python爬虫应该怎么学?程序猿花了一周整理的学习技巧,请收下...
- 谷歌中国算法比赛解题报告 APAC2017C
- mysql 笛卡尔积
- Godaddy域名注册详细图文教程(转)
- uva 10019 Funny Encryption Method
- Python爬虫大众点评字体加密评论采集!听说这个网站很难?
- 检测到已经有其他更新程序正在运行,请结束后再试的解决
- oracle log_archive_dest_1 未指定导致flash_recovery_area引发数据库挂起
- linux 命令之jq
- constraint PK_LDBACKUPTEXTINFO primary key (xx) using index tablespace lisi
- 浅谈text段、data段和bss段