AT91RM9200+S1D13505,本来想用S1D13506可惜公司没有库存,大量使用S1D13505,只好慢慢啃了。使用ncs7接S1D13505的片选,使用如下测试程序
unsigned char * pRegs=0X80000000;
static unsigned short tmp=0x55;
//Step 1: Enable the host interface.
*(pRegs + 0x1B) = 0x00; /* 0000 0000 */
while(1){
tmp=*((unsigned char *)0x80000000);
}
一直没有调试通,使用示波器测量结果发现接M/R的A21引脚竟然被拉高,我觉得很奇怪。甚至我去掉pRegs直接硬读0x80000000的版本寄存器内容A21还是被拉高,这是为什么呢?
今天终于解决了S1D13505的LCD显示问题,当初以为两者差不多,偷懒,没有把datasheet从头到尾研究过,最终酿成苦果,花了2天时间才查出问题所在。原来它比S1D13506多了个SUSPEND引脚,用于控制LCD进入省电模式,当MD9下拉时SUSPEND引脚=0时立即进入硬件休眠状态,所有内存与寄存器都不能读写。要读写寄存器必须将SUSPEND引脚拉高。没办法,我飞!飞完后液晶测试正常,可惜没带数码相机。奇怪的是A21引脚依然在我不访问200000地址时还是被周期性拉高,看了一下时许,与CS配合感觉好像是对的。可能是S1D13505内部造成的。
测试程序如下:
/*
**===========================================================================
**Designed for SSC 510T LCD test;
** The code in this example will perform initialization to the following
** specification:
**
** - 640 x 480 dual 16-bit color passive panel.
** - 75 Hz frame rate.
** - 8 BPP (256 colors).
** - 33 MHz input clock.
** - 2 MB of 60 ns EDO memory.
**---------------------------------------------------------------------------
** Copyright (c) 2008 WFG
** All Rights Reserved.
**===========================================================================
*/
/*
** Note that only the upper four bits of the LUT are actually used.
*/
unsigned char LUT8[256*3] =
{
/* Primary and secondary colors */
0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x00, 0xA0, 0xA0,
0xA0, 0x00, 0x00, 0xA0, 0x00, 0xA0, 0xA0, 0xA0, 0x00, 0xA0, 0xA0, 0xA0,
0x50, 0x50, 0x50, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0xF0,
0xF0, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0xF0, 0xF0, 0x00, 0xF0, 0xF0, 0xF0,
/* Gray shades */
0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30,
0x40, 0x40, 0x40, 0x50, 0x50, 0x50, 0x60, 0x60, 0x60, 0x70, 0x70, 0x70,
0x80, 0x80, 0x80, 0x90, 0x90, 0x90, 0xA0, 0xA0, 0xA0, 0xB0, 0xB0, 0xB0,
0xC0, 0xC0, 0xC0, 0xD0, 0xD0, 0xD0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0,
/* Black to red */
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00,
0x40, 0x00, 0x00, 0x50, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00,
0x80, 0x00, 0x00, 0x90, 0x00, 0x00, 0xA0, 0x00, 0x00, 0xB0, 0x00, 0x00,
0xC0, 0x00, 0x00, 0xD0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00,
/* Black to green */
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, 0x00,
0x00, 0x40, 0x00, 0x00, 0x50, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00,
0x00, 0x80, 0x00, 0x00, 0x90, 0x00, 0x00, 0xA0, 0x00, 0x00, 0xB0, 0x00,
0x00, 0xC0, 0x00, 0x00, 0xD0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xF0, 0x00,
/* Black to blue */
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30,
0x00, 0x00, 0x40, 0x00, 0x00, 0x50, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70,
0x00, 0x00, 0x80, 0x00, 0x00, 0x90, 0x00, 0x00, 0xA0, 0x00, 0x00, 0xB0,
0x00, 0x00, 0xC0, 0x00, 0x00, 0xD0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xF0,
/* Blue to cyan (blue and green) */
0x00, 0x00, 0xF0, 0x00, 0x10, 0xF0, 0x00, 0x20, 0xF0, 0x00, 0x30, 0xF0,
0x00, 0x40, 0xF0, 0x00, 0x50, 0xF0, 0x00, 0x60, 0xF0, 0x00, 0x70, 0xF0,
0x00, 0x80, 0xF0, 0x00, 0x90, 0xF0, 0x00, 0xA0, 0xF0, 0x00, 0xB0, 0xF0,
0x00, 0xC0, 0xF0, 0x00, 0xD0, 0xF0, 0x00, 0xE0, 0xF0, 0x00, 0xF0, 0xF0,
/* Cyan (blue and green) to green */
0x00, 0xF0, 0xF0, 0x00, 0xF0, 0xE0, 0x00, 0xF0, 0xD0, 0x00, 0xF0, 0xC0,
0x00, 0xF0, 0xB0, 0x00, 0xF0, 0xA0, 0x00, 0xF0, 0x90, 0x00, 0xF0, 0x80,
0x00, 0xF0, 0x70, 0x00, 0xF0, 0x60, 0x00, 0xF0, 0x50, 0x00, 0xF0, 0x40,
0x00, 0xF0, 0x30, 0x00, 0xF0, 0x20, 0x00, 0xF0, 0x10, 0x00, 0xF0, 0x00,
/* Green to yellow (red and green) */
0x00, 0xF0, 0x00, 0x10, 0xF0, 0x00, 0x20, 0xF0, 0x00, 0x30, 0xF0, 0x00,
0x40, 0xF0, 0x00, 0x50, 0xF0, 0x00, 0x60, 0xF0, 0x00, 0x70, 0xF0, 0x00,
0x80, 0xF0, 0x00, 0x90, 0xF0, 0x00, 0xA0, 0xF0, 0x00, 0xB0, 0xF0, 0x00,
0xC0, 0xF0, 0x00, 0xD0, 0xF0, 0x00, 0xE0, 0xF0, 0x00, 0xF0, 0xF0, 0x00,
/* Yellow (red and green) to red */
0xF0, 0xF0, 0x00, 0xF0, 0xE0, 0x00, 0xF0, 0xD0, 0x00, 0xF0, 0xC0, 0x00,
0xF0, 0xB0, 0x00, 0xF0, 0xA0, 0x00, 0xF0, 0x90, 0x00, 0xF0, 0x80, 0x00,
0xF0, 0x70, 0x00, 0xF0, 0x60, 0x00, 0xF0, 0x50, 0x00, 0xF0, 0x40, 0x00,
0xF0, 0x30, 0x00, 0xF0, 0x20, 0x00, 0xF0, 0x10, 0x00, 0xF0, 0x00, 0x00,
/* Red to magenta (blue and red) */
0xF0, 0x00, 0x00, 0xF0, 0x00, 0x10, 0xF0, 0x00, 0x20, 0xF0, 0x00, 0x30,
0xF0, 0x00, 0x40, 0xF0, 0x00, 0x50, 0xF0, 0x00, 0x60, 0xF0, 0x00, 0x70,
0xF0, 0x00, 0x80, 0xF0, 0x00, 0x90, 0xF0, 0x00, 0xA0, 0xF0, 0x00, 0xB0,
0xF0, 0x00, 0xC0, 0xF0, 0x00, 0xD0, 0xF0, 0x00, 0xE0, 0xF0, 0x00, 0xF0,
/* Magenta (blue and red) to blue */
0xF0, 0x00, 0xF0, 0xE0, 0x00, 0xF0, 0xD0, 0x00, 0xF0, 0xC0, 0x00, 0xF0,
0xB0, 0x00, 0xF0, 0xA0, 0x00, 0xF0, 0x90, 0x00, 0xF0, 0x80, 0x00, 0xF0,
0x70, 0x00, 0xF0, 0x60, 0x00, 0xF0, 0x50, 0x00, 0xF0, 0x40, 0x00, 0xF0,
0x30, 0x00, 0xF0, 0x20, 0x00, 0xF0, 0x10, 0x00, 0xF0, 0x00, 0x00, 0xF0,
/* Black to magenta (blue and red) */
0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x20, 0x00, 0x20, 0x30, 0x00, 0x30,
0x40, 0x00, 0x40, 0x50, 0x00, 0x50, 0x60, 0x00, 0x60, 0x70, 0x00, 0x70,
0x80, 0x00, 0x80, 0x90, 0x00, 0x90, 0xA0, 0x00, 0xA0, 0xB0, 0x00, 0xB0,
0xC0, 0x00, 0xC0, 0xD0, 0x00, 0xD0, 0xE0, 0x00, 0xE0, 0xF0, 0x00, 0xF0,
/* Black to cyan (blue and green) */
0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x20, 0x20, 0x00, 0x30, 0x30,
0x00, 0x40, 0x40, 0x00, 0x50, 0x50, 0x00, 0x60, 0x60, 0x00, 0x70, 0x70,
0x00, 0x80, 0x80, 0x00, 0x90, 0x90, 0x00, 0xA0, 0xA0, 0x00, 0xB0, 0xB0,
0x00, 0xC0, 0xC0, 0x00, 0xD0, 0xD0, 0x00, 0xE0, 0xE0, 0x00, 0xF0, 0xF0,
/* Red to white */
0xF0, 0x00, 0x00, 0xF0, 0x10, 0x10, 0xF0, 0x20, 0x20, 0xF0, 0x30, 0x30,
0xF0, 0x40, 0x40, 0xF0, 0x50, 0x50, 0xF0, 0x60, 0x60, 0xF0, 0x70, 0x70,
0xF0, 0x80, 0x80, 0xF0, 0x90, 0x90, 0xF0, 0xA0, 0xA0, 0xF0, 0xB0, 0xB0,
0xF0, 0xC0, 0xC0, 0xF0, 0xD0, 0xD0, 0xF0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0,
/* Green to white */
0x00, 0xF0, 0x00, 0x10, 0xF0, 0x10, 0x20, 0xF0, 0x20, 0x30, 0xF0, 0x30,
0x40, 0xF0, 0x40, 0x50, 0xF0, 0x50, 0x60, 0xF0, 0x60, 0x70, 0xF0, 0x70,
0x80, 0xF0, 0x80, 0x90, 0xF0, 0x90, 0xA0, 0xF0, 0xA0, 0xB0, 0xF0, 0xB0,
0xC0, 0xF0, 0xC0, 0xD0, 0xF0, 0xD0, 0xE0, 0xF0, 0xE0, 0xF0, 0xF0, 0xF0,
/* Blue to white */
0x00, 0x00, 0xF0, 0x10, 0x10, 0xF0, 0x20, 0x20, 0xF0, 0x30, 0x30, 0xF0,
0x40, 0x40, 0xF0, 0x50, 0x50, 0xF0, 0x60, 0x60, 0xF0, 0x70, 0x70, 0xF0,
0x80, 0x80, 0xF0, 0x90, 0x90, 0xF0, 0xA0, 0xA0, 0xF0, 0xB0, 0xB0, 0xF0,
0xC0, 0xC0, 0xF0, 0xD0, 0xD0, 0xF0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0
};
/*
** REGISTER_OFFSET points to the starting address of the S1D13505 registers
*/
#define REGISTER_OFFSET ((unsigned char *) 0x80000000)
/*
** DISP_MEM_OFFSET points to the starting address of the display buffer memory
*/
#define DISP_MEM_OFFSET ((unsigned char *) 0x80200000)
/*
** DISP_MEMORY_SIZE is the size of display buffer memory
*/
#define DISP_MEMORY_SIZE 0x200000
/*
** Calculate the value to put in Ink/Cursor Start Address Select Register
** Offset = (DISP_MEM_SIZE - (X * 8192)
** We want the offset to be just past the end of display memory so:
** (640 * 480) = DISP_MEMORY_SIZE - (X * 8192)
**
** CURSOR_START = (DISP_MEMORY_SIZE - (640 * 480)) / 8192
*/
#define CURSOR_START 218
void LCD_Test(void)
{
unsigned char * pRegs = REGISTER_OFFSET;
unsigned char * pMem;
unsigned char * pLUT;
unsigned char * pTmp;
unsigned char * pCursor;
static unsigned short tmp=0x55;
long lpCnt;
int idx;
int rgb;
long x, y;
/*
** Initialize the chip.
*/
/*
** Step 1: Enable the host interface.
**
** Register 1B: Miscellaneous Disable - host interface enabled, half frame
** buffer enabled.
*/
*(pRegs + 0x1B) = 0x00; /* 0000 0000 */
//add by wfg
// while(1){
tmp=*((volatile unsigned char *)0x80000000);
// *((unsigned char *)0x8020001b) = 0x00;
// }
/*
** Step 2: Disable the FIFO
*/
*(pRegs + 0x23) = 0x80; /* 1000 0000 */
/*
** Step 3: Set Memory Configuration
**
** Register 1: Memory Configuration - 5 ms refresh, EDO
*/
*(pRegs + 0x01) = 0x40; /* 0011 0000 */
/*
** Step 4: Set Performance Enhancement 0 register
*/
*(pRegs + 0x22) = 0x24; /* 0010 0100 */
/*
** Step 5: Set the rest of the registers in order.
*/
/*
** Register 2: Panel Type - 16-bit, format 1, color, dual, passive.
*/
*(pRegs + 0x02) = 0x26; /* 0010 0110 */
/*
** Register 3: Mod Rate
*/
*(pRegs + 0x03) = 0x00; /* 0000 0000 */
/*
** Register 4: Horizontal Display Width (HDP) - 640 pixels
** (640 / 8) - 1 = 79t = 4Fh
*/
*(pRegs + 0x04) = 0x4f; /* 0100 1111 */
/*
** Register 5: Horizontal Non-Display Period (HNDP)
** PCLK
** Frame Rate = -----------------------------
** (HDP + HNDP) * (VDP + VNDP)
**
** 16,500,000
** = -----------------------------
** (640 + HNDP) * (480 + VNDP)
**
** HNDP and VNDP must be calculated such that the desired frame rate
** is achieved.
*/
*(pRegs + 0x05) = 0x1F; /* 0001 1111 */
/*
** Register 6: HRTC/FPLINE Start Position - applicable to CRT/TFT only.
*/
*(pRegs + 0x06) = 0x00; /* 0000 0000 */
/*
** Register 7: HRTC/FPLINE Pulse Width - applicable to CRT/TFT only.
*/
*(pRegs + 0x07) = 0x00; /* 0000 0000 */
/*
** Registers 8-9: Vertical Display Height (VDP) - 480 lines.
** 480/2 - 1 = 239t = 0xEF
*/
*(pRegs + 0x08) = 0xEF; /* 1110 1111 */
*(pRegs + 0x09) = 0x00; /* 0000 0000 */
/*
** Register A: Vertical Non-Display Period (VNDP)
** This register must be programed with register 5 (HNDP)
** to arrive at the frame rate closest to the desired
** frame rate.
*/
*(pRegs + 0x0A) = 0x01; /* 0000 0001 */
/*
** Register B: VRTC/FPFRAME Start Position - applicable to CRT/TFT only.
*/
*(pRegs + 0x0B) = 0x00; /* 0000 0000 */
/*
** Register C: VRTC/FPFRAME Pulse Width - applicable to CRT/TFT only.
*/
*(pRegs + 0x0C) = 0x00; /* 0000 0000 */
/*
** Register D: Display Mode - 8 BPP, LCD disabled.
*/
*(pRegs + 0x0D) = 0x0C; /* 0000 1100 */
/*
** Registers E-F: Screen 1 Line Compare - unless setting up for
** split screen operation use 0x3FF.
*/
*(pRegs + 0x0E) = 0xFF; /* 1111 1111 */
*(pRegs + 0x0F) = 0x03; /* 0000 0011 */
/*
** Registers 10-12: Screen 1 Display Start Address - start at the
** first byte in display memory.
*/
*(pRegs + 0x10) = 0x00; /* 0000 0000 */
*(pRegs + 0x11) = 0x00; /* 0000 0000 */
*(pRegs + 0x12) = 0x00; /* 0000 0000 */
/*
** Register 13-15: Screen 2 Display Start Address - not applicable
** unless setting up for split screen operation.
*/
*(pRegs + 0x13) = 0x00; /* 0000 0000 */
*(pRegs + 0x14) = 0x00; /* 0000 0000 */
*(pRegs + 0x15) = 0x00; /* 0000 0000 */
/*
** Register 16-17: Memory Address Offset - this address represents the
** starting WORD. At 8BPP our 640 pixel width is 320
** WORDS
*/
*(pRegs + 0x16) = 0x40; /* 0100 0000 */
*(pRegs + 0x17) = 0x01; /* 0000 0001 */
/*
** Register 18: Pixel Panning
*/
*(pRegs + 0x18) = 0x00; /* 0000 0000 */
/*
** Register 19: Clock Configuration - In this case we must divide
** PCLK by 2 to arrive at the best frequency to set
** our desired panel frame rate.
*/
*(pRegs + 0x19) = 0x01; /* 0000 0001 */
/*
** Register 1A: Power Save Configuration - enable LCD power, CBR refresh,
** not suspended.
*/
*(pRegs + 0x1A) = 0x00; /* 0000 0000 */
/*
** Register 1C-1D: MD Configuration Readback - these registers are
** read only, but it's OK to write a 0 to keep
** the register configuration logic simpler.
*/
*(pRegs + 0x1C) = 0x00; /* 0000 0000 */
*(pRegs + 0x1D) = 0x00; /* 0000 0000 */
/*
** Register 1E-1F: General I/O Pins Configuration
*/
*(pRegs + 0x1E) = 0x00; /* 0000 0000 */
*(pRegs + 0x1F) = 0x00; /* 0000 0000 */
/*
** Register 20-21: General I/O Pins Control
*/
*(pRegs + 0x20) = 0x00; /* 0000 0000 */
*(pRegs + 0x21) = 0x00; /* 0000 0000 */
/*
** Registers 24-26: LUT control.
** For this example do a typical 8 BPP LUT setup.
**
** Setup the pointer to the LUT data and reset the LUT index register.
** Then, loop writing each of the RGB LUT data elements.
*/
pLUT = LUT8;
*(pRegs + 0x24) = 0;
for (idx = 0; idx < 256; idx++)
{
for (rgb = 0; rgb < 3; rgb++)
{
*(pRegs + 0x26) = *pLUT;
pLUT++;
}
}
/*
** Register 27: Ink/Cursor Control - disable ink/cursor
*/
*(pRegs + 0x27) = 0x00; /* 0000 0000 */
/*
** Registers 28-29: Cursor X Position
*/
*(pRegs + 0x28) = 0x00; /* 0000 0000 */
*(pRegs + 0x29) = 0x00; /* 0000 0000 */
/*
** Registers 2A-2B: Cursor Y Position
*/
*(pRegs + 0x2A) = 0x00; /* 0000 0000 */
*(pRegs + 0x2B) = 0x00; /* 0000 0000 */
/*
** Registers 2C-2D: Ink/Cursor Color 0 - blue
*/
*(pRegs + 0x2C) = 0x1F; /* 0001 1111 */
*(pRegs + 0x2D) = 0x00; /* 0000 0000 */
/*
** Registers 2E-2F: Ink/Cursor Color 1 - green
*/
*(pRegs + 0x2E) = 0xE0; /* 1110 0000 */
*(pRegs + 0x2F) = 0x07; /* 0000 0111 */
/*
** Register 30: Ink/Cursor Start Address Select
*/
*(pRegs + 0x30) = 0x00; /* 0000 0000 */
/*
** Register 31: Alternate FRM Register
*/
*(pRegs + 0x31) = 0x00;
/*
** Register 23: Performance Enhancement - display FIFO enabled, optimum
** performance. The FIFO threshold is set to 0x00; for
** 15/16 bpp modes, set the FIFO threshold
** to a higher value, such as 0x1B.
*/
*(pRegs + 0x23) = 0x00; /* 0000 0000 */
/*
** Register D: Display Mode - 8 BPP, LCD enable.
*/
*(pRegs + 0x0D) = 0x0D; /* 0000 1101 */
/*
** Clear memory by filling 2 MB with 0
*/
pMem = DISP_MEM_OFFSET;
for (lpCnt = 0; lpCnt < DISP_MEMORY_SIZE; lpCnt++)
{
*pMem = 0;
pMem++;
}
/*
** Draw a 100x100 red rectangle in the upper left corner (0, 0)
** of the display.
*/
pMem = DISP_MEM_OFFSET;
for (y = 0; y < 100; y++)
{
pTmp = pMem + y * 640L;
for (x = 0; x < 100; x++)
{
*pTmp = 0x0c;
pTmp++;
}
}
/*
** Init the HW cursor. In this example the cursor memory will be located
** immediately after display memory. Why here? Because it's an easy
** location to calculate and will not interfere with the half frame buffer.
** Additionally, the HW cursor can be turned into an ink layer quite
** easily from this location.
*/
*(pRegs + 0x30) = CURSOR_START;
pTmp = pCursor = pMem + (DISP_MEMORY_SIZE - (CURSOR_START * 8192L));
/*
** Set the contents of the cursor memory such that the cursor
** is transparent. To do so, write a 10101010b pattern in each byte.
** The cursor is 2 bpp so a 64x64 cursor requires
** 64/4 * 64 = 1024 bytes of memory.
*/
for (lpCnt = 0; lpCnt < 1024; lpCnt++)
{
*pTmp = 0xAA;
pTmp++;
}
/*
** Set the first user definable cursor color to black and
** the second user definable cursor color to white.
*/
*(pRegs + 0x2C) = 0;
*(pRegs + 0x2D) = 0;
*(pRegs + 0x2E) = 0xFF;
*(pRegs + 0x2F) = 0xFF;
/*
** Draw a hollow rectangle around the cursor.
*/
pTmp = pCursor;
for (lpCnt = 0; lpCnt < 16; lpCnt++)
{
*pTmp = 0x55;
pTmp++;
}
for (lpCnt = 0; lpCnt < 14; lpCnt++)
{
*pTmp = 0x6A;
pTmp += 15;
*pTmp = 0xA9;
pTmp++;
}
for (lpCnt = 0; lpCnt < 16; lpCnt++)
{
*pTmp = 0x55;
pTmp++;
}
/*
** Move the cursor to 100, 100.
*/
/*
** First we wait for the next vertical non-display
** period before updating the position registers.
*/
while (*(pRegs + 0x0A) & 0x80); /* wait while in VNDP */
while (!(*(pRegs + 0x0A) & 0x80)); /* wait while in VDP */
/*
** Now update the position registers.
*/
*(pRegs + 0x28) = 100; /* Set Cursor X = 100 */
*(pRegs + 0x29) = 0x00;
*(pRegs + 0x2A) = 100; /* Set Cursor Y = 100 */
*(pRegs + 0x2B) = 0x00;
/*
** Enable the hardware cursor.
*/
*(pRegs + 0x27) = 0x40;
}
此段程序成功让液晶在红绿蓝间切换。可是还不能实现方框的绘制的功能,奇怪,为什么呢?