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