找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2255|回复: 0
打印 上一主题 下一主题
收起左侧

单片机如何在LCD12864上任意画点

[复制链接]
跳转到指定楼层
楼主
ID:355219 发表于 2020-5-2 09:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  • 关于12864的画图功能。
我们知道在纸上画出一个点,我们要知道这个点在张纸上面的位置,也就是这个点在这张纸上面的坐标。而在12864上面画点也是一样,我们要先知道这个点在液晶屏上面的坐标,然后我们该坐标点黑或是点白可以了。而在这之前,我们要首先理解12864图形显示坐标。
12864的绘图显示坐标如图所示:
需要注意的是它的水平位址并不是一个点有一个位址的,它是16个格才有一个位址。它的垂直位址也分为上下两半部分。当我们给出位址是X是0,Y是0的时候,其实里面包含了16个点,也就是说我们一次要操作16个点。所有当我们要点亮一个点的时候,我们不仅要知道的位址,还要知道它在这个位址中是第几个位,也就是第几个点。
#include<reg52.h>

#define uint unsigned int
#define uchar unsigned char

sbit RS=P2^6;  //这个是LCD的数据命令选择端
sbit RW=P2^5;  //这个是LCD的写入或是读出选择端
sbit PSB=P3^2; //这个是LCD串行还是并行选择端
sbit RST=P3^4; //这个是LCD的复位端口
sbit LCDE=P2^7; // 这个是LCD的使能端
/*
延时子函数
*/
void delay(uint x)
{
              uint y;
              for(;x>0;x--)
                            for(y=110;y>0;y--);
}
/*
忙碌检查
*/
void lcd_busy()
{
              RS=0;
              RW=1;
              P0=0XFF;
              LCDE=1;
              delay(2);
              while((P0&0x80)==0x80);
/*如下图1,当LCD忙碌的时候BF位是为1,而我们只需要想知道这位,所有与上0x80,当它是1的时候得到0X80,当它是0的时候得到0.*/
              LCDE=0;
}
/*
写入命令
*/
void write_com(uchar com)
{
              lcd_busy();
/*每次操作LCD之前都需要检查一次LCD是否忙碌,不过一般LCD工作比单片机快,所有都不用检查。*/
              RS=0;
              RW=0;
              LCDE=0;
              P0=com;
              delay(1);
              LCDE=1;
              delay(3);
              LCDE=0;
}
/*
写入数据
*/
void write_num(uchar num)
{
              lcd_busy();
              RS=1;
              RW=0;
              LCDE=0;
              P0=num;
              delay(1);
              LCDE=1;
              delay(3);
              LCDE=0;
}
/*
读取数据
*/
uchar read_data()
{
              uchar read;
              lcd_busy();
              RS=1;
              RW=1;
              LCDE=0;
              delay(1);
              LCDE=1;
              delay(3);
              read=P0;
              LCDE=0;
              delay(5);;

              return read;
}
/*
画图清屏,由于LCD的清屏指令0X01不能作用在绘图中,所有只能自己写清屏子程序
*/
void clear_lcd()
{            
              uchar i,j;
              write_com(0x34);
              for(i=0;i<32;i++)                                            //因为LCD有纵坐标32格所以写三十二次
              {
                            write_com(0x80+i);                              //先写入纵坐标Y的值
                            write_com(0x80);                              //再写入横坐标X的值
                            for(j=0;j<32;j++)                              //横坐标有16位,每位写入两个字节的的数据,也就写入32次
                            {                                                                                      //因为当写入两个字节之后横坐标会自动加1,所以就不用再次写入地址了。
                                          write_num(0x00);               
                            }
              }
              write_com(0x36);
              write_com(0x30);
}
/*
写入一个点的子程序。具体步骤是:计算出X轴、Y轴的地址、X轴中的第几位,然后读出该地址现在的值,因为一般写入新的点的时候,会覆盖掉16个点中其他点,当你要同时显示16个点中的两个点的时候就会冲突,所以先将显示中的点读出来,然后在或上要点亮的点,这样就可以同时点亮。注意读取数据的时候读取的第一个数据不要,从第二数据开始取,也就是说要读取三次,只取后面两次的值。还有就是读取数据之前要先写入你要读取数据的地址,读取数据之后的写入数据还要从新写入地址。最后就是输入数据地址,先输入Y轴,再输入X轴,输入数据。
*/
void put_point(uchar x,uchar y)
{
              uint bt=0,read=0;
              uchar x_adr,y_adr,h_bit,l_bit;
              y_adr=0x80+y%32;                                          //计算Y轴的地址,应为纵坐标有64个,所有对32求余,当Y大于31时,Y的坐标是下半屏的。
              if(y>31)            //计算X轴的地址当Y大于31时X的地址在下半屏,从0X88开始,小于31时X的地址是在上半屏,从0X80开始
                            x_adr=0x88+x/16;                           
              else
                            x_adr=0x80+x/16;
              bt=0x8000>>(x%16);  //求这个点到底是在哪个点
              write_com(0x34);
              write_com(0x34);
              write_com(y_adr);                //读取数据的时候要先写入所取数据的地址
              write_com(x_adr);
              read_data();                              //读取的第一个字节不要,
              read=read_data();                //从第二个字节开始接收。
              read<<=8;
              read|=read_data();
              bt=bt|read;
              h_bit=bt>>8;
              l_bit=bt;
              write_com(y_adr);                 //写入点的时候,重新写入地址,因为地址已经改变。
              write_com(x_adr);
              write_num(h_bit);
              write_num(l_bit);
              write_com(0x36);    //开显示
              write_com(0x30);                //转回基本指令集                           
}
/*
液晶初始化
*/
void lcd_init()
{
              PSB=1;
              RST=1;
              write_com(0x30);              //基本指令操作
              write_com(0x0c);              //开显示
              write_com(0x01);              //清除LCD显示
}

void main()
{            
              float i;
              uchar x,y;
              lcd_init();
              clear_lcd();
              while(1)
              {               
                            write_com(0x34);
                            write_com(0x34);
                            write_com(0x80);
                            write_com(0x88);
                            for(i=16;i>0;i--)  //画出X轴
                            {
                                          write_num(0xff);            
                            }
                            for(i=0;i<64;i++)   //画出Y轴
                            {
                                          put_point(0,i);
                            }
                            for(i=0;i<128;i++)
                            {
                                          x=i;
                                          y=32-x%32;
                                          put_point(x,y);
                            }
                            write_com(0x36);
                            write_com(0x30);  
                            while(1);
              }

}

完整代码下载:http://www.51hei.com/bbs/dpj-186495-1.html
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表