求救: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);
}
}
像是0108的驱动芯片,个人推荐程序中定义一个缓冲空间,与液晶的显存对应,不要使用读函数(用了显示太慢),在缓冲区中画点画图等等,然后把修改过的位置(应是0-8页,0-63列)写到对应位置 是两片0108的驱动芯片,我就是想学习一下,使用读函数的用法,结果是啥数据也没读出来,不知啥原因,不知道是不是程序的问题。 dpjaihaozhe 发表于 2012-9-27 00:07 static/image/common/back.gif
是两片0108的驱动芯片,我就是想学习一下,使用读函数的用法,结果是啥数据也没读出来,不知啥原因,不知道 ...
如果学习一下读数据的话,我记得0108手册说像是要读两次 是的,需要读两次。我写的程序读了三次也没读出什么数据。
请问是什么原因呢?
是不是读函数有问题,请教。 这是我的读函数,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;
} 首先,谢谢你的帮助,我在试试。 你发的程序我已经试过了,很好用,已经可以正常读取液晶的显示数据了,真的非常感谢。 收藏了,谢谢
页:
[1]