⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ltps_lcd_pmp.c

📁 用PIC24F128GA006做的CF与TFT液晶演示
💻 C
字号:

/*************************************************************************************
 Programmer	: Stanley Huang, The FAE of Hsinchu office.
 Date		: 2007.01.31
 
 Processor	: PIC24FJ128GA006
 Compiler	: C30 V3.0
 Board		: (1)Microchip Taiwan PIC24 64-pin demo board
 		  	  (2)TPO 1.77" 128x160xRGB LTPS panel, TD018THEM2,
 
 *************************************************************************************/

/* Setup:

	- If you plan on interfacing to a CompactFlash card, add cf.c and CF.h to
		your project.  If you're using SD or MMC cards, add sdmmc.c, sdmmc.h,
		and sdmmc_lld.h.  Set the appropriate preprocessor directive in _fat.def.
		"#if 0" for CF, "#if 1" for SD/MMC.
	- Define your system clock in _fat.def
	- If you're going to use static memory for your file objects, specify the 
		maximum number of files that you are going to open at any time in _fat.def
	- Uncomment the appropriate SPI line in _fat.def.  FAT_MEDIA_IF_SPI if your part
		only has one SPI module, FAT_MEDIA_IF_SPI1 if your part has two modules and you
		are using the first one, FAT_MEDIA_IF_SPI2 if your part has two modules and you
		are using the second one.  Only necessary for SD/MMC
	- If you are using PIC18, modify your linker file to include a 
		512-byte section of RAM that will act as a buffer for file reads/writes.
		This buffer is defined at the top of the sdmmc.c or 
		cf.c files.  You should also create a section in the linker mapped 
		to this RAM called "myBuff."  An example of how to do this is given 
		in the 18F4550 linker file included with this library
	- If you plan to use dynamic memory to allocate file objects, set the 
		corresponding preprocessor directive in the _fat.def file to "#if 1"
		Also, if you are using PIC18, you must create a section in the linker
		file called "_SRAM_ALLOC_HEAP" that contains enough memory to contain all
		of the file objects you want to open.  Each file object is 46 bytes.  Due to
		variation in the memory allocation algorithm, the amount you are required to
		allocate will be larger than this.  This is also true for PIC24.  Testing
		will be necessary to determine if enough memory was allocated.  Include the
		salloc.c and salloc.h files in your project if you are using PIC18.
		If you plan on using dynamic memory allocation with the PIC24, you will need
		to create a heap in the MPLINK30 tab of the Build Options menu.
	-Set the library path and include path (and linker path, if PIC18) in the General
		tab of the Build Options menu
	-Set the required input and output pins in CF.h or sdmmc.h.  These include:
		CF.h: Address and Data busses and Tri-state registers, Chip select, output enable,
			write enable, reset, ready, and card detect
		sdmmc.h: Chip select, write enabled, card detect
		These pins have separate definitions for PIC18 and PIC24 in the files.
	-Make sure that all pins you use are configured as digital I/Os, including PORTB pins set
		in the configuration registers, and any pins that could be analog channels for the A/D 
		converter
	-Select the appropriate device and language toolset.  The code that will be compiled will
		be appropriate to the processor type (PIC18 or PIC24F)
	-Add Compiler.h to your project files if you're using PIC18

*/

#include "FAT16.h"
#include "system.h"
#include "Bitmap.h"

// Setup configuration bits
_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2) 
_CONFIG2( FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & IESO_OFF)  
//

void InitialIOPort(void);
void PMPInitial(void);
void PowerOnLCD(void);

void WriteLCD_Data(unsigned char DataByte);
void WriteLCD_Command(unsigned char RegAddress, unsigned char CommandByte);
void MovePenXY(unsigned char X, unsigned char Y);

void ADC10_Initial(void);
unsigned int ReadAD(void);
void CheckTask(void);
void PerformTask(void);
void Timer32Init(void);
void WaitNSec(void);

void Delay(int value);



/**************************************************************************************
-This Panel uses these pins below:

PortD<0>		= LTPS$CS_N
PortD<1>		= LTPS$RESET_N
PortE<7:0> (PMP Data) 	= LTPS$D7~D0
PortD<4> (PMP PMWR) 	= LTPS$WR_N
PortB<15> (PMP PMA0) 	= LTPS$RS	// Writing address 0x0000 to set RS=Low
					// Writing address 0x0001 to set RS=High

-The POT use these pins below:
PortB<0>		=> AN0


-The following definition is defined in _fat.def file:	

#define SD_CS		PORTBbits.RB1
#define SD_CS_TRIS	TRISBbits.TRISB1
#define SD_CD		0		//PORTFbits.RF0, Stanley remark, Card alwayse in. 
#define SD_CD_TRIS	TRISFbits.TRISF0
#define SD_WE		0		//PORTFbits.RF1, Stanley remark, alwayse no protect 
#define SD_WE_TRIS	TRISFbits.TRISF1

					
-Note: 
(1)LTPS$VDDIO goes to VDD 3.3V directly.
(2)PortB<14> (PMP PMA1) also can't be used duo to PMP setting.

**************************************************************************************/
#define		LTPS$CS_N        	LATDbits.LATD0
#define		LTPS$RESET_N     	LATDbits.LATD1
#define		LTPS$XStart		0
#define		LTPS$YStart		0
#define		LTPS$XEnd		160
#define		LTPS$YEnd		128


#define		HIGH			1
#define		LOW			0


#define		MaxTask			12	// 0~12

//The destination for the information read from SD card
unsigned char	RdBuffer[3840];

unsigned char 	NewTask, CurrentTask ;


/**************************************************************************************
 || D7, D6, D5, D4, D3, D2, D1, D0 || D7, D6, D5, D4, D3, D2, D1, D0 ||

=>  R5, R4, R3, R2, R1, G5, G4, G3    G2, G1, G0, B5, B4, B3, B2, B1
 
 2 byte per pixel
**************************************************************************************/
unsigned char TPattern[]={
0xF8,0x00,	//Red
0xFC,0x00,
0xFF,0xE0,	//Yellow
0x04,0x10,	
0x00,0x1F,
0x00,0x10,
0x80,0x1F,
0xFF,0xFF	
};


int main(void)
{


			         
	//Nop()
	InitialIOPort();
	PowerOnLCD();

	PMPInitial();				// Initial PMP Module

	LTPS$CS_N	= LOW ;
	WriteLCD_Command(0x06,0xc7);		// Set LCD bias
	WriteLCD_Command(0x17,0x01);		// Set SRAM writed direction
  	LTPS$CS_N	= HIGH ;

	Timer32Init();
	ADC10_Initial();
	
	// Obtain information about the file system on the card
	// This function will also send initialization codes to the card,
	// which means it must be called every time the card is 
	// removed and reinserted
	while (!FAT16Init());
  	
	CurrentTask = NewTask = 0 ;
	
	while(1)
	{
		PerformTask();				
	}
	
}


/**************************************************************************************
 I/O functions:
 **************************************************************************************/
void InitialIOPort(void)
{
	TRISD	&= 0xfffc ;			// Low 2 pins are Control Pins
}

void PMPInitial(void)
{
	PMCON	= 0x02E1 ;			// Setup the PMP
	PMMODE	= 0x0200 ;			// 8 bit mode; No delay cycle;
	PMAEN	= 0x0001 ;			// Use PMPEN, when you use C30 2.05
	PMADDR	= 0x0001 ;
	PMCON	|= 0x8000 ;
}


/**************************************************************************************
 Subroutines for the panel:
 **************************************************************************************/
void PowerOnLCD(void)
{
	LTPS$CS_N	= LOW ;
  	LTPS$RESET_N	= LOW ;
	
	//-- Reset wavform --
	Delay(1000) ;
	LTPS$RESET_N	= HIGH ;
	Delay(1000) ;	
	
  	LTPS$CS_N	= HIGH ;

	/****************************************************
	Panel registers:
	Register(0x01h), MODE_SEL1
	register(0x02h), MODE_SEL2
	register(0x03h), MODE_SEL3		//for CPU I/F
	register(0x04h), MODE_SEL4		//for SPI I/F
	register(0x05h), VCO_Mode	
	register(0x07h), VCOMH_CTRL	
	register(0x08h), VCOML_CTRL	
	register(0x09h), PWS_X		
	register(0x10h), PWS_Y		
	register(0x11h), PWE_X		
	register(0x12h), PWE_Y		
	register(0x18h), SRAM_POSITION_X
	register(0x19h), SRAM_POSITION_Y
	register(0x17h), SRAM_Control	
	/***************************************************/
}

void WriteLCD_Data(unsigned char DataByte)
{
	
	//PMADDR 	= 0x0001 ;
	PMDIN1 		= DataByte ;
}

void WriteLCD_Command(unsigned char RegAddress, unsigned char CommandByte)
{

	PMADDR 		= 0x0000 ;
	PMDIN1 		= RegAddress ;
	
	PMADDR 		= 0x0001 ;
	PMDIN1 		= CommandByte ;
}

void MovePenXY(unsigned char X, unsigned char Y)
{

  WriteLCD_Command(0x18, X);
  WriteLCD_Command(0x19, Y);  
}


/**************************************************************************************
 Peripheral functions:
 **************************************************************************************/
void ADC10_Initial(void)
{

 	AD1PCFG 	= 0xFFFE;		// AN0/RB0 is Analog , others are Digital;
 	AD1CON2 	= 0x0000;		// 0000_0000 0000_0000
						// Don't Scan, SMPI 00, 16W Buf, MUX A only,
						
 	AD1CON3 	= 0x1C70;		// 0001_1100 0111_0000
 						
 	AD1CON1 	= 0x20E4;		// 0b0010 0000 1110 0100 
						// Integer, Auto-convert, Sample immed.
						
 	AD1CSSL 	= 0x0000;		// no scan input selected .......
 
	AD1CHS 		= 0x0000;		// 0000_0000 0000_0000
						// MUX A Ch0 Pos, VR- Neg

	IEC0bits.AD1IE 	= 0 ;			// Disable AD interrupt
	
	IPC3bits.AD1IP 	= 0 ;			// Set Priority to 0
	
 	AD1CON1bits.ADON = 1;			// Turn ADC ON

}

unsigned int ReadAD(void)
{
	AD1CON1bits.DONE = 0;
 	while(!AD1CON1bits.DONE);
 	return(ADC1BUF0) ;
}

void CheckTask(void)
{
	
 	unsigned int ADRes;
 	
 	ADRes 		= ReadAD();
 	
 	if(ADRes>=0 && ADRes<0x40)
 		NewTask = 0;
 		
 	else if(ADRes>=0x50 && ADRes<0x90)
 		NewTask = 1;
 		
 	else if(ADRes>=0xA0 && ADRes<0xE0)
 		NewTask = 2;
 		
 	else if(ADRes>=0xF0 && ADRes<0x130)
 		NewTask = 3;
 		
 	else if(ADRes>=0x140 && ADRes<0x180)
 		NewTask = 4;
 		
 	else if(ADRes>=0x190 && ADRes<0x1D0)
 		NewTask = 5;
 		
 	else if(ADRes>=0x1E0 && ADRes<0x220)
 		NewTask = 6;
 		
 	else if(ADRes>=0x230 && ADRes<0x270)
 		NewTask = 7;
 		
 	else if(ADRes>=0x280 && ADRes<0x2C0)
 		NewTask = 8;
 		
 	else if(ADRes>=0x2D0 && ADRes<0x310)
 		NewTask = 9;
 		
 	else if(ADRes>=0x320 && ADRes<0x360)
 		NewTask = 10;
 		
 	else if(ADRes>=0x370 && ADRes<0x3E0)
 		NewTask = 11;
 		
 	else if(ADRes>=0x3F0 && ADRes<=0x3FF)
 		NewTask = MaxTask;

}


void PerformTask(void)
{
	
  unsigned char 	x, y, Loop, Rdata, Gdata, Bdata;
  unsigned int  	ImagePt;
  
  FILE			*file_ptr;		// The file_ptr to the file object
  
  BITMAPFILEHEADER	Bitmapfileheader; 
  
  // Name of the file to create
  const char *fileName[] = {
  			    "dummy", "dummy",
  			    "im1.bmp", "im2.bmp", "im3.bmp", "im4.bmp", "im5.bmp", 
			    "im6.bmp", "im7.bmp", "im8.bmp", "im9.bmp", "im10.bmp"
			   };


  switch( CurrentTask )
  {
	
	// ---------------- R ----------------
	case 0:
	
		LTPS$CS_N  = LOW ;
		MovePenXY(0x00, 0x00);
		
		for(x=LTPS$XStart; x<LTPS$XEnd; x++)
		{
			for(y=LTPS$YStart; y<LTPS$YEnd; y++)
			{
				WriteLCD_Data(0xF8) ;		// R
				WriteLCD_Data(0x00) ;
				
				//WriteLCD_Data(0x07) ;		// G
				//WriteLCD_Data(0xE0) ;
				
				//WriteLCD_Data(0x00) ;		// B
				//WriteLCD_Data(0x1F) ;
			}
		}
		LTPS$CS_N  = HIGH ;
		
		break;
			

	// ---------------- Pattern (Rainbow) ----------------
	case 1:
		
		LTPS$CS_N  = LOW ;
		MovePenXY(0x00, 0x00);
			
		for(Loop=0; Loop<16; Loop+=2)
		{
			for(x=0; x<20; x++)
			{
				for(y=LTPS$YStart; y<LTPS$YEnd; y++)
				{
					WriteLCD_Data(TPattern[Loop]) ;
					WriteLCD_Data(TPattern[Loop+1]) ;
				}
			}
		}
		LTPS$CS_N  = HIGH ;
		
		break;
			

	// ---------------- Read images from SD card ----------------
	case 2:
	case 3:
	case 4:
	case 5:
	case 6:
	case 7:
	case 8:
	case 9:
	case 10:
	case 11:			
	
		if ((file_ptr = fopenpgm(fileName[CurrentTask], "r")) != NULL)
		{
			// Check the files if BMP format
			fread(Bitmapfileheader.Headerbuffer, 1, 54, file_ptr);
			
			if (Bitmapfileheader.bfType == 0x4D42)	// Check if BMP.
			{
        	
				LTPS$CS_N	= LOW ;
				
				MovePenXY(0x00, 0x00);
        			
				for(x=0; x<16; x++)
				{
					// For efficient consideration:
					// Read 8 row one time.
					// 160(Pixel) * 3(Byte) * 8(Row) = 3840(Byte)
					// So read 128/8=16 time.
					fread(RdBuffer, 1, 3840, file_ptr);
					
					for(ImagePt=0; ImagePt<3840; ImagePt+=3)
					{
						Bdata = RdBuffer[ImagePt];
						Gdata = RdBuffer[ImagePt+1];
						Rdata = RdBuffer[ImagePt+2];
						
						// 3 bytes data are packed into 2 bytes.
						// Wrong :
						/*
						Rdata = ((Rdata<<2) & 0xF8) |
						        ((Gdata>>3) & 0x07) ;
						        
						Bdata = ((Gdata<<5) & 0xE0) |
							((Bdata>>1) & 0x1F) ;
						*/
						
						// Trunk lower bits directly
						//asm("nop");		// debug point
						WriteLCD_Data( (Rdata & 0xF8) | (Gdata >> 5) ) ;
						WriteLCD_Data( ((Gdata << 3) & 0xE0) | ( Bdata >> 3) ) ;					
					}
				}
				LTPS$CS_N	= HIGH ;
			}  // End of if (Bitmapfileheader.bfType == 0x4D42)
		}
		fclose (file_ptr);
		
		break;
			
				
	default :
		break;
		

  }	// End of switch( CurrentTask )
	
	
	
  if( NewTask == MaxTask )
  {
  	// Auto Run
  	if( CurrentTask< MaxTask )	// Check boundary
  		CurrentTask ++;
  	else
  		CurrentTask = 0;
  		
  	WaitNSec();
  	CheckTask();			// In order to change NewTask.
  	
  }
  else
  {
	while( CurrentTask == NewTask )
	{		
  		CheckTask();
  	}
  
	CurrentTask = NewTask ;
  }
		
}


void Timer32Init(void)
{
    //IFS0bits.T2IF = 0;			// clear IF bit //
    //IPC1bits.T2IP = 0;			// assigning Interrupt Priority //
    IEC0bits.T2IE 	= 0;			// Interrupt Enable /Disable //
   
    PR2   		= 0x0000; 		// Assigning Period to Timer2 & 3
    PR3   		= 0x0200;
    
    T2CON 		= 0x2008;		// TimerOff, 1:1, T32, IntClk.
    						// 0b 0010_0000 0011_1000
}


void WaitNSec(void)
{
	
	TMR2		= 0;			// Reset Timer2 & 3 to 0x0000 //
	TMR3HLD		= 0;
	IFS0bits.T3IF	= 0;

	T2CON		|=0x8000;		// Timer2 On

	while(!IFS0bits.T3IF);
	
	T2CON &=0x7FFF;				// Timer2 Off
}

/**************************************************************************************
 ISR:
 **************************************************************************************/
/*
void _ISR _ADCInterrupt(void)
{

	Flags.ADC_DONE 		= 1 ;
	IFS0bits.ADIF 		= 0 ;
	MyADC 			= ADCBUF0 ;
}
*/


/**************************************************************************************
 Misc:
 **************************************************************************************/
void Delay(int value)
{
	
	for(;value>0;value--);
}






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -