davecater 发表于 2012-5-31 18:19:34

LCD1602程序问题请教傻孩子

以前都CodeVision自带的LCD库,下午花两个小时自己写了一个LCD1602的程序,遇到些问题想请教你。
程序如下:
#include<mega64.h>
#include<delay.h>

//////////////////////LCD1602硬件接口//////////////////////////////
#define SET_BIT(port,a)port |= 1<<a            //置I/O口PORT A位为1
#define CLI_BIT(port,b)port &= (~(1<<b))    //清I/O口PORT B位

#define LCD_RS0
#define SET_LCD_RS()SET_BIT(PORTA,LCD_RS)
#define CLI_LCD_RS()CLI_BIT(PORTA,LCD_RS)
#define LCD_RW1
#define SET_LCD_RW()   SET_BIT(PORTA,LCD_RW)
#define CLI_LCD_RW()   CLI_BIT(PORTA,LCD_RW)
#define LCD_EN   2
#define SET_LCD_EN()   SET_BIT(PORTA,LCD_EN)
#define CLI_LCD_EN()   CLI_BIT(PORTA,LCD_EN)   

#define LCD_DATA_PORTPORTA   //the next three port should be the same
#define LCD_DATA_DDR   DDRA    //must use the high 4bit
#define LCD_DATA_PIN   PINA
#define LCD_DATA       0xf0    //DATA PORT
/*
#define LCD_RS         PORTA.0 //RS lcd
#define LCD_WR         PORTA.1//WR lcd
#define LCD_EN         PORTA.2 //EN lcd */




/////////////////LCD1602指令集定义////////////////////////////////
#define LCD_CLEAR                                        0x01        ///< Clear display
#define LCD_HOME                                        0x02        ///< Display and cursor home

#define LCD_ENTRY_CURSOR_INC                0x06        ///< Cursor move direction increment
#define LCD_ENTRY_CURSOR_DEC                0x04        ///< Cursor move direction decrement
#define LCD_ENTRY_DISP_SHIFT_ON                0x05        ///< Display shift on
#define LCD_ENTRY_DISP_SHIFT_OFF        0x04        ///< Display shift off

#define LCD_DISP_DISP_ON                        0x0C        ///< Display on
#define LCD_DISP_DISP_OFF                        0x08        ///< Display off
#define LCD_DISP_CURSOR_ON                        0x0A        ///< Cursor on
#define LCD_DISP_CURSOR_OFF                        0x08        ///< Cursor off
#define LCD_DISP_BLINK_ON                        0x09        ///< Blinking on
#define LCD_DISP_BLINK_OFF                        0x08        ///< Blinking off

#define LCD_SHIFT_DISP_LEFT                        0x18        ///< Shift display left
#define LCD_SHIFT_DISP_RIGHT                0x1C        ///< Shift display right
#define LCD_SHIFT_CURSOR_LEFT                0x10        ///< Shift cursor left
#define LCD_SHIFT_CURSOR_RIGHT                0x14        ///< Shift cursor right

#define LCD_MODE_BIT_8                                0x38        ///< 8-bit interface data 2-line display
#define LCD_MODE_BIT_4                                0x28        ///< 4-bit interface data2-line display

void LCD_en_write(void)//enable LCD
{
SET_LCD_EN();//EN=1
delay_us(10);
CLI_LCD_EN();//EN=0
}

void LCD_WriteCommand(unsigned char data) //write data
{
delay_us(50);                                              //标注3
CLI_LCD_RS();//RS=0,write command
LCD_DATA_PORT&=0X0f;       //clr high 4bit
LCD_DATA_PORT|=data&0xf0;//wirte high 4bit
LCD_en_write();
data=data<<4;               //turn the low 4bit to high 4bit
LCD_DATA_PORT&=0X0f;      //clr high 4bit
LCD_DATA_PORT|=data&0xf0;   //write low 4bit
LCD_en_write();
}
void LCD_WriteData(unsigned char data) //write data
{
delay_us(50);                                          //标注4
   SET_LCD_RS();//RS=1,write data
LCD_DATA_PORT&=0X0f;       //clr high 4bit
LCD_DATA_PORT|=data&0xf0;//wirte high 4bit
LCD_en_write();
data=data<<4;               //turn the low 4bit to high 4bit
LCD_DATA_PORT&=0X0f;      //clr high 4bit
LCD_DATA_PORT|=data&0xf0;   //write low 4bit
LCD_en_write();
}
void LCD_init(void)       //lcd init
{
LCD_DATA_DDR=0xff;
LCD_DATA_PORT = 0;//PORTA 方向为输出
CLI_LCD_RW();         //LCD只写
//delay_ms(10);
// LCD_WriteCommand(LCD_MODE_BIT_4);//4bit show                  
// delay_ms(15);
LCD_WriteCommand(LCD_MODE_BIT_4);//4bit show   
delay_ms(1);
LCD_WriteCommand(LCD_DISP_DISP_ON);//do now show cursor
LCD_WriteCommand(0x80);
delay_ms(1);
LCD_WriteCommand(LCD_CLEAR);//clr
delay_ms(2);
LCD_WriteCommand(LCD_ENTRY_CURSOR_INC);
}
//orientation a dress
//x:0 or 1
//y:0-15
void LCD_set_xy( unsigned char x, unsigned char y )//write address funcation
{
    unsigned char address;
    if (y==0) address=0x80+x;
    else address=0xc0+x;
    LCD_WriteCommand(address);
}
void LCD_write_string(unsigned char X,unsigned char Y,unsigned char flash *s)
{
    LCD_set_xy(X,Y); //write address
    while (*s)// write the char to show
    {
      LCD_WriteData(*s);
      s++;
    }
      
}

void LCD_clear()
{
    LCD_WriteCommand(0x01);
// delay_us(50);
}
void main(void)
{
// Declare your local variables here
//init();
LCD_init();   /////////////////////
//write_flash_string(1,2,"Resetting....","LaserShow");   
////////////////////////上电后从EEPROM中读出地址、工作模式、速度等级、X/Y停转状态及位置参数///////////////////                     
/*dmx_address = address_eep;
master_slave = master_slave_eep;
x_speed_rate = x_speed_rate_eep;   
y_speed_rate = y_speed_rate_eep;
x_run_state = x_run_state_eep;
y_run_state = y_run_state_eep;
color = color_eep;
show_mode=show_mode_eep;
x_position_data = x_position_data_eep;
y_position_data = y_position_data_eep;   

dmx_slave = dmx_slave_eep;
add = dmx_address/100 + '0';
add = (dmx_address/10)%10 + '0';
add = dmx_address%10 + '0';
if(master_slave == MASTER_MODE)
{
RXD_TXD_UART0 = 1;
master_work_mode = work_mode_eep;
}
else if(master_slave == SLAVE_MODE)
{
RXD_TXD_UART0 = 0;   
if(dmx_slave==SLAVE)
{
   uart0_slave_recv_flag=0;
   EIMSK &= ~(1<<INT0);
}
}

//TIMSK&=~(1<<TOIE1);   
//ETIMSK&=~(1<<TOIE3);
reset_function();                        // Global enable interrupts   
//x_count=0;
//y_count=0;
//x_current_back=0;
//y_current_back=0;
//TIMSK|=(1<<TOIE1);
//ETIMSK|=1<<TOIE3;*/
#asm("sei")
LCD_clear();
LCD_write_string(0,0,"this lcd test");
LCD_write_string(0,1,"test OK!");         //////标注1

delay_ms(2000);
LCD_clear();                                     ///标注2
LCD_write_string(0,1,"this lcd test");
LCD_write_string(0,0,"test OK!");
while (1)
{
/////////////////////Place your flash here//////////////////////////
   if(key_flag)                            //表示有键按下。
    {
   key_flag=0;
   LCD_clear();
      LCD_write_string(0,6,"write");
    //delay_ms(100);//标注5
      LCD_write_string(0,1,"Welcome to use");            
// get_menu();
    }
   
/*   get_maxspeed_position();
    x_motor_control();   
    y_motor_control();
    animal_play();   
    if(master_slave==MASTER_MODE)
       uart0_send_data();
    uart1_send_data();

};*/
//
}
问题描述:
程序运行至标注1,LCD1602显示正常,但延时2S,清屏后运行标注2时,LCD1602为空白,白屏不显示,这是什么原因所致?谢谢!

调试过程中,改变LCD初始化中延时时间长短,会发现运行标注1的时候就会出乱码现像或者白屏不显示,改变标注3、标注4的延时时间,现像与改变LCD初始化中延时时间长短一样。
在主程序WHILE{}中,任意按键按下时(按键程序没有帖出),如果不加标注5 的延时,现像同样是白屏不显示,而加入标注5的延时后,只是在第LCD1602第二行显示Welcome to use,第一行还是白屏不显示,而不是我想要显示的write。
请傻孩子及各位高手们分析下。

davecater 发表于 2012-6-1 18:00:49

自己顶!居然没人回??{:cry:}{:cry:}

Gorgon_Meducer 发表于 2012-6-1 23:10:18

本帖最后由 Gorgon_Meducer 于 2012-6-1 23:13 编辑

你在write command和write data里面应该在动作执行后加入一定的延时或者等待busy信号。你可以尝试在write command和wirte data里面各个操作的后面都加入延时,现保证一切正常,然后尝试一点一点减少延时以及延时的位置。

millwood0 发表于 2012-6-2 05:28:36

清屏后运行标注2时,LCD1602为空白

read the f@#$king datasheet, particularly the section on execution timing for the "clear display" command.

mowin 发表于 2012-6-2 08:21:37

米兄淡定
高手也是从菜鸟过来的
记得1602指令执行时间一般是几十us,而清屏是2mS左右!

davecater 发表于 2012-6-4 10:02:24

谢谢高手们帮我分析。
“write command和write data里面应该在动作执行后等待busy信号”,则需要在这两个程序中加入一个读数据D7的while循环,这样的话,如果LCD1602损坏或不接入显示屏,程序就会在这里出现死循环,不能满足屏损坏或不接显示屏的情况下,产品能继续工作。

“记得1602指令执行时间一般是几十us,而清屏是2mS左右”这个提醒,对我的启发很大。

现在问题已经解决了,再次谢谢大虾们!

fangxiaoyan 发表于 2014-2-17 09:09:07

davecater 发表于 2012-6-4 10:02
谢谢高手们帮我分析。
“write command和write data里面应该在动作执行后等待busy信号”,则需要在这两个程 ...

楼主,怎么解决的问题?是时序方面么?
页: [1]
查看完整版本: LCD1602程序问题请教傻孩子