dpjaihaozhe 发表于 2012-9-26 21:33:32

求救:AVR atmega16驱动M12864无字库液晶问题

我是用的单片机是ATmega16,驱动M12864无字库液晶,可以显示点,但是同一页同一列显示有问题,不能同时显示,感觉读液晶函数有问题,就是没有发现问题出在哪儿,求大侠帮忙看看,不胜感激。
程序如下:
#include <avr/io.h>
#include <util/delay.h>
//#include <avr/pgmspace.h>        //此连接为使用FLASH中的常量而设,
//#include "M12864.h"                        //如定义方式const prog_uchar tmpled[],读方式pgm_read_byte(tmpled+i)
#define RS_H                PORTB|=0X01                //p1.0=1 数据0000 0001
#define RS_L                PORTB&=0XFE                //p1.0=0 指令1111 1110
#define RW_H                PORTB|=0X02                //p1.1=1 读0000 0010
#define RW_L                PORTB&=0XFD                //p1.1=0 写1111 1101
#define EN_H                PORTB|=0X04                //p1.2=1 使能 0000 0100
#define EN_L                PORTB&=0XFB                //p1.2=01111 1011
#define CS1_H                PORTD|=0X40                //p3.6=00100 0000
#define CS1_L                PORTD&=0XBF                //p3.6=01011 1111
#define CS2_H                PORTD|=0X80                //p3.7=01000 0000
#define CS2_L                PORTD&=0X7F                //p3.7=00111 1111
//#define lcd_data        PORTC                        //输出数据的端口
//#define lcd_data_in        PINC                        //输入数据

#define Disp_on    0x3f           //开显示                                               
#define Disp_off   0x3e           //关显示
#define Col_add    0x40           //列起始地址
#define Page_add   0xb8           //页起始地址
#define Start_line 0xc0           //行起始地址

void write_com(unsigned char cmdcode);                //向LCD写命令
void write_data(unsigned char dispdata);        //向LCD写数据
char read_data(void);                                                //读LCD显示数据
void read_busy(void);                                                //读LCD忙函数
void clr_lcd();                                                                //清LCD
void disp_rgw(unsigned x,unsigned y,unsigned disy);//画点
void disp_frame();                                                        //画框架函数
//void disp_huadian(unsigned char x,unsigned char y);//画点函数
void init_lcd();                                                        //初始化LCD
//void disp_hz16(unsigned char pag,unsigned char col, unsigned char *hzk);          //行列显示汉字

void write_com(unsigned char cmdcode)                               //写指令
{
        RS_L;                  //di=0;
        RW_L;                  //rw=0;
        PORTC=cmdcode;
        EN_H;
        _delay_us(10);
        EN_L;                       
}

void write_data(unsigned char dispdata)                                  //写数据
{
        RS_H;                  //di=1;
        RW_L;                  //rw=0;
        PORTC=dispdata;
        EN_H;
        _delay_us(10);
        EN_L;               
}
char read_data(void)                                                                //读数据
{
    unsigned char dat=0;
        DDRC=0X00;
        PORTC=0X00;                        //带上拉电阻的输出
        _delay_us(10);
        read_busy();
        RS_H;                 
        RW_H;                 
        EN_H;
        dat=PINC;                       
        _delay_us(10);
        EN_L;
        DDRC=0XFF;
        return dat;
}       
void read_busy(void)                                                                //读状态
{
        unsigned char i=0;
        DDRC=0X00;
        PORTC=0X00;
        RS_H;                  //di=0;
        RW_H;                  //rw=0;
        EN_H;
        _delay_us(10);
        i=PINC;                        //读状态
        while(i&=0x80);
        EN_L;
        DDRC=0XFF;
}
void disp_rgw(unsigned x,unsigned y,unsigned disy)//读显示数据,修改,写回函数;相当于画点函数
{
        unsigned char temp=0 ,n;
        n=y;y/=8;n%=8;
       
        if(x<64)
          {
                CS1_H;CS2_L;       
          }
        else
          {
                x-=64;
                CS1_L;CS2_H;
          }

        write_com(Page_add+y);
        write_com(Col_add+x);
       
        temp=read_data();//空读
    temp=read_data();
    temp=read_data();
       
        switch(disy)
          {
                case 0: temp&=~_BV(n);break;//此点不显示
                case 1: temp|=_BV(n); break;//此点显示
                case 2: temp=~_BV(n);break;//此点反显
                default : break;
          }
        if(x<64)
          {
                CS1_H;CS2_L;       
      write_com(Page_add+y);
                write_com(Col_add+x);
                write_data(temp);
      //_delay_us(10);
          }
        else
          {
                x-=64;
                CS1_L;CS2_H;
                write_com(Page_add+y);
                write_com(Col_add+x);
                write_data(temp);
      //_delay_us(10);
          }
       
}


void clr_lcd()                                                                                  //清屏函数
{
        unsigned char j,k;
        CS1_H;CS2_H;                //cs1=1;cs2=1;
        write_com(Page_add+0);
        write_com(Col_add+0);
        for(k=0;k<8;k++)
          {
           write_com(Page_add+k);
           for(j=0;j<64;j++)
             write_data(0x00);
          }
}

/*void disp_huadian(unsigned char x,unsigned char y)        //画点函数
{
       
        unsigned char i=0x01,j=0,l=0;
        disp_frame();
        l=y;
        y=(y/8);
        if(x<64)
          {
                CS1_H;CS2_L;
                write_com(Page_add+y);
                write_com(Col_add+x);
               //read_data();
                //j=read_data();
                //j=read_data();
               
                l%=8;
                i<<=l;
                //i |=j;
                write_data(i);
          }
        else
          {
                x-=64;
                CS1_L;CS2_H;
                write_com(Page_add+y);
                write_com(Col_add+x);
               //read_data();
                //j=read_data();
                //j=read_data();
                l%=8;
                i<<=l;
                //i |=j;
                write_data(i);
               
          }       
}
*/
void init_lcd()                                                                                   //显示初始化
{
       
        DDRC=0XFF;
        DDRB|=0X07;
        DDRD|=0XC0;
       
        PORTC=0XFF;
        PORTB=0X07;
        PORTD=0XC0;
       
        CS1_H;CS2_H;
       
        write_com(Disp_off);
        write_com(Page_add);                //页起始地址
        write_com(Start_line);                //行起始地址
        write_com(Col_add);                        //列起始地址
        write_com(Disp_on);
}

void disp_frame()                                                                        //显示框架
{   
       
        unsigned char i;
        CS1_H;CS2_H;
       
        write_com(Page_add+0);                      //画横线
        write_com(Col_add+0);                               
        for(i=0;i<64;i++) write_data(0x01);
       
        write_com(Page_add+7);
        write_com(Col_add+0);
        for(i=0;i<64;i++) write_data(0x80);
       
        for(i=0;i<8;i++)
          {
                CS1_H;CS2_L;                                          //画竖线
                write_com(Page_add+i);
                write_com(Col_add+0);
                write_data(0xff);
               
                CS1_L;CS2_H;
                write_com(Page_add+i);
                write_com(Col_add+63);
                write_data(0xff);
          }
}



int main(void)                                                                               //主程序
{
        init_lcd();
        while(1)
          {       
                clr_lcd();
               
                disp_frame();
                _delay_ms(1000);
               
                disp_rgw(6,5,2);
                _delay_ms(1000);
               
               
               
                disp_rgw(6,6,2);
                _delay_ms(1000);
               
                disp_rgw(6,7,1);
                _delay_ms(1000);
               
               
               
                disp_rgw(12,12,1);
                _delay_ms(1000);
               
               
               
                disp_rgw(14,16,1);
                _delay_ms(1000);
               
                disp_rgw(16,18,1);
                _delay_ms(1000);
               
                disp_rgw(18,20,1);
                _delay_ms(1000);
               
                disp_rgw(20,22,1);
                _delay_ms(1000);
          }
}

worldly_guest 发表于 2012-9-26 23:36:13

像是0108的驱动芯片,个人推荐程序中定义一个缓冲空间,与液晶的显存对应,不要使用读函数(用了显示太慢),在缓冲区中画点画图等等,然后把修改过的位置(应是0-8页,0-63列)写到对应位置

dpjaihaozhe 发表于 2012-9-27 00:07:40

是两片0108的驱动芯片,我就是想学习一下,使用读函数的用法,结果是啥数据也没读出来,不知啥原因,不知道是不是程序的问题。

worldly_guest 发表于 2012-9-27 08:33:52

dpjaihaozhe 发表于 2012-9-27 00:07 static/image/common/back.gif
是两片0108的驱动芯片,我就是想学习一下,使用读函数的用法,结果是啥数据也没读出来,不知啥原因,不知道 ...

如果学习一下读数据的话,我记得0108手册说像是要读两次

dpjaihaozhe 发表于 2012-9-27 19:37:33

是的,需要读两次。我写的程序读了三次也没读出什么数据。
请问是什么原因呢?
是不是读函数有问题,请教。

worldly_guest 发表于 2012-9-27 20:25:08

这是我的读函数,ICC的,用的延时,测试的19264,12864都是可以的,液晶厂家不一样延时长不一样,需要你自己测试调整,你看看有没有用

unsigned char lcd_read_data(unsigned char x, unsigned char page)          /*读显示数据 */
{
        unsigned char data;
       
        lcd_set_x(x);
        lcd_set_page(page);
       
        CLEAR_LCD_E;
       
Delayus(2);       
       
        SET_LCD_DATA;
        SET_LCD_READ;

       
    LCD_DIR_PORT = 0x00;
    LCD_OP_PORT = 0xff;

       
        SET_LCD_E;
       
Delayus(2);
       
   data=LCD_IP_PORT;

Delayus(2);

    CLEAR_LCD_E;

Delayus(2);       
       
    SET_LCD_WRITE;
       
//第二次读

        SET_LCD_DATA;
    SET_LCD_READ;
       
    LCD_DIR_PORT = 0x00;
    LCD_OP_PORT = 0xff;
       
Delayus(2);

        SET_LCD_E;
       
Delayus(2);

   data=LCD_IP_PORT;
   
Delayus(2);

    CLEAR_LCD_E;
       
Delayus(2);
       
    SET_LCD_WRITE;


        return data;
       
}

dpjaihaozhe 发表于 2012-9-27 23:14:01

首先,谢谢你的帮助,我在试试。

dpjaihaozhe 发表于 2012-9-27 23:35:28

你发的程序我已经试过了,很好用,已经可以正常读取液晶的显示数据了,真的非常感谢。

beggard 发表于 2013-12-9 21:43:46

收藏了,谢谢
页: [1]
查看完整版本: 求救:AVR atmega16驱动M12864无字库液晶问题