/*------------------------------------------------------------------------------------- date:20070911 author: wkj ver 1.0 sed1520 12232 lcd driver input:XXXXXX output:return 0 ---------------------------------------------------------------------------------------*/ #include <sys/types.h> #include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #include <time.h> #include <sys/time.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/file.h> #include "gpio.h" #include "main.h" #include "io.h" #include <stdarg.h> #include <memory.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <fcntl.h> #include <signal.h> #include "font5x7.h" #define DEVICE_FILE_NAME "scan_keyb" void *map_base; //phy 0xffff f000 virtual address #define uchar unsigned char #define uint unsigned int #define Byte unsigned char #define Word unsigned int #define FIRSTPAGE 2 //当前像素位置 和当前显示页 static unsigned char PixX,page; #define DEBUGMSG(x, y, args...) printf(y, ##args)
#define LCD_CMD *((unsigned long*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = 0x1<<28; //PC28 as 0; A0=0 #define LCD_DATA *((unsigned long*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0x1<<28; //PC28 as 1; A0=1 #define LCD_WRITE *((unsigned long*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = 0x1<<30;//PC30 as 0 ; RW=0 #define LCD_READ *((unsigned long*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0x1<<30;//PC30 as 1 ; RW=1
#define Clear_LCD_E1 *((unsigned long*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = 0x1<<13;//PC13 as 0; E1=0 #define SET_LCD_E1 *((unsigned long*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0x1<<13;//PC13 as 1; E1=1
#define Clear_LCD_E2 *((unsigned long*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = 0x1<<10;//PC10 as 0; E2=0 #define SET_LCD_E2 *((unsigned long*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0x1<<10;//PC10 as 1; E2=1
/*---------------------------------------------------------------------------- 调用方式:void OutMI(uchar i) 函数说明:发指令i到主窗口。(内函数,私有,用户不直接调用) ------------------------------------------------------------------------------*/ void OutMI(uchar i) { volatile unsigned int LCD_STAT; // A0=0; LCD_CMD ; // RW=1; LCD_READ; do //if lcd is always busy ,should no return,so should add couter for exit of timeout { //DATA=0xFF; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0xFF<<16; //all data to 1 //E1=1; SET_LCD_E1; //LCD_STAT=LCD_BUSY; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_ODR )))) = 0xFF<<16;//as input //0 bit no effect LCD_STAT=*(unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_PDSR )));//PC0...PC31 *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_OER )))) = 0xFF<<16;//as output again } while (((LCD_STAT >>16 )&0x80)!=0); //bit 7 of pc23..pc16 is 1 is busy. pc23..16>>16=>D7..D0
//RW=0; LCD_WRITE; //DATA=i; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = i<<16; //all 1 bit output *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = (~i)<<16; //all 0 bit output use negtive //E1=1; //E1=0; SET_LCD_E1; Clear_LCD_E1; } /*------------------------------------------------------------------------------ -- 调用方式:void OutMD(uchar i) 函数说明:发数据i到主窗口。(内函数,私有,用户不直接调用) -------------------------------------------------------------------------------- -*/ void OutMD(uchar i) { volatile unsigned int LCD_STAT; // A0=0; LCD_CMD ; // RW=1; LCD_READ; do //if lcd is always busy ,should no return,so should add couter for exit of timeout { //DATA=0xFF; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0xFF<<16; //all data to 1 //E1=1; SET_LCD_E1; //LCD_STAT=LCD_BUSY; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_ODR )))) = 0xFF<<16;//as input //0 bit no effect LCD_STAT=*(unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_PDSR )));//PC0...PC31 *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_OER )))) = 0xFF<<16;//as output again } while (((LCD_STAT >>16 )&0x80)!=0); //bit 7 of pc23..pc16 is 1 is busy. pc23..16>>16=>D7..D0
// A0=1; LCD_DATA; //RW=0; LCD_WRITE; //DATA=i; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = i<<16; //all 1 bit output *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = (~i)<<16; //all 0 bit output use negtive //E1=1; //E1=0; SET_LCD_E1; Clear_LCD_E1; } /*------------------------------------------------------------------------------ -- 调用方式:void OutSI(uchar i) 函数说明:发指令i到从窗口。(内函数,私有,用户不直接调用) -------------------------------------------------------------------------------- -*/ void OutSI(uchar i) { volatile unsigned int LCD_STAT; // A0=0; LCD_CMD ; // RW=1; LCD_READ; do //if lcd is always busy ,should no return,so should add couter for exit of timeout { //DATA=0xFF; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0xFF<<16; //all data to 1 //E1=1; SET_LCD_E2; //LCD_STAT=LCD_BUSY; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_ODR )))) = 0xFF<<16;//as input //0 bit no effect LCD_STAT=*(unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_PDSR )));//PC0...PC31 *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_OER )))) = 0xFF<<16;//as output again } while (((LCD_STAT >>16 )&0x80)!=0); //bit 7 of pc23..pc16 is 1 is busy. pc23..16>>16=>D7..D0
//RW=0; LCD_WRITE; //DATA=i; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = i<<16; //all 1 bit output ; 0 no effect *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = (~i)<<16; //all 0 bit output use negtive //E1=1; //E1=0; SET_LCD_E2; Clear_LCD_E2; } /*------------------------------------------------------------------------------ -- 调用方式:void OutSD(uchar i) 函数说明:发数据i到从窗口。(内函数,私有,用户不直接调用) -------------------------------------------------------------------------------- -*/ void OutSD(uchar i) { volatile unsigned int LCD_STAT; // A0=0; LCD_CMD ; // RW=1; LCD_READ; do //if lcd is always busy ,should no return,so should add couter for exit of timeout { //DATA=0xFF; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0xFF<<16; //all data to 1 //E1=1; SET_LCD_E2; //LCD_STAT=LCD_BUSY; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_ODR )))) = 0xFF<<16;//as input //0 bit no effect LCD_STAT=*(unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_PDSR )));//PC0...PC31 *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_OER )))) = 0xFF<<16;//as output again } while (((LCD_STAT >>16 )&0x80)!=0); //bit 7 of pc23..pc16 is 1 is busy. pc23..16>>16=>D7..D0
// A0=1; LCD_DATA; //RW=0; LCD_WRITE; //DATA=i; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = i<<16; //all 1 bit output *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = (~i)<<16; //all 0 bit output use negtive //E1=1; //E1=0; SET_LCD_E2; Clear_LCD_E2; }
/*------------------------------------------------------------------------------ -- 调用方式:void LcdIni(void) 函数说明:12232点阵液晶初始化,开机后仅调用一次。 -------------------------------------------------------------------------------- -*/ void LcdIni(void) { unsigned int i; //LCD_RESET=0; //to 68 mode *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_CODR)))) = 0x1 <<14;//Reset PC14=0 for(i=0;i<255;i++); //LCD_RESET=1; *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_SODR)))) = 0x1 <<14;//Reset PC14=1 OutMI(0XE2);OutSI(0XE2);//复位 OutMI(0XA4);OutSI(0XA4);//动态驱动//关闭休闲状态 //OutMI(0XAE);OutSI(0XAE);//POWER SAVE //disp off OutMI(0XA9);OutSI(0XA9);//1/32占空比 OutMI(0XA0);OutSI(0XA0);// ADC forward ,时钟线输出 OutMI(0Xc0);OutSI(0Xc0);//display start line,first line OutMI(0X00);OutSI(0X00);//col address 0 OutMI(0XB8);OutSI(0XB8);//set page 0 OutMI(0XEE);OutSI(0XEE);//read modify off 写模式 OutMI(0XAF);OutSI(0XAF); //display on of main and master } /*------------------------------------------------------------------------------ -- 调用方式:void SetPage(uchar page0,uchar page1) 函数说明:同时设置主从显示页为0-3页。(内函数,私有,用户不直接调用) -------------------------------------------------------------------------------- -*/ void SetPage(uchar page0,uchar page1) { OutMI(0xB8|page1);OutSI(0xB8|page0); }
/*------------------------------------------------------------------------------ -- 调用方式:void SetAddress(uchar address0,uchar address1) 函数说明:同时设置主从列地址为0-121。(内函数,私有,用户不直接调用) -------------------------------------------------------------------------------- -*/ void SetAddress(uchar address0,uchar address1) { OutMI(address1&0x7F);OutSI(address0&0x7F); } /*------------------------------------------------------------------------------ -- 调用方式:void SetStartRow(uchar row0,uchar row1) 函数说明:同时设置主从行地址为0-31。(内函数,私有,用户不直接调用) -------------------------------------------------------------------------------- -*/ void SetStartRow(uchar row0,uchar row1) { OutMI(row0&0xC0);OutSI(row1&0xC0); }
/*------------------------------------------------------------------------------ -- 调用方式:void PutChar0(uchar ch) 函数说明:在左页当前地址画一个字节8个点。(内函数,私有,用户不直接调用) -------------------------------------------------------------------------------- -*/ void PutChar0(uchar ch) { OutSD(ch); }
/*------------------------------------------------------------------------------ -- 调用方式:void PutChar1(uchar ch) 函数说明:在右页当前地址画一个字节8个点。(内函数,私有,用户不直接调用) -------------------------------------------------------------------------------- -*/ void PutChar1(uchar ch) { OutMD(ch); }
/*------------------------------------------------------------------------------ -- 调用方式:void clrscr(void) 函数说明:清屏 -------------------------------------------------------------------------------- -*/ void clrscr(void) { uchar i;
for (page=0;page<4;page++) { SetPage(page,page); SetAddress(0,0); for (i=0;i<61;i++){PutChar0(0x00);PutChar1(0);} } page=FIRSTPAGE; PixX=0; SetPage(page,page); SetAddress(0,0); SetStartRow(0,0); }
/*------------------------------------------------------------------------------ -- every chinese charset is 16x16 bitmap 调用方式:void LcdPutCch(unsigned char str[]) 函数说明:显示中文字符 字符在LCD上的显示速度较慢,如果正在接受serial port的数据,请不要一次显示太多的字符, 以免字符接受丢失 进入中文显示方式是: 发送字符 CCHMODE (0xF0); 发送字符阵列(纵向16点阵(上部),纵向16点阵(下部) 调用LcdPutCch,str为点阵指针; --------------------------------------------------------------------------------*/ /*void LcdPutCch(unsigned char str[]) { unsigned char i,j; if (PixX>121-15) //no space to place one chinese char , need to <CR> { page++; if (page==4) //out of last line page=0; //wrap to firt line of display PixX=0; SetPage(page,page); SetAddress(0,0); } for (i=0;i<32;i++) { if (i==16) { PixX=PixX-16; //back 16 pix page++; if (page==4) //out of last line page=0; //wrap to firt line of display SetPage(page,page); SetAddress(PixX,PixX); } if (PixX<61) //0..60 { PutChar1(str); PixX++; } else //61..121 { PutChar0(str); PixX++; } } } */ /*------------------------------------------------------------------------------ -- every english charset is 8x8 bitmap 调用方式:void LcdPutCh(unsigned char ch) 函数说明:显示字符 only display from 0x20 to 0x7f , all ASCIII code. 字符在LCD上的显示速度较慢,如果正在接受serial port的数据,请不要一次显示太多的字符, 以免字符接受丢失 --------------------------------------------------------------------------------*/ void LcdPutCh(unsigned char ch) { unsigned char i,j;
if (ch=='\n') //need to <CR> { page++; if (page==4) //out of last line page=0; //wrap to firt line of display PixX=0; SetPage(page,page); SetAddress(0,0); return; } if (PixX>121-6) //no space to place one char , need to <CR> { page++; if (page==4) //out of last line page=0; //wrap to firt line of display PixX=0; SetPage(page,page); SetAddress(0,0); }
i=ch-' '; for (j=0;j<5;j++) //3 space pixel { if (PixX<61) //0..60 { PutChar1(Fonts[j]); PixX++; } else //61..121 { PutChar0(Fonts[j]); PixX++; } } for (j=0;j<3;j++) { if (PixX<61) //0..60 { PutChar1(0x0); PixX++; } else //61..121 { PutChar0(0x0); PixX++; } } } /*------------------------------------------------------------------------------ -- 调用方式: 函数说明:显示字符串 \n will <CR>, string length must be less then 255. every line <15 ASCII, It will be display line by line, if display after last line,it will be display in first line --------------------------------------------------------------------------------*/ void LcdPutS(unsigned char *Str) { unsigned char i; for (i=0;i<strlen(Str);i++) { LcdPutCh(Str); } } //#define DEBUGMSG(x, y, args...) FILE *f; int n,fd;
int main(int argc, char *argv[]) { char num,status=0; int i,j,count; int ch; printf("start\n"); if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1){ DEBUGMSG(DEBUG_ERR, "gpio: Error opening /dev/mem\n"); exit(-1); } //map 0xffff map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, AT91_SYS);//AT91_SYS = 0xffff f000 *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_PER )))) = 0x50FF6400; //PC23:PC16 PC14,13,10,30,28as gpio ;1 bit set to GPIO and zero bit no effect //may the format is better= (0xff<<16)|(0x1<<14)|(0x1<<13)|(0x1<<10)|(0x1<<30)|(0x1<<28); *((volatile unsigned int*)(map_base + ((PIOC_OFFSET + AT91_PIO_OER )))) = 0x50FF6400;//as output
LcdIni(); //LCD init and reset clrscr(); LcdPutS("1234567890abcde"); LcdPutS("2@#$%^&*()ABCDF"); clrscr(); LcdPutS("$:>"); close(fd); return 0; }
|
|