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