打印

at91rm9200驱动 sed1520 12232 lcd的程序(原创)

[复制链接]
3252|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wangkj|  楼主 | 2007-9-11 15:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

/*-------------------------------------------------------------------------------------
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;
}

相关帖子

沙发
LPcfANS| | 2007-9-11 15:18 | 只看该作者

沙发.

使用特权

评论回复
板凳
wangkj|  楼主 | 2007-9-11 15:21 | 只看该作者

http 下载地址:

这是根据我的at91_core和ext扩展做得,这个是12232的。
刚刚完成,还没测试。以前测试过320*240和19264的是没有问题的。
用GPIO驱动的,改动起来很容易,非内核方式。
原来我说过,作一个使用的非内核驱动的例子,这个就是了。

使用特权

评论回复
地板
wangkj|  楼主 | 2007-9-11 15:28 | 只看该作者

沙发太快了 ......比我的注释还快。

我写的这个例子程序注释极其清楚。如果再不明白。无语了。
LCD 手册:http://amd.9966.org/pic/qf12232A.pdf
这个程序是给别人订做的,不过,版权是我的,就公开了。
这个仅仅是lcd部分的。所以,对用户也没有任何损失。

使用特权

评论回复
5
阿南| | 2007-9-11 20:17 | 只看该作者

支持老wang,嗨没办法!否则要天天给您穿红酷头,烦死人.

以后自己加

使用特权

评论回复
6
wangkj|  楼主 | 2007-9-12 08:02 | 只看该作者

这个程序和51的程序除了最底层的四个函数不同

其他的完全相同。最底层的四个函数其实也是类似的。
这些都是直接控制硬件实现的。
就是是我说的,用arm像51一样简单的意思。

使用特权

评论回复
7
wangkj|  楼主 | 2007-9-20 12:27 | 只看该作者

无意中发现 俺的帖子在头版

使用特权

评论回复
8
xieqin| | 2007-9-20 12:53 | 只看该作者

...

玩单片机或只玩玩简单的LCD显示,这种方法倒不错.

对UI要求较高的应用,这种方法的效率和性能就太低了. 用个buffer做虚拟的"屏幕"才行.

不信,搞个简单的两行字重叠显示试试,搞个图片上显示半透字试试

使用特权

评论回复
9
flylongins| | 2007-9-20 19:13 | 只看该作者

老王时间真多啊。。。。

顶。

使用特权

评论回复
10
wangkj|  楼主 | 2007-9-20 22:08 | 只看该作者

这个针对的就是简单应用

让arm9比单片机还简单
如果是我的全环境的at91_core,连编译器都内置到板子中了。

使用特权

评论回复
11
hotpover| | 2007-9-21 22:24 | 只看该作者

怎么会有void *map_base; 这样的语法的 ?

使用特权

评论回复
12
wangkj|  楼主 | 2007-9-22 00:01 | 只看该作者

无类型指针。

使用特权

评论回复
13
ggbb| | 2008-1-23 16:11 | 只看该作者

;;

本帖最后由 ggbb 于 2014-12-1 01:44 编辑

;;

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

581

主题

9976

帖子

24

粉丝