液晶显示器初始化

时间:2010-05-10 17:34:42

标签: lcd atmega16

void lcdinit(void)
{
command1( 0x03 );
command1( 0x03 );
command1( 0x03 );
delay1(20);
command1( 0x02 );   //lcd home
delay1(10);
Command( 0x28 );
delay1(10); 
Command( 0x08 );     //display of cursor off
delay1(10);
Command( 0x0C );       //display on and cursor  off
delay1(10); 
Command( 0x06 );           //shift cursor right
delay1(10);
Command( 0x01 );        //clear display screen
delay1(10);

问:我已经将lcd与atmega32一起使用了。我已经评论了我所知道的命令。这是未注释命令的含义吗?

3 个答案:

答案 0 :(得分:0)

也许您应该查看LCD模块的数据表。它将显示它支持的命令集,或者至少为您提供有关命令集的位置的参考。

答案 1 :(得分:0)

这可能是HD44780兼容控制器(不幸的是我们不知道) 我认为0x28是功能集(4位接口,2行,5 * 7像素)

0x03命令是显示器初始化序列的一部分,然后是20 ms的休眠

答案 2 :(得分:0)

这是一些评论很好的4位LCD代码,包括初始化代码。它不是“AVR”C,但如果你将宏移植到它上面应该可以正常工作。

作为参考,“原始”HD44780 LCD控制器数据表可在此处获取:http://crystalfontz.com/controllers/Hitachi/HD44780

(来自https://forum.crystalfontz.com/showthread.php/6119的代码)

//============================================================================
typedef unsigned char ubyte;
typedef signed char sbyte;
typedef unsigned short word;
typedef unsigned long dword;
/============================================================================
//LCD Control line macros
#define SET_LCD_E \
  { \
  /* fill out with your port access code */ \
  }
#define CLEAR_LCD_E \
  { \
  /* fill out with your port access code */ \
  }
#define SET_LCD_RS \
  { \
  /* fill out with your port access code */ \
  }
#define CLEAR_LCD_RS \
  { \
  /* fill out with your port access code */ \
  }
#define SET_LCD_RW \
  { \
  /* fill out with your port access code */ \
  }
#define CLEAR_LCD_RW \
  { \
  /* fill out with your port access code */ \
  }

//Apply the high 4 bits of data to the low four bits of the port.
#define OUT_HIGH_NIBBLE (PRT1DR=(port1=(port1&0xF0)|(data>>4)))

//Apply the low 4 bits of data to the low four bits of the port.
#define OUT_LOW_NIBBLE (PRT1DR=(port1=(port1&0xF0)|(data&0x0F)))

//Read the high nibble of the data is on the low nibble of Port 1.
//Mask off the lower bits and store it.
#define IN_HIGH_NIBBLE (read_data=(PRT1DR&0x0F)<<4)

//Read the low nibble of the data is on the low nibble of Port 1.
#define IN_LOW_NIBBLE (read_data|=PRT1DR&0x0F)

#define SET_PORT1_FOR_LCD_WRITE \
  { \
  /* fill out with your port access code */ \
  }

#define SET_PORT1_FOR_LCD_READ \
  { \
  /* fill out with your port access code */ \
  }

#define PORT1_LCD_DATA_BUSY 0x08
//============================================================================
void Wait_For_Not_Busy(void)
  {
  uword
    timeout;
  //Poll the LCD's busy line until it is clear.
  //Make register select 0
  CLEAR_LCD_RS;
  //Make R/W 1=read.
  SET_LCD_RW;
  //Change the data bits to inputs.
  SET_PORT1_FOR_LCD_READ;
  //Enable the controller's data onto the bus.
  SET_LCD_E;
  //Test the port's bit, wait for the bit to go low
  if(PRT1DR&PORT1_LCD_DATA_BUSY)
    for(timeout=1000;(PRT1DR&PORT1_LCD_DATA_BUSY)&&timeout;timeout--);
  }
//============================================================================
ubyte Read_LCD_Address(void)
  {
  ubyte
    read_data;
  Wait_For_Not_Busy();
  //Now the high nibble of the address is on the low nibble of Port 2.
  //Mask off the busy bit and the upper bits and store it.
  IN_HIGH_NIBBLE;
  //Finish the high nibble clock cycle.
  CLEAR_LCD_E;
  //Strobe enable to clock in the low nibble--finishing the read.
  SET_LCD_E;
  //Now the low nibble of the address is on the low nibble of Port 2.
  //Mask the upper bits and add it to the result.
  IN_LOW_NIBBLE;
  CLEAR_LCD_E;
  //Turn the data bits back to their default output state.
  SET_PORT1_FOR_LCD_WRITE;
  return(read_data);  
  }
//============================================================================
void Write_LCD_Data(ubyte data)
  {
  Wait_For_Not_Busy();
  //Finish the high nibble clock cycle.
  CLEAR_LCD_E;
  //Strobe enable to clock in the low nibble--finishing the read.
  SET_LCD_E;
  CLEAR_LCD_E;
  //Turn the data bits back to their default output state.
  SET_PORT1_FOR_LCD_WRITE;
  //Make R/W 0=write.
  CLEAR_LCD_RW;
  //Make register select 1
  SET_LCD_RS;
  //Apply the high 4 bits of data to the low four bits of the port.
  OUT_HIGH_NIBBLE;
  //Strobe enable to clock in the high nibble.
  SET_LCD_E;
  CLEAR_LCD_E;
  //Apply the low 4 bits of data to the low four bits of the port.
  OUT_LOW_NIBBLE;
  //Strobe enable to clock in the low nibble.
  SET_LCD_E;
  CLEAR_LCD_E;  
  }
//============================================================================
void Write_LCD_Control(ubyte data)
  {
  Wait_For_Not_Busy();
  //Finish the high nibble clock cycle.
  CLEAR_LCD_E;
  //Strobe enable to clock in the low nibble--finishing the read.
  SET_LCD_E;
  CLEAR_LCD_E;
  //Turn the data bits back to their default output state.
  SET_PORT1_FOR_LCD_WRITE;
  //Make R/W 0=write.
  CLEAR_LCD_RW;
  //Apply the high 4 bits of data to the low four bits of the port.
  OUT_HIGH_NIBBLE;
  //Strobe enable to clock in the high nibble.
  SET_LCD_E;
  CLEAR_LCD_E;
  //Apply the low 4 bits of data to the low four bits of the port.
  OUT_LOW_NIBBLE;
  //Strobe enable to clock in the low nibble.
  SET_LCD_E;
  CLEAR_LCD_E;
  }
//============================================================================
void Read_LCD_Data(ubyte length,ubyte address,ubyte *destination)
  {
  uword
    timeout;
  ubyte
    read_data;
  //First we need to write the address to the LCD.
  //0x40 is first CGRAM
  //0x80 is first DDRAM
  Write_LCD_Control(address);
  while(length--)
    {
    Wait_For_Not_Busy();
    //Finish the high nibble clock cycle.
    CLEAR_LCD_E;
    //Strobe enable to clock in the low nibble--finishing the read.
    SET_LCD_E;
    CLEAR_LCD_E;
    //Make register select 1, selecting the data instead of the address.
    SET_LCD_RS;
    //Enable the controller's data onto the bus.
    SET_LCD_E;
    //Now the high nibble of the data is on the low nibble of Port 2.
    //Mask off the lower bits and store it.
    IN_HIGH_NIBBLE;
    //Finish the high nibble clock cycle.
    CLEAR_LCD_E;
    //Strobe enable to clock in the low nibble--finishing the read.
    SET_LCD_E;
    //Now the low nibble of the data is on the low nibble of Port 1.
    IN_LOW_NIBBLE;
    CLEAR_LCD_E;
    //Store the data
    *destination++=read_data;
    }
  //Turn the data bits back to their default output state.
  SET_PORT1_FOR_LCD_WRITE;
  }
//============================================================================
//does an "8-bit" write (as seen by the LCD)
void Blind_Write_LCD_Upper_Control_Nibble(ubyte data)
  {
  //Make R/W 0=write
  CLEAR_LCD_RW;
  //Make register select 0
  CLEAR_LCD_RS;
  //Apply the high 4 bits of data to the low four bits of the port.
  OUT_HIGH_NIBBLE;
  //Strobe enable to clock in the high nibble.
  SET_LCD_E;
  CLEAR_LCD_E;
  }
//============================================================================
void LCD_Position_Cursor(ubyte x, ubyte y)
  {
  //Valid x is 0-15, valid y is 0-1
  if((x<16)&&(y<2))
    Write_LCD_Control(0x80|(y<<6)|x);
  }
//============================================================================
//Could make this aware of display size & wrapping.
void LCD_puts(const char *input_string)
  {
  while(*input_string)
    Write_LCD_Data(*input_string++);
  }
//============================================================================
void LCD_put_dec_3(ubyte input)
  {
  ubyte
    digit;
  ubyte
    no_blank;
  digit=input/100;
  if(digit)
    {
    Write_LCD_Data(digit+'0');
    no_blank=1;
    }
  else
    {
    Write_LCD_Data(' ');
    no_blank=0;
    }
  input%=100;
  digit=input/10;
  if(digit|no_blank)
    Write_LCD_Data(digit+'0');
  else
    Write_LCD_Data(' ');
  Write_LCD_Data(input%10+'0');
  }
//============================================================================
void LCD_Initialize(void)
  {
  ubyte
    i;
  ubyte
    j;

  SET_PORT1_FOR_LCD_WRITE;

  //This sequence is from the initialization on page 46 of the HD44780U
  //data sheet.
  delay_mS(40);
  Blind_Write_LCD_Upper_Control_Nibble(0x30);
  //Yes, the data sheet says write it twice.
  delay_mS(5);
  Blind_Write_LCD_Upper_Control_Nibble(0x30);
  //Yes, the data sheet says write it three times.
  delay_mS(1);
  Blind_Write_LCD_Upper_Control_Nibble(0x30);
  //Yes, the data sheet says write it four times, but at least this one counts.
  //020h is Function set:
  //4 bit,
  //2 line
  //F = (5x8)
  delay_mS(1);
  //This is last 8-bit write, which is an instruction to put the LCD into 4-bit mode.
  Blind_Write_LCD_Upper_Control_Nibble(0x20);
  //Here is the 4-bit instruction to set the font and number of lines.
  Write_LCD_Control(0x28);

  //"Display off"
  Write_LCD_Control(0x08);
  //"Display clear"
  Write_LCD_Control(0x01);
  //This delay is needed for at least one version of the Sitronix
  //ST7066 Controller. No reasonable explanation, I found it
  //empirically.
  delay_mS(2);
  //006h is Entry mode set, increment, no shift
  Write_LCD_Control(0x06);
  //Display on, cursor on, blinking
  Write_LCD_Control(Cursor_Style=0x0F);
  //Clear the display again. This seems to fix a power-up problem
  //where the display shows "{{{{{" in a couple of places.
  Write_LCD_Control(0x01);
  //Why is this needed? Apparently not needed on the 635.
  //delay_mS(2);
  }
//============================================================================