专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

ST7586S的AVR单片机驱动程序

作者:huqin   来源:本站原创   点击数:  更新时间:2014年11月22日   【字体:

AVR 单片机 MEGA64A
/***************************ST7586S********************************************/

/************************PE5  --->  /CS ***************************************/
/************************PG3  --->  RS  ***************************************/
/************************PG4  --->  /WR ***************************************/
/************************PA0  --->  /RD ***************************************/
/********************PF0-PF7  --->  DATA DB0-DB7 ******************************/
/************************PA1  --->  /RESET ************************************/
/************************PA2  --->  LED+(H)************************************/   
#define LCD_COMMAND  0
//数据
#define LCD_DATA   1
 
#define DATA_IO_INIT() {DDRF=0xFF;PORTF=0x00;}
 
#define LCD_RST_ON() {DDRA|=BIT(1);PORTA&=~BIT(1);}
#define LCD_RST_OFF() {DDRA|=BIT(1);PORTA|=BIT(1);}
 
#define LCD_RS_LOW_COMMAND() {DDRG|=BIT(3);PORTG&=~BIT(3);}
#define LCD_RS_HIGH_DATA() {DDRG|=BIT(3);PORTG|=BIT(3);}
 
#define LCD_RD_LOW() {DDRA|=BIT(0);PORTA&=~BIT(0);}
#define LCD_RD_HIGH() {DDRA|=BIT(0);PORTA|=BIT(0);}
 
#define LCD_WR_LOW() {DDRG|=BIT(4);PORTG&=~BIT(4);}
#define LCD_WR_HIGH() {DDRG|=BIT(4);PORTG|=BIT(4);}
 
#define LCD_CS_LOW_ON() {DDRE|=BIT(5);PORTE&=~BIT(5);}
#define LCD_CS_HIGH_OFF() {DDRE|=BIT(5);PORTE|=BIT(5);}
 
#define LCD_LED_OFF() {DDRA|=BIT(2);PORTA|=BIT(2);}
#define LCD_LED_ON() {DDRA|=BIT(2);PORTA&=~BIT(2);}
 
//ST7586 COMMAND
#define LCD_NOP 0x00
#define LCD_RST 0x01 //软件复位,RAM内容不清
#define POWER_SAVE_ON 0x10 //0X10,SLEEP,0X11,WAKE UP
#define POWER_SAVE_OFF 0x11
#define PARTIAL_DISPLAY_ON 0x12 //0x12,ON,0x13,OFF
#define PARTIAL_DISPLAY_OFF 0x13
#define INVERSE_DISPLAY_OFF 0x20 //0x20,正显,0X21,负显
#define INVERSE_DISPLAY_ON 0x21
#define ALL_PIXEL_ON 0x23 //0x22,off,0X23,on
#define ALL_PIXEL_OFF 0x22
#define DISPLAY_ON 0x29
#define DISPLAY_OFF 0X28
#define SET_COLUMN_ADDRESS 0x2A //0x2A+XS0000H+XE007FH 0<=XS<=XE<=7F
#define SET_ROW_ADDRESS 0x2B //0x2B+YS+YE 0<=YS<=YE<=9F
#define WRITE_DISPLAY_DATA 0x2C
//#define READ_DISPLAY_DATA 0x2E //串口模式无此功能
#define PARTIAL_DISPLAY_AREA 0x30 //个参数
#define SCROLL_AREA 0x33 // TA,SA,BA:0-A0
#define DISPLAY_CONTROL 0x36 //MY,MX1,MX0
#define START_LINE 0x37 //0-9F
#define DISPLAY_MODE 0x38 //四级灰度,39,单色显示
#define ENABLE_DDRAM_INTERFACE 0x3A //3AH+02H
#define DISPLAY_DUTY 0xB0 //B0+9F
#define FIRST_OUTPUT_COM 0xB1 //B1H+00H
#define FOSC_DIVIDER 0xB3 //B3H+1;0:不分频,1:2分频,2:4分频,3:8分频
#define PARTIAL_DISPLAY 0xB4 //B4+A0,在局部显示区域设置之前写入
#define SET_VOP 0xC0 //+42H+01H
#define VOP_INCREASE 0xC1
#define VOP_DECREASE 0xC2
#define BIAS_SYSYTEM 0xC3  //C3+04;1/10
#define BOOSTER_LEVEL 0xC4 //C4+07
#define VOP_OFFSET 0xC7 //C7+1
#define ANALOG_CONTROL 0xD0 //D0+1D
#define FRAME_RATE 0xF0 //F0+06+0B+0D+12H
/****************************取模方式******************************************/
/******点阵格式--阴码,列行式,取模走向为逆向**********************************/
//举一个例子,显示0,像素16*24,显示的有效数据的位数一定是要3的倍数
//16*24,宽度是2个字节16位,但是传输给LCD显示时,一定要补2位,是16+2=18
/*************************************16*24*************************************/
const unsigned char Image_0[]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x0E,0xE0,0x1C,0x70,
0x1C,0x70,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,
0x38,0x38,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00};/*0*/  

/*******************************LCD写命令**********************************/
void LCD_Cmd_Write(unsigned char cmd)
   {
       LCD_RS_LOW_COMMAND();
  LCD_RD_HIGH();
       /*LCD_ChkBusy();*/         //Call LCD_ChkBusy to Check Busy Bit
  LCD_WR_LOW();
  NOP();
  NOP();
  DDRF = 0xFF;
  PORTF = cmd;
       LCD_CS_LOW_ON();
  NOP();
  NOP();
       LCD_WR_HIGH();
      Some_NOP(3);
  LCD_CS_HIGH_OFF();
   }

/*****************************LCD写数据**********************************/
void LCD_Data_Write(unsigned char data)
   {
      /*LCD_ChkBusy(); */      //Call LCD_ChkBusy to Check Busy Bit
      DDRF = 0xFF;
 LCD_RS_HIGH_DATA();
 LCD_RD_HIGH();
      PORTF = data;
 LCD_WR_LOW();
 NOP();
 NOP();
 LCD_CS_LOW_ON();     
      NOP()
 NOP();
      LCD_WR_HIGH();
      Some_NOP(3);
      LCD_CS_HIGH_OFF();
   }  
/***********************LCD读数据*******************************/
unsigned char LCD_Data_Read(void)
   {
       unsigned char data_m=0;
       DDRF = 0x00;  //读出
       LCD_RS_HIGH_DATA();
       LCD_RD_HIGH(); 
  LCD_WR_LOW();
  NOP();
  NOP();                    
       LCD_CS_LOW_ON();
  NOP();
  NOP();
       LCD_WR_HIGH();
       NOP();
       NOP();
      LCD_RD_LOW();
      NOP();
      NOP();
      data_m = PINF;
      LCD_RD_HIGH();
    NOP();
      NOP();
      return data_m;
   }
/*********0<XS<XE<7F,0<YS<YE<9F************/
//LCD_Clear_RAM(0,127,0,159);//x-y
void LCD_Clear_RAM(uchar xs,uchar xe,uchar ys,uchar ye)
   {
       uchar x,y;
  LCD_Cmd_Write(SET_COLUMN_ADDRESS);
  LCD_Data_Write(0x00);
  LCD_Data_Write(xs);
  LCD_Data_Write(0x00);
  LCD_Data_Write(xe);
  
  LCD_Cmd_Write(SET_ROW_ADDRESS);
  LCD_Data_Write(0x00);
  LCD_Data_Write(ys);
  LCD_Data_Write(0x00);
  LCD_Data_Write(ye);
  
  LCD_Cmd_Write(WRITE_DISPLAY_DATA);
  for(y=ys;y<=ye;y++)
   {
   for(x=xs;x<=xe;x++)
{
    LCD_Data_Write(0x00);
}
}   
   }  
//========================================================
// 画图函数
//========================================================
void Image_Disp(uchar x,uchar y,uchar width,uchar high,const uchar *pstr)
// 坐标(x,y),x为水平方向字符位(1个字符位占3个像素点);y为垂直方向像素行;
// width:图片宽度,按照水平方向像素点计算;high:为图片高度,按照像素点计算,*pstr 图片数组名
   {
  uchar i,j,k,data,temp;
  LCD_Cmd_Write(0x2a); // Column Address Setting
  LCD_Data_Write(0x00); // 
  LCD_Data_Write(x); // 
  LCD_Data_Write(0x00);
  LCD_Data_Write((width/3)+x-1); //
  LCD_Cmd_Write(0x2b); // Row Address Setting
  LCD_Data_Write(0x00); // 
  LCD_Data_Write(y);
  LCD_Data_Write(0x00);
  LCD_Data_Write(y+high-1);
  LCD_Cmd_Write(0x2c);
  for(i=0;i<high;i++)
   {
       for(j=0;j<width;j=j+24)
        {
            data = *pstr++;
for(k=0;k<2;k++)
   {
       temp = data&0xe0;
   LCD_Data_Write(LCD_Change_Tab[temp>>5]);
             data = data<<3;
           }
    data = data + ((*pstr)>>2); 
        for(k=0;k<2;k++)
         {
             temp = data&0xe0;
   LCD_Data_Write(LCD_Change_Tab[temp>>5]);
             data = data<<3;
           }
  data = data + (((*pstr++)&0x03)<<4);  
         data = data +((*pstr)>>4);
 for(k=0;k<2;k++)
      {
            temp = data&0xe0;
      LCD_Data_Write(LCD_Change_Tab[temp>>5]);
                data = data<<3;
                }
                             data = data +(((*pstr++)&0x0f)<<2);
             for(k=0;k<2;k++)
              {
                  temp = data&0xe0;
                  LCD_Data_Write(LCD_Change_Tab[temp>>5]);
                                  data = data<<3;
                }
                    }
   }
    }    

void Image18_Disp(uchar x,uchar y,uchar width,uchar high,const uchar *pstr)
// 坐标(x,y),x为水平方向字符位(1个字符位占3个像素点);y为垂直方向像素行;
// width:图片宽度,按照水平方向像素点计算;high:为图片高度,按照像素点计算,*pstr 图片数组名
   {
  uchar i,j,k,data,temp;
  LCD_Cmd_Write(0x2a); // Column Address Setting
  LCD_Data_Write(0x00); // 
  LCD_Data_Write(x); // 
  LCD_Data_Write(0x00);
  LCD_Data_Write((width/3)+x-1); //
  LCD_Cmd_Write(0x2b); // Row Address Setting
  LCD_Data_Write(0x00); // 
  LCD_Data_Write(y);
  LCD_Data_Write(0x00);
  LCD_Data_Write(y+high-1);
  LCD_Cmd_Write(0x2c);
  for(i=0;i<high;i++)
   {
            data = *pstr++;
for(k=0;k<2;k++)
   {
       temp = data&0xe0;
   LCD_Data_Write(LCD_Change_Tab[temp>>5]);
             data = data<<3;
           }
 
    data = data + ((*pstr)>>2); 
        for(k=0;k<2;k++)
         {
             temp = data&0xe0;
   LCD_Data_Write(LCD_Change_Tab[temp>>5]);
             data = data<<3;
           }
 
data = data + (((*pstr++)&0x03)<<4);//指针
        for(k=0;k<2;k++)
         {
             temp = data&0xe0;
   LCD_Data_Write(LCD_Change_Tab[temp>>5]);
             data = data<<3;
           } 
     }
    }   
void Image8_Disp(uchar x,uchar y,uchar width,uchar high,const uchar *pstr)
// 坐标(x,y),x为水平方向字符位(1个字符位占3个像素点);y为垂直方向像素行;
// width:图片宽度,按照水平方向像素点计算;high:为图片高度,按照像素点计算,*pstr 图片数组名
   {
  uchar i,j,k,data,temp;
  LCD_Cmd_Write(0x2a); // Column Address Setting
  LCD_Data_Write(0x00); // 
  LCD_Data_Write(x); // 
  LCD_Data_Write(0x00);
  LCD_Data_Write((width/3)+x-1); //
  LCD_Cmd_Write(0x2b); // Row Address Setting
  LCD_Data_Write(0x00); // 
  LCD_Data_Write(y);
  LCD_Data_Write(0x00);
  LCD_Data_Write(y+high-1);
  LCD_Cmd_Write(0x2c);
  for(i=0;i<high;i++)
   {
            data = *pstr++;
for(k=0;k<3;k++)
   {
       temp = data&0xe0;
   LCD_Data_Write(LCD_Change_Tab[temp>>5]);
             data = data<<3;
           }
     }
    }

/**********************LCD复位程序********************/
void LCD_Reset(void )
{
LCD_RST_OFF();
Delay_us(20);
LCD_RST_ON();
Delay_us(50);
LCD_RST_OFF();
Delay_us(20);


/*************************LCD初始化***********************/
void LCD_Init(void)
{
LCD_Reset();
Delay_ms(10);
LCD_Cmd_Write(POWER_SAVE_OFF);//wake up
Delay_ms(10);
LCD_Cmd_Write(0xd7); // Disable Auto Read
LCD_Data_Write(0x9F);
LCD_Cmd_Write(0xe0);// Enable OTP Read
LCD_Data_Write(0x00);
Delay_ms(10);
LCD_Cmd_Write(0xe3); // OTP Up-Load
Delay_ms(20);
LCD_Cmd_Write(0xe1); // OTP Control Out
// initail set
LCD_Cmd_Write(0x11); // Sleep Out
LCD_Cmd_Write(0x28); // Display OFF Delay_ms(50);
LCD_Cmd_Write(0xc0); // Vop = B9h
LCD_Data_Write(0x1f); // contrast value
LCD_Data_Write(0x01); // 01
LCD_Cmd_Write(0xc3); // BIAS
LCD_Data_Write(0x02); // 05 = 1/12
LCD_Cmd_Write(0xc4); // Booster = x8
LCD_Data_Write(0x07);
LCD_Cmd_Write(0xd0); // Enable Analog Circuit
LCD_Data_Write(0x1d);
LCD_Cmd_Write(0xb5); // N-Line = 13
LCD_Data_Write(0x8d); //8d
LCD_Cmd_Write(0x38); // 4 Gray
// SdCmd(0x39); // B/W Mode
LCD_Cmd_Write(0x3a); // Enable DDRAM Interface
LCD_Data_Write(0x02);
LCD_Cmd_Write(0x36); // Dispaly Control
LCD_Data_Write(0xc8); // MY=1,MX[1:0]=11;
LCD_Cmd_Write(0xb0); // Duty Setting
LCD_Data_Write(0x9f); // 160 line 9f
LCD_Cmd_Write(0x20); // Display Inversion OFF
LCD_Cmd_Write(0xb1); // First COM out
LCD_Data_Write(0x00); // com0
LCD_Clear_RAM(0,127,0,159);
LCD_Cmd_Write(0x29); // Display ON
}

 
实际调试时一开始使用的是电源发生器的,5V标准的电压,当时没发现阴影,LCD是3.3V的,实际线路板上电压大概是5.06V,结果背景就开始有阴影了,后来重新外加弄了块5V转3.3V的转接线路板。

其中DIR的电平可以单独再用一个I/O口去控制,不过一般实际使用时基本上都是WRITE LCD的,READ LCD RAM很少,如无READ指令的话,DIR可以直接接高电平。
 
关闭窗口

相关文章