天天看點

STM32F767 FSMC驅動8位LCD顯示屏

STM32F767 FSMC驅動8位LCD顯示屏

ili9342_lcd.c:
#include "ili9342_lcd.h"
#include "stdlib.h"
#include "ili9342_font.h" 
#include "usart.h"	 
#include "delay.h"	 

SRAM_HandleTypeDef SRAM_Handler;    //SRAM句柄(用于控制LCD)
//LCD的畫筆顔色和背景色	   
u32 POINT_COLOR=0xFF000000;		//畫筆顔色
u32 BACK_COLOR =0xFFFFFFFF;  	//背景色 
  
//管理LCD重要參數
//預設為豎屏
_lcd_dev lcddev;




void LCD_WR_REG(uint8_t regval)
{   
	regval=regval;
	LCD->LCD_REG=regval;
}


//寫LCD資料
//data:要寫入的值
void LCD_WR_DATA_8BIT(uint8_t data)
{	  
	data=data;
	LCD->LCD_RAM=data;
}


//讀LCD資料
//傳回值:讀到的值
uint8_t LCD_RD_DATA(void)
{
	uint8_t ram;			//防止被優化
	ram=LCD->LCD_RAM;	
	return ram;	 
}


//讀取液晶ID
uint16_t LCD_GET_ID(void)
{
	uint16_t id=0;
	LCD_WR_REG(0xD3);
//	
	LCD_RD_DATA();
	LCD_RD_DATA();
	
	//高位
	id|=LCD_RD_DATA();
	id<<=8;
	//低位
	id|=LCD_RD_DATA();
	 
	return id;
	
}


void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
	
		LCD_WR_REG(0x2a);//列位址設定
		LCD_WR_DATA_8BIT(x1);
		LCD_WR_DATA_8BIT(x2);
		LCD_WR_REG(0x2b);//行位址設定
		LCD_WR_DATA_8BIT(y1);
		LCD_WR_DATA_8BIT(y2);
		LCD_WR_REG(0x2c);//儲存器寫
	
}



void LCD_SetCursor(u16 Xpos, u16 Ypos)
{	 	    
	LCD_WR_REG(0x2A); 
	LCD_WR_DATA_8BIT(Xpos); 	 
	LCD_WR_REG(0x2B); 
	LCD_WR_DATA_8BIT(Ypos);
	LCD_WR_REG(0x2C); 
} 		 

void LCD_DrawPoint(u16 x,u16 y)
{
	LCD_Address_Set(x,y,x,y);
//	LCD->LCD_RAM=POINT_COLOR>>8;
//	LCD->LCD_RAM=POINT_COLOR;
//	LCD_SetCursor(x,y);		//設定光标位置 
	LCD->LCD_REG=0x2C;//開始寫入GRAM
		LCD->LCD_RAM=POINT_COLOR>>8;
	LCD->LCD_RAM=POINT_COLOR;
}

void LCD_Fast_DrawPoint(u16 x,u16 y,u32 color)
{
	LCD_WR_REG(0x2A); 
	LCD_WR_DATA_8BIT(x>>8);
	LCD_WR_DATA_8BIT(x&0XFF);  			 
	LCD_WR_REG(0x2B); 
	LCD_WR_DATA_8BIT(y>>8);
	LCD_WR_DATA_8BIT(y&0XFF); 
	LCD->LCD_REG=0x2C;//開始寫入GRAM
	LCD->LCD_RAM=color>>8;
	LCD->LCD_RAM=color;
}


//當mdk -O1時間優化時需要設定
//延時i
void opt_delay(u8 i)
{
	while(i--);
}



//讀取個某點的顔色值	 
//x,y:坐标
//傳回值:此點的顔色
u32 LCD_ReadPoint(u16 x,u16 y)
{
 	u16 r=0,g=0,b=0,rgb=0;
	LCD_Address_Set(x, y, x, y);
	LCD_WR_REG(0X2E);     		 				    
 	r=LCD_RD_DATA();								//dummy Read	   
 	r=LCD_RD_DATA();  		  						//實際坐标顔色
//	printf("r=%X\r\n",r);

	g=LCD_RD_DATA();
//	printf("g=%X\r\n",g);

	b=LCD_RD_DATA(); 
//	printf("b=%X\r\n",b);
	
	r=(r<<8)&0xF800;
	g=(g<<3)&0x07E0;
	b=(b>>3)&0x001F;
	rgb=r|g|b;	
	return rgb;	
}	









//配置MPU的region(SRAM區域為透寫模式)
void LCD_MPU_Config(void)
{	
	MPU_Region_InitTypeDef MPU_Initure;

	HAL_MPU_Disable();							//配置MPU之前先關閉MPU,配置完成以後在使能MPU	
	//外部SRAM為region0,大小為2MB,此區域可讀寫
	MPU_Initure.Enable=MPU_REGION_ENABLE;	    //使能region
	MPU_Initure.Number=LCD_REGION_NUMBER;		//設定region,外部SRAM使用的region0
	MPU_Initure.BaseAddress=LCD_ADDRESS_START;	//region基位址
	MPU_Initure.Size=LCD_REGION_SIZE;			//region大小
	MPU_Initure.SubRegionDisable=0X00;
	MPU_Initure.TypeExtField=MPU_TEX_LEVEL0;
	MPU_Initure.AccessPermission=MPU_REGION_FULL_ACCESS;	//此region可讀寫
	MPU_Initure.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;	//允許讀取此區域中的指令
	MPU_Initure.IsShareable=MPU_ACCESS_NOT_SHAREABLE;
	MPU_Initure.IsCacheable=MPU_ACCESS_NOT_CACHEABLE;
	MPU_Initure.IsBufferable=MPU_ACCESS_BUFFERABLE;
	HAL_MPU_ConfigRegion(&MPU_Initure);
	HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);     //開啟MPU
}
//SRAM底層驅動,時鐘使能,引腳配置設定
//此函數會被HAL_SRAM_Init()調用
//hsram:SRAM句柄
void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram)
{
    GPIO_InitTypeDef GPIO_Initure;
	
	__HAL_RCC_FMC_CLK_ENABLE();				//使能FMC時鐘
	__HAL_RCC_GPIOD_CLK_ENABLE();			//使能GPIOD時鐘
	__HAL_RCC_GPIOE_CLK_ENABLE();			//使能GPIOE時鐘
	
	//初始化PD0,1,4,5,7,8,9,10,13,14,15
	GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7|GPIO_PIN_8|\
                     GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
	GPIO_Initure.Mode=GPIO_MODE_AF_PP; 		//推挽複用
	GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
	GPIO_Initure.Speed=GPIO_SPEED_HIGH;		//高速
	GPIO_Initure.Alternate=GPIO_AF12_FMC;	//複用為FMC
	HAL_GPIO_Init(GPIOD,&GPIO_Initure);     //初始化
	
	//初始化PE7,8,9,10,11,12,13,14,15
	GPIO_Initure.Pin=GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|\
                     GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
	HAL_GPIO_Init(GPIOE,&GPIO_Initure);
}
        
//初始化lcd
//該初始化函數可以初始化各種型号的LCD(詳見本.c檔案最前面的描述)
void ILI9342_LCD_Init(void)
{ 	  
    GPIO_InitTypeDef GPIO_Initure;
	FMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim;
    FMC_NORSRAM_TimingTypeDef FSMC_WriteTim;
	
	
    
    __HAL_RCC_GPIOB_CLK_ENABLE();			//開啟GPIOB時鐘
    GPIO_Initure.Pin=GPIO_PIN_5;            //PB5,背光控制
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽輸出
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOB,&GPIO_Initure); 
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);	//PB5置1 
	

    
    LCD_MPU_Config();                       //使能MPU保護LCD區域
    SRAM_Handler.Instance=FMC_NORSRAM_DEVICE;       
    SRAM_Handler.Extended=FMC_NORSRAM_EXTENDED_DEVICE;       
    
    SRAM_Handler.Init.NSBank=FMC_NORSRAM_BANK1;     //使用NE1
    SRAM_Handler.Init.DataAddressMux=FMC_DATA_ADDRESS_MUX_DISABLE; //不複用資料線
    SRAM_Handler.Init.MemoryType=FMC_MEMORY_TYPE_SRAM;   //SRAM
    SRAM_Handler.Init.MemoryDataWidth=FMC_NORSRAM_MEM_BUS_WIDTH_8; //8位資料寬度
    SRAM_Handler.Init.BurstAccessMode=FMC_BURST_ACCESS_MODE_DISABLE; //是否使能突發通路,僅對同步突發存儲器有效,此處未用到
    SRAM_Handler.Init.WaitSignalPolarity=FMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的極性,僅在突發模式通路下有用
    SRAM_Handler.Init.WaitSignalActive=FMC_WAIT_TIMING_BEFORE_WS;   //存儲器是在等待周期之前的一個時鐘周期還是等待周期期間使能NWAIT
    SRAM_Handler.Init.WriteOperation=FMC_WRITE_OPERATION_ENABLE;    //存儲器寫使能
    SRAM_Handler.Init.WaitSignal=FMC_WAIT_SIGNAL_DISABLE;           //等待使能位,此處未用到
    SRAM_Handler.Init.ExtendedMode=FMC_EXTENDED_MODE_ENABLE;        //讀寫使用不同的時序
    SRAM_Handler.Init.AsynchronousWait=FMC_ASYNCHRONOUS_WAIT_DISABLE;//是否使能同步傳輸模式下的等待信号,此處未用到
    SRAM_Handler.Init.WriteBurst=FMC_WRITE_BURST_DISABLE;           //禁止突發寫
    SRAM_Handler.Init.ContinuousClock=FMC_CONTINUOUS_CLOCK_SYNC_ASYNC;
    
    //FSMC讀時序控制寄存器
    FSMC_ReadWriteTim.AddressSetupTime=0x11; // 0x11  //位址建立時間(ADDSET)為17個HCLK 1/216M=4.6ns*17=78ns
    FSMC_ReadWriteTim.AddressHoldTime=0x00;
    FSMC_ReadWriteTim.DataSetupTime=0x55;   //  0x55  //資料儲存時間(DATAST)為85個HCLK	=4.6*85=391ns
    FSMC_ReadWriteTim.AccessMode=FMC_ACCESS_MODE_A; //模式A
    //FSMC寫時序控制寄存器
    FSMC_WriteTim.AddressSetupTime=0x15;   // 0x15    //位址建立時間(ADDSET)為21個HCLK=96ns
    FSMC_WriteTim.AddressHoldTime=0x00;
    FSMC_WriteTim.DataSetupTime=0x15;    // 0x15    //資料儲存時間(DATAST)為4.6ns*21個HCLK=96ns
    FSMC_WriteTim.AccessMode=FMC_ACCESS_MODE_A;     //模式A
	HAL_SRAM_Init(&SRAM_Handler,&FSMC_ReadWriteTim,&FSMC_WriteTim);		
 	delay_ms(50); // delay 50 ms 
	
	//嘗試9342 ID的讀取					   
	lcddev.id=LCD_GET_ID();	//dummy read 	
	lcddev.width=320;
	lcddev.height=240;
	if(lcddev.id==0x9342)
	{
		LCD_WR_REG(0xC8);       //Set EXTC
		LCD_WR_DATA_8BIT(0xFF);
		LCD_WR_DATA_8BIT(0x93);
		LCD_WR_DATA_8BIT(0x42);

		LCD_WR_REG(0xb6);  
		LCD_WR_DATA_8BIT(0x0a);
		LCD_WR_DATA_8BIT(0xE0);//SS GS

		LCD_WR_REG(0x36); //Memory Access Control
		LCD_WR_DATA_8BIT(0x08); //MY,MX,MV,ML,BGR,MH

		LCD_WR_REG(0x3A); //Pixel Format Set
		LCD_WR_DATA_8BIT(0x55); //DPI [2:0],DBI [2:0]

		LCD_WR_REG(0xC0); //Power Control 1
		LCD_WR_DATA_8BIT(0x12); //VRH[5:0]
		LCD_WR_DATA_8BIT(0x12); //VC[3:0]

		LCD_WR_REG(0xC1);  //Power Control 2
		LCD_WR_DATA_8BIT(0x04); //02,SAP[2:0],BT[3:0]VGL=12V,VGH=15V

		LCD_WR_REG(0xC5); //VCOM
		LCD_WR_DATA_8BIT(0XFD); //C8++

		LCD_WR_REG(0xB1);      
		LCD_WR_DATA_8BIT(0x00);     
		LCD_WR_DATA_8BIT(0x1B);

		LCD_WR_REG(0xB4);      
		LCD_WR_DATA_8BIT(0x02);
		//	//*****************GAMMA*****************  
		LCD_WR_REG(0xE0);
		LCD_WR_DATA_8BIT(0x00);//P01-VP63   
		LCD_WR_DATA_8BIT(0x05);//P02-VP62   
		LCD_WR_DATA_8BIT(0x08);//P03-VP61   
		LCD_WR_DATA_8BIT(0x04);//P04-VP59   
		LCD_WR_DATA_8BIT(0x13);//P05-VP57   
		LCD_WR_DATA_8BIT(0x0A);//P06-VP50   
		LCD_WR_DATA_8BIT(0x34);//P07-VP43   
		LCD_WR_DATA_8BIT(0x8A);//P08-VP27,36
		LCD_WR_DATA_8BIT(0x46);//P09-VP20   
		LCD_WR_DATA_8BIT(0x07);//P10-VP13   
		LCD_WR_DATA_8BIT(0x0E);//P11-VP6    
		LCD_WR_DATA_8BIT(0x0A);//P12-VP4    
		LCD_WR_DATA_8BIT(0x1B);//P13-VP2    
		LCD_WR_DATA_8BIT(0x1D);//P14-VP1    
		LCD_WR_DATA_8BIT(0x0F);//P15-VP0    

		LCD_WR_REG(0xE1);
		LCD_WR_DATA_8BIT(0x0C);//P01
		LCD_WR_DATA_8BIT(0x05);//P02
		LCD_WR_DATA_8BIT(0x08);//P03
		LCD_WR_DATA_8BIT(0x04);//P04
		LCD_WR_DATA_8BIT(0x13);//P05
		LCD_WR_DATA_8BIT(0x0A);//P06
		LCD_WR_DATA_8BIT(0x34);//P07
		LCD_WR_DATA_8BIT(0x8A);//P08
		LCD_WR_DATA_8BIT(0x46);//P09
		LCD_WR_DATA_8BIT(0x07);//P10
		LCD_WR_DATA_8BIT(0x0E);//P11
		LCD_WR_DATA_8BIT(0x0A);//P12
		LCD_WR_DATA_8BIT(0x1B);//P13
		LCD_WR_DATA_8BIT(0x1D);//P14
		LCD_WR_DATA_8BIT(0x0F);//P15

		LCD_WR_REG(0x21); 

		//********Window(視窗/位址)****************
		LCD_WR_REG(0x2A); //320
		LCD_WR_DATA_8BIT(0x00);
		LCD_WR_DATA_8BIT(0x00);
		LCD_WR_DATA_8BIT(0x01);
		LCD_WR_DATA_8BIT(0x3F);

		LCD_WR_REG(0x2B); //240
		LCD_WR_DATA_8BIT(0x00);
		LCD_WR_DATA_8BIT(0x00);
		LCD_WR_DATA_8BIT(0x00);
		LCD_WR_DATA_8BIT(0xEF);
		//****************************** 
		LCD_WR_REG(0x11);//Exit Sleep
		delay_ms(120);
		LCD_WR_REG(0x29);//Display On
		LCD_WR_REG(0x2c); 
		LCD_Clear(WHITE);
	}

	
   
	
}  


/******************************************************************************
      函數說明:LCD清屏函數
      入口資料:無
      傳回值:  無
******************************************************************************/
void LCD_Clear(u16 Color)
{
	u16 i,j;  	
	LCD_SetCursor(0,0);
    for(i=0;i<lcddev.width;i++)
	 {
	  for (j=0;j<lcddev.height;j++)
	   	{
        	LCD_WR_DATA_8BIT(Color>>8);
			LCD_WR_DATA_8BIT(Color);
	    }

	  }
}


/******************************************************************************
      函數說明:在指定區域填充顔色
      入口資料:xsta,ysta   起始坐标
                xend,yend   終止坐标
      傳回值:  無
******************************************************************************/
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{          
	u16 i,j; 
	LCD_Address_Set(xsta,ysta,xend,yend);      //設定光标位置 
	for(i=xsta;i<xend;i++)
	{													   	 	
		for(j=ysta;j<yend;j++)
		{
			LCD_WR_REG(0x2A); 
			LCD_WR_DATA_8BIT(i>>8);
			LCD_WR_DATA_8BIT(i&0XFF);  			 
			LCD_WR_REG(0x2B); 
			LCD_WR_DATA_8BIT(j>>8);
			LCD_WR_DATA_8BIT(j&0XFF); 
			LCD->LCD_REG=0x2C;//開始寫入GRAM
			LCD->LCD_RAM=color>>8;
			LCD->LCD_RAM=color;
			
		}
			    
	} 					  	    
}



           
ILI9342.h:
#ifndef __ILI9342_LCD_H
#define __ILI9342_LCD_H
#include "sys.h"	 
#include "stdlib.h" 



//LCD重要參數集
typedef struct  
{		 	 
	u16 width;			//LCD 寬度
	u16 height;			//LCD 高度
	u16 id;				//LCD ID
	u8  dir;			//橫屏還是豎屏控制:0,豎屏;1,橫屏。	
	u16	wramcmd;		//開始寫gram指令
	u16 setxcmd;		//設定x坐标指令
	u16 setycmd;		//設定y坐标指令 
}_lcd_dev; 	  

//LCD參數
extern _lcd_dev lcddev;	//管理LCD重要參數
//LCD的畫筆顔色和背景色	   
extern u32  POINT_COLOR;//預設紅色    
extern u32  BACK_COLOR; //背景顔色.預設為白色



//LCD MPU保護參數
#define LCD_REGION_NUMBER		MPU_REGION_NUMBER0		//LCD使用region0
#define LCD_ADDRESS_START		(0X60000000)			//LCD區的首位址
#define LCD_REGION_SIZE			MPU_REGION_SIZE_256MB   //LCD區大小

//	 
//-----------------MCU屏 LCD端口定義---------------- 
//LCD背光	PB5	
#define LCD_LED(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET)) 	    
//LCD位址結構體
typedef struct
{
	__IO uint8_t LCD_REG;
	__IO uint8_t LCD_RAM;
} LCD_TypeDef;

//使用NOR/SRAM的 Bank1.sector4,位址位HADDR[27,26]=11 A18作為資料指令區分線 
//注意設定時STM32内部會右移一位對其! 			    
//#define LCD_BASE        ((u32)(0x60000000 | 0x0007FFFE))
#define LCD_BASE          ((uint32_t)(0x60000000 | 0x0003ffff))

#define LCD             ((LCD_TypeDef *) LCD_BASE)
//
	 




//畫筆顔色
#define WHITE         	 0xFFFF
#define BLACK         	 0x0000	  
#define BLUE         	 0x001F  
#define BRED             0XF81F
#define GRED 			 0XFFE0
#define GBLUE			 0X07FF
#define RED           	 0xF800
#define MAGENTA       	 0xF81F
#define GREEN         	 0x07E0
#define CYAN          	 0x7FFF
#define YELLOW        	 0xFFE0
#define BROWN 			 0XBC40 //棕色
#define BRRED 			 0XFC07 //棕紅色
#define GRAY  			 0X8430 //灰色
//GUI顔色

#define DARKBLUE      	 0X01CF	//深藍色
#define LIGHTBLUE      	 0X7D7C	//淺藍色  
#define GRAYBLUE       	 0X5458 //灰藍色
//以上三色為PANEL的顔色 
 
#define LIGHTGREEN     	 0X841F //淺綠色
//#define LIGHTGRAY        0XEF5B //淺灰色(PANNEL)
#define LGRAY 			 0XC618 //淺灰色(PANNEL),窗體背景色

#define LGRAYBLUE        0XA651 //淺灰藍色(中間層顔色)
#define LBBLUE           0X2B12 //淺棕藍色(選擇條目的反色)
	    															  


void LCD_WR_REG(uint8_t regval);
void LCD_WR_DATA_8BIT(uint8_t data);
uint8_t LCD_RD_DATA(void);
uint16_t LCD_GET_ID(void);
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2);
void LCD_SetCursor(u16 Xpos, u16 Ypos);
void LCD_DrawPoint(u16 x,u16 y);
void LCD_Fast_DrawPoint(u16 x,u16 y,u32 color);
void opt_delay(u8 i);
u32 LCD_ReadPoint(u16 x,u16 y);
void LCD_MPU_Config(void);
void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram);
void ILI9342_LCD_Init(void);
void LCD_Clear(u16 Color);

void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color);
void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color);
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color);
void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color);


void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode);						//顯示一個字元
void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size);  						//顯示一個數字
void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode);				//顯示 數字
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p);		//顯示一個字元串,12/16字型
u32 LCD_Pow(u8 m,u8 n);




void LCD_DrawLine2(u16 x1, u16 y1, u16 x2, u16 y2, u16 size, u16 color);
void gui_circle(int xc, int yc,u16 c,int r, int fill);
void _draw_circle_8(int xc, int yc, int x, int y, u16 c);







#endif