找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4305|回复: 1
收起左侧

12864增加画点功能程序

[复制链接]
ID:26188 发表于 2015-2-18 01:06 | 显示全部楼层 |阅读模式
//LCD显示器端口定义
#define LCD_RS          P21    // LCD数据/命令(H/L)选择端
#define LCD_RW          P22    // LCD读/写(H/L)选择端
#define LCD_EN          P23    // LCD使能信号高有效
#define LCD_DATA        P0     // LCD并行数据线
#define LCD_BUSY        P07    // LCD忙信号位
//12864特殊端口
//#define LCD_12864_CSA P24    // LCD12864左半屏选择端
//#define LCD_12864_CSB P25    // LCD12864右半屏选择端
//12864基本指令集********************************************************************
#define LCD_12864_CLR                   0x01    //清屏,AC、光标归零,DDRAM填满0x20H
#define LCD_12864_GO_HOME               0x02    //AC、光标归零,DDRAM不改变
//输入方式设置
#define LCD_12864_AC_AUTO_INCREMENT     0x06    //数据读、写操作后,AC自动增一
#define LCD_12864_AC_AUTO_DECREASE      0x04    //数据读、写操作后,AC自动减一
#define LCD_12864_MOVE_ENABLE           0x05    //数据读、写操作,画面平移
#define LCD_12864_MOVE_DISENABLE        0x04    //数据读、写操作,画面不动
//设置显示、光标及闪烁开、关
#define LCD_12864_DISPLAY_ON            0x0C    //显示开
#define LCD_12864_DISPLAY_OFF           0x08    //显示关
#define LCD_12864_CURSOR_ON             0x0A    //光标显示
#define LCD_12864_CURSOR_OFF            0x08    //光标不显示
#define LCD_12864_CURSOR_BLINK_ON       0x09    //光标闪烁
#define LCD_12864_CURSOR_BLINK_OFF      0x08    //光标不闪烁
//光标、画面移动,不影响DDRAM
#define LCD_12864_LEFT_MOVE             0x18    //LCD显示(整屏)左移一位 0x05
#define LCD_12864_RIGHT_MOVE            0x1C    //LCD显示(整屏)右移一位 0x07
#define LCD_12864_CURSOR_LEFT_MOVE      0x10    //光标左移一位
#define LCD_12864_CURSOR_RIGHT_MOVE     0x14    //光标右移一位
//指令集设置
#define LCD_12864_BASIC_INSTRUCTION     0x30    //使用基本指令集
#define LCD_12864_EXPAND_INSTRUCTION    0x34    //使用扩充指令集
//地址设定
#define LCD_12864_BASIC_CGRAM           0x40    //设定CGRAM地址到地址计数器(AC)64X256 点阵显示RAM(GDRAM)。
#define LCD_12864_BASIC_DDRAM           0x80    //设定DDRAM地址到地址计数器(AC)
//12864扩充指令集********************************************************************
#define LCD_12864_ORDER                 0x01    //待命模式将DDRAM 填满“ 20H ”, 并且设定DDRAM 的地址计数器(AC)到“00H”
#define LCD_12864_IRAM_ON               0x02    //允许输入IRAM地址
#define LCD_12864_VERTICAL_ADDRESS_ON   0x03    //允许输入垂直卷动地址
//反白显示
#define LCD_12864_UP_ONE                0x04    //第一行反白显示
#define LCD_12864_UP_TWO                0x05    //第二行反白显示
#define LCD_12864_UP_THREE              0x06    //第三行反白显示
#define LCD_12864_UP_FOUR               0x07    //第四行反白显示
//睡眠模式
#define LCD_12864_SLEEP_ON              0x08    //进入睡眠模式
#define LCD_12864_SLEEP_OFF             0x0c    //脱离睡眠模式
//在扩充指令集时的指令选择
#define LCD_12864_BASIC_INSTRUCTION     0x30    //基本指令集
#define LCD_12864_EXPAND_INSTRUCTION    0x34    //扩充指令集
#define LCD_12864_DRAW_OFF              0x34    //绘图显示关
#define LCD_12864_DRAW_ON               0x36    //绘图显示开
//地址设定
#define LCD_12864_EXPAND_IRAM           0x40    //SR=1:AC5—AC0 为垂直卷动地址SR=0:AC3—AC0 为ICON IRAM 地址
#define LCD_12864_EXPAND_CGRAM          0x80    //设定CGRAM 地址到地址计数器(AC)
//LCD函数声明*************************************************************************
void LCD_Delay_us(unsigned int us);                        //LCD延时微秒级
unsigned char LCD_BUSY_Bit(void);                          //解决忙问题
void LCD_Write_Command(unsigned char byteData);        //写指令
void LCD_Write_DATA(unsigned char byteData);               //写数据
unsigned char LCD_Read_Data();                             //从内部RAM读取数据
void LCD_12864_Initialization(void);                       //12864初始化
void LCD_12864_bitInitialization(void);                    //图形初始化
void LCD12864_WH_String(unsigned char x,unsigned char y,unsigned char *s); //写入字符函数
void LCD_Read_dat_I(unsigned char *xp,unsigned char *yp);  //读绘图RAM指定点数据函数
void cls_lcd(unsigned char dat);                                            //初始化绘图RAM并清屏函数
void LCD_DrawingPoint(unsigned char xp,unsigned char yp,bit dat);  //绘图RAM画点函数  
//写入字符串到第x(1,2,3,4)行y(1,16)列 //中间可以有汉字,并自动插入空格
//void LCD_12864_DRAW_CGRAM(UCHAR x,UCHAR *ZOON_CHAR) ;/*CGRAM.x (0-15)的分区数据写入  */
/***************************************************************************************
** 函数名称: LCD_Delay_us(unsigned int us)
** 功能描述: 微秒延时
****************************************************************************************/
void LCD_Delay_us(unsigned int us)
{
    while(us--);
}
/***************************************************************************************
** 函数名称: void LCD_12864_Initialization(void)
** 功能描述: 12864LCD字符输入初始化函数
** 调用模块: LCD_Write_Command();
****************************************************************************************/
void LCD_12864_Initialization(void)   
{
    LCD_Write_Command(LCD_12864_BASIC_INSTRUCTION);               //使用基本指令集
    LCD_Write_Command(LCD_12864_AC_AUTO_INCREMENT);               //数据读、写操作后,AC自动增一,画面不动
    LCD_Write_Command(LCD_12864_DISPLAY_ON|LCD_12864_CURSOR_OFF); //显示开光标不显示光标不闪烁
    LCD_Write_Command(LCD_12864_ORDER);                           //清屏
}
/***************************************************************************************
** 函数名称: unsigned char LCD_BUSY_Bit(void)
** 功能描述: 解决忙问题,等待DB07为空
** 说    明:返回当前AC地址
****************************************************************************************/
unsigned char LCD_BUSY_Bit(void)   
{
    bit byteData;
    do
    {                              //循环开始
        LCD_EN = 0;                //使能关
        LCD_RS = 0;                //1数据0指令
        LCD_RW = 1;                //1读0写
        LCD_DATA = 0xff;           //拉高数据口电位
        LCD_EN = 1;                //使能开
        byteData = LCD_BUSY;       //取状态字DB07的结果  
    }while(byteData);              //循环终点 读到 忙位为0退出,否则继续读忙。
    return((LCD_DATA&0x7F)+0x80);  //返回AC的值
    LCD_EN = 0;                    //使能关
}
/***************************************************************************************
** 函数名称: void LCD_Write_Command(unsigned char byteData)
** 功能描述: 写指令
** 输   入: unsigned char byteData 写指令
** 调用模块: LCD_BUSY_Bit();
****************************************************************************************/
void LCD_Write_Command(unsigned char byteData)
{
    LCD_BUSY_Bit();       //读忙
    LCD_EN = 0;           //使能关
    LCD_RS = 0;           //指令方式
    LCD_RW = 0;           //写LCD
    LCD_DATA = byteData;  //指令写入数据口
    LCD_EN = 1;           //使能开
    LCD_Delay_us(4);      //微秒延时
    LCD_EN = 0;           //使能关
}
/***************************************************************************************
** 函数名称: void LCD_Write_DATA(unsigned char byteData)
** 功能描述: 写数据
** 输   入: unsigned char byteData 写数据
** 调用模块: LCD_BUSY_Bit(); LCD_Delay_us();
****************************************************************************************/
void LCD_Write_DATA(unsigned char byteData)
{
    LCD_BUSY_Bit();       //读忙
    LCD_EN = 0;           //使能关
    LCD_RS = 1;           //数据方式
    LCD_RW = 0;           //写LCD
    LCD_DATA = byteData;  //数据写入数据口
    LCD_EN = 1;           //使能开
    LCD_Delay_us(4);      //微秒延时
    LCD_EN = 0;           //使能关
}
/***************************************************************************************
** 函数名称: unsigned char LCD_Read_Data()
** 功能描述: 读取并返回AC指向的数据
** 说    明: 函数外设定AC地址,第一次试读读出高位,第二次会再次读出高位,第三次读出低位,
** 然后AC自动加一,在接下来的读取中,只要不再次指定AC,可按AC顺序读取
****************************************************************************************/
unsigned char LCD_Read_Data()
{
    LCD_BUSY_Bit();
    LCD_EN = 0;                 //使能关
    LCD_RS = 1;                 //数据方式
    LCD_RW = 1;                 //读LCD
    LCD_DATA = 0xFF;            //数据写入数据口
    LCD_EN = 1;                 //使能开
    LCD_Delay_us(4);            //微秒延时
    return(LCD_DATA);           //返回AC地址数据
}
/***************************************************************************************
** 函数名称: unsigned char LCD_Read_Data()
** 功能描述: 读取绘图RAM中指定坐标的数据
** 说    明: 参数输入坐标地址,读取后从坐标地址参数位返回数据,所以,地址参数在输入前须使用
** 零时变量,否则地址会被冲掉
****************************************************************************************/
void LCD_Read_dat_I(unsigned char *xp,unsigned char *yp)
{
LCD_Write_Command(*yp);     //写竖坐标(0x80-0x9f)
LCD_Write_Command(*xp);     //写横坐标(AC地址) 上半屏(0x80-0x87) 下半屏(0x88-0x90)
LCD_Read_Data();            //试读
*xp=LCD_Read_Data();        //读高字节并返回给xp
*yp=LCD_Read_Data();        //读低字节并返回给yp
}
/***************************************************************************************
** 函数名称: void LCD12864_WH_String(unsigned char x,unsigned char y,unsigned char *s)
** 功能描述: 写入字符串到第x(1,2,3,4)行y(1,16)列
** 输   入: unsigned char x,unsigned char y,unsigned char *s
** 输   出: 无
** 全局变量: 无
** 调用模块:  LCD_BUSY_Bit();LCD_Read_DATA();LCD_Write_Command();LCD_Write_DATA();
**设定起始行列数和字符数组,将在12864中顺序显示,在遇到汉字时如果是在地址低位,将在地址低位插入
**一个空格
****************************************************************************************/
void LCD12864_WH_String(unsigned char x,unsigned char y,unsigned char *s)
{
    unsigned char Tempi=0;          //循环行计次变量
    unsigned char TempAC=0;         //返回的DDRAM地址变量
    unsigned char TempData=0;       //返回的DDRAM高字节数据
    bit test0=1;                    //判断是否在第一行
    bit test1=0;                    //标准ASCII码数量的奇偶标记
    --y;                            //输入y下标为1,统一运算y最低为0
    for(Tempi=x;Tempi<5;Tempi++)
    {                               //行扫描循环
        switch(Tempi)
        {                           //强制指定正确的行地址起点
            case 1:x=0x80;break;    //第一行光标位置
            case 2:x=0x90;break;    //第二行光标位置
            case 3:x=0x88;break;    //第三行光标位置
            case 4:x=0x98;break;    //第四行光标位置
            default: break;
        }
        if(test0)
        {                                     //如果这是第一行               
            LCD_Write_Command(x+(y>>1));      //写入坐标位置
            if(y%2)
            {                                 //如果y起点在AC地址低位
                TempAC=LCD_BUSY_Bit();        //取当前AC地址
                LCD_Write_Command(TempAC);    //重置当前AC地址
                LCD_Read_Data();              //读AC地址高位数据
                TempData= LCD_Read_Data();    //读AC地址高位数据
                LCD_Write_Command(TempAC);    //再次重置当前AC地址
                LCD_Write_DATA(TempData);     //重写地址高位数据(只有重写地址原来高位数据,才能在此地址顺利写入低位数据)
                if(*s>127)
                {                             //如果首字是汉字且起点占据了奇数位
                    test1=1;                  //告诉下面的程序在首字插入一个空格
                }
                else
                {                             //如果首字是标准ASCII码(这行可以不写)
                    test1=0;
                }
            }
            test0=0;                          //首行定位完成,告诉下轮循环从新的地址开始,4轮循环下3次循环都不需要再计算首行起点
        }
        else
        {                                     //这是4轮循环中的后3轮循环
            y=0;                              //列地址始终从0开始
            LCD_Write_Command(x);             //写入新行首列AC地址
        }
        for(y;y<16;y++)
        {                                     //列循环扫描
            if(*s)
            {                                 //如果字符数组没有到最后一位空数据
                if(*s<128)
                {                             //如果当前字符数组数据是标准ASCII码
                    test1=~test1;             //奇偶翻转
                    LCD_Write_DATA(*s++);     //向LCD写入当前字符后,指针自加1
                }
                else
                {                             //如果当前字符数组数据是扩展ASCII码
                    if(test1)
                    {                         //如果已经写入了奇数个标准ASCII码
                        LCD_Write_DATA(' ');  //插入一个空格,凑齐偶数个标准ASCII码
                        test1=0;              //清空奇偶判断位成偶数标记
                     }
                    else
                    {                         //如果先前已经凑齐偶数个标准ASCII码
                        LCD_Write_DATA(*s++); //写入扩展ASCII码
                    }
                }
            }
        }
    }
}
/***************************************************************************************
** 函数名称: void cls_lcd(unsigned char dat)
** 功能描述: 绘图模式初始化并按输入数据填写绘图RAM
** 输   入: unsigned char dat
** 调用模块: LCD_Write_Command();LCD_Write_DATA();
****************************************************************************************/
void cls_lcd(unsigned char dat)
{
    unsigned char i,j,k;
    LCD_Write_Command(0x34);
    LCD_Write_Command(0x36);
    for(i=0;i<2;i++)
    {                                      //上下屏选择
        for(j=0;j<32;j++)
        {                                  //竖向扫描
            LCD_Write_Command(0x80+j);     //写竖向地址
            if(i==0)
            {                              //如果在上半屏
                LCD_Write_Command(0x80);   //写横向首地址
            }
            else                           //如果在下半屏
            {
                LCD_Write_Command(0x88);   //写横向首地址
            }
            for(k=0;k<16;k++)              //横向AC自加
            {
                LCD_Write_DATA(dat);       //填数据
            }
        }
    }
}
/***************************************************************************************
** 函数名称: void LCD_DrawingPoint(unsigned char xp,unsigned char yp,bit dat)
** 功能描述: 指定坐标点画点
** 输   入: unsigned char xp,unsigned char yp,bit dat  X,Y坐,dat 写1或0擦除
** 调用模块: LCD_Write_Command();LCD_Write_DATA();LCD_Read_dat_I(&rx,&ry);
****************************************************************************************/
void LCD_DrawingPoint(unsigned char xp,unsigned char yp,bit dat)
{
    unsigned char xd,rx,ry;
    xd=xp/0x10;                                   //计算横坐标AC步进
    xp%=0x10;                                     //计算AC地址位偏移
xp++;
    if(yp>31)
    {                                             //如果yp大于31选下半屏
        yp-=32;                                   //计算yp在下半屏的竖向坐标
        yp+=0x80;                                 //地址命名
        xd+=0x88;                                 //下半屏起点地址是0x88,地址命名
    }
    else
    {                                             //选上半屏
        yp+=0x80;                                 //地址命名
        xd+=0x80;                                 //上半屏起点地址是0x80,地址命名
    }
    rx=xd;ry=yp;                                  //取AC数据函数需要两个参数返回数据,且参数公用地址,所以使用零时变量
    LCD_Read_dat_I(&rx,&ry);                      //取当前字节数据
    LCD_Write_Command(yp);                        //重指定当前y地址
    LCD_Write_Command(xd);                        //重指定当前x地址
    if(dat)
    {                                             //如果是画点
        if(xp<=8)
        {                                         //如果当前画点坐标在AC地址数据对应的高字节(取余计算结果与字节移位方向相反)
            LCD_Write_DATA(rx|(0x01<<(8-xp)));//读取的高位数据与翻转的指定位进行与操作后写入高位
            LCD_Write_DATA(ry);                    //读取的低位数据原样写回
  }
  else
        {                                         //如果当前画点坐标在AC地址数据对应的低字节(取余计算结果与字节移位方向相反)
            LCD_Write_DATA(rx);                   //读取的高位数据原样写回
            LCD_Write_DATA(ry|(0x01<<(16-xp)));   //读取的低位数据与指定位进行或操作后写入低位
        }
    }
    else
    {                                              //如果是擦除图像
        if(xp<=8)
        {                                          //如果当前画点坐标在AC地址数据对应的高字节(取余计算结果与字节移位方向相反)
            LCD_Write_DATA(rx&~(0x01<<(8-xp)));//读取的高位数据与翻转的指定位进行与操作后写入高位
            LCD_Write_DATA(ry);                    //读取的低位数据原样写回
        }
        else
        {                                          //如果当前画点坐标在AC地址数据对应的低字节(取余计算结果与字节移位方向相反)
            LCD_Write_DATA(rx);                    //读取的高位数据原样写回
            LCD_Write_DATA(ry&~(0x01<<(16-xp)));   //读取的低位数据与翻转的指定位进行与操作后写入低位
        }
    }
}


回复

使用道具 举报

ID:220385 发表于 2017-7-17 20:25 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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