您的位置 首页 制造

浅谈STM32的FSMC的TFT笔记

浅谈STM32的FSMC的TFT笔记-FSMC _Bank 用来选择外接存储器的地址,FSMC所控制的外存储器所映射的地址是0x6000 0000 ~ 0x9fff ffff,其中属于NOR FLASH 的是0x6000 0000 ~ 0x6fff ffff ,然后这部分的地址空间又被分为四份,每份64MB, 编号是BANK1 ~ BANK 4 ,每个BANK 都有一个片选引脚。

1、FSMC初初了解:

FSMC 包含4个模块:

(1)AHB接口(包含FSMC装备寄存器

(2)NOR闪存和PSRAM操控器(驱动LCD的时分LCD就好像一个PSRAM的里边只要2个16位的存储空间,一个是DATA RAM 一个是CMD RAM)

(3)NAND闪存和PC卡操控器

(4)外部设备接口

咱们驱动TFT很明显用的是第二个模块:NOR闪存。

2、FSMC的外设地址挑选

FSMC _Bank 用来挑选外接存储器的地址,FSMC所操控的外存储器所映射的地址是0x6000 0000 ~ 0x9fff ffff

其间归于NOR FLASH 的是0x6000 0000 ~ 0x6fff ffff ,然后这部分的地址空间又被分为四份,每份64MB, 编号是BANK1 ~ BANK 4 ,每个BANK 都有一个片选引脚。

而这四个分存储块的片选,则运用NE[4:1]来挑选。数据线/地址线/操控线是同享的。

NE1 ->Bank1   NE2->Bank2  NE3->Bank3  NE4->Bank4

榜首块:6000 0000h–63ff ffffh 

第二块:6400 0000h–67ff ffffh

第三块:6800 0000h–6bff ffffh

第四块:6c00 0000h–6fff ffffh

3、FSMC 驱动LCD

FSMC供给了一切的LCD操控器的信号:

FSMC_D[16:0]:16bit的数据总线

FSMC NEx:分配给NOR的256M,再分为4个区,每个区用来分配一个外设,这四个外设的片选分为是NE1-NE4,对应的引脚为:PD7—NE1,PG9—NE2,PG10-NE3,PG12—NE4

FSMC NOE:输出使能,衔接LCD的RD脚。

FSMC NWE:写使能,衔接LCD的RW脚。

FSMC Ax:用在LCD显现RAM和寄存器之间进行挑选的地址线,即该线用于挑选LCD的RS脚,该线可用地址线的恣意一根线,规模:FSMC_A[25:0]。

正如咱们操作12864的指令/数据挑选端口RS相同,关于FSMC驱动TFT :RS = 0时,表明读写寄存器;RS = 1表明读写数据RAM。

4、GPIO端口装备

由所以运用FSMC来驱动TFT的,所以除了背光用的PD13和复位用的PC1要设置为通用推挽输出之外,其他引脚都有必要设置为复用推挽输出。但是,很奇怪的是。当我装备好PD13时,我发现程序下载进去后是一片乌黑的,后来一再查看是背光的PD13的问题。有必要把PD13置高才能够亮,不然默许低电平,便是一片黑了。

5、 详细程序

/*******************************************************************************

* FuncTIon Name  : Lcd_ConfiguraTIon

* DescripTIon    : Configures LCD Control lines

* Input          : None

* Output         : None

* Return         : None

* AttenTIon  : None

*******************************************************************************/

static void LCD_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

/* Enable GPIOD and GPIOE clocks */

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE);  

/* PE.00(D0), PE.01(D1), PE.02(D2), PE.03(D3), PE.04(D4), PE.05(D5), PE.06(D6), PE.07(D7), PE.08(D8)

PE.09(D9), PE.10(D10), PE.11(D11), PE.12(D12), PE.13(D13), PE.14(D14), PE.15(D15)   */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOE, &GPIO_InitStructure);

/* PD.13(RS), PD.14(WR), PD.15(RD) */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOD, &GPIO_InitStructure);

/* PD.12(CS)*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOD, &GPIO_InitStructure);

}

/*******************************************************************************

* Function Name  : LCD_WriteReg

* Description    : LCD操控器寄存器地址

* Input          : – index: 寄存器地址

* Output         : None

* Return         : None

* Attention  : None

*******************************************************************************/

__inline void LCD_WriteIndex(uint16_t index)

{

Clr_Rs;

Set_nRd;

GPIOE->ODR = index;  /* GPIO_Write(GPIOE,index); */

Clr_nWr;

Set_nWr;

}

/*******************************************************************************

* Function Name  : LCD_WriteReg

* Description    : LCD寄存器数据

* Input          : – index: 寄存器数据

* Output         : None

* Return         : None

* Attention  : None

*******************************************************************************/

__inline void LCD_WriteData(uint16_t data)

{

Set_Rs;

GPIOE->ODR = data;  /* GPIO_Write(GPIOE,data); */

Clr_nWr;

Set_nWr;

}

/*******************************************************************************

* Function Name  : LCD_ReadData

* Description    : 读取操控器数据

* Input          : None

* Output         : None

* Return         : 回来读取到的数据

* Attention  : None

*******************************************************************************/

__inline uint16_t LCD_ReadData(void)

uint16_t value;

Set_Rs;

Set_nWr;

Clr_nRd;

GPIOE->CRH = 0x44444444;

GPIOE->CRL = 0x44444444;

value = GPIOE->IDR;

value = GPIOE->IDR;

GPIOE->CRH = 0x33333333;

GPIOE->CRL = 0x33333333;

Set_nRd;

return value;

}

__inline void LCD_WriteReg(uint16_t LCD_Reg,uint16_t LCD_RegValue)

/* Write 16-bit Index, then Write Reg */  

Clr_Cs;

LCD_WriteIndex(LCD_Reg);         

/* Write 16-bit Reg */

LCD_WriteData(LCD_RegValue);  

Set_Cs; 

}

__inline uint16_t LCD_ReadReg(uint16_t LCD_Reg)

{

uint16_t LCD_RAM;

/* Write 16-bit Index (then Read Reg) */

Clr_Cs;

LCD_WriteIndex(LCD_Reg);

/* Read 16-bit Reg */

LCD_RAM = LCD_ReadData();       

Set_Cs;

return LCD_RAM;

}

static void LCD_SetCursor( uint16_t Xpos, uint16_t Ypos )

{

#if  ( DISP_ORIENTATION == 90 ) || ( DISP_ORIENTATION == 270 )

uint16_t temp = Xpos;

Xpos = Ypos;

Ypos = ( MAX_X – 1 ) – temp;  

#elif  ( DISP_ORIENTATION == 0 ) || ( DISP_ORIENTATION == 180 )

#endif

LCD_WriteReg(0x004e, Xpos );      

LCD_WriteReg(0x004f, Ypos );          

}

static void delay_ms(uint16_t ms)    

uint16_t i,j; 

for( i = 0; i < ms; i++ )

for( j = 0; j < 1141; j++ );

}

void LCD_Initializtion(void)

{

LCD_Configuration();

// DeviceCode = LCD_ReadReg(0x0000);

/* 读取屏ID */

LCD_WriteReg(0x0000,0x0001);    delay_ms(50);   /* 翻开晶振 ,内部晶振500k*/

LCD_WriteReg(0x0003,0xA8A4);    delay_ms(50);   

LCD_WriteReg(0x000C,0x0000);    delay_ms(50);   

LCD_WriteReg(0x000D,0x080C);    delay_ms(50);   

LCD_WriteReg(0x000E,0x2B00);    delay_ms(50);   

LCD_WriteReg(0x001E,0x00B0);    delay_ms(50);   

LCD_WriteReg(0x0001,0x2B3F);    delay_ms(50);   /* 驱动输出操控320*240 0x2B3F */

LCD_WriteReg(0x0002,0x0600);    delay_ms(50);

LCD_WriteReg(0x0010,0x0000);    delay_ms(50);

LCD_WriteReg(0x0011,0x6070);    delay_ms(50);   /* 界说数据格式 16位色 横屏 0x6070 */

LCD_WriteReg(0x0005,0x0000);    delay_ms(50);

LCD_WriteReg(0x0006,0x0000);    delay_ms(50);

LCD_WriteReg(0x0016,0xEF1C);    delay_ms(50);

LCD_WriteReg(0x0017,0x0003);    delay_ms(50);

LCD_WriteReg(0x0007,0x0133);    delay_ms(50);         

LCD_WriteReg(0x000B,0x0000);    delay_ms(50);

LCD_WriteReg(0x000F,0x0000);    delay_ms(50);   /* 扫描开端地址 */

LCD_WriteReg(0x0041,0x0000);    delay_ms(50);

LCD_WriteReg(0x0042,0x0000);    delay_ms(50);

LCD_WriteReg(0x0048,0x0000);    delay_ms(50);

LCD_WriteReg(0x0049,0x013F);    delay_ms(50);

LCD_WriteReg(0x004A,0x0000);    delay_ms(50);

LCD_WriteReg(0x004B,0x0000);    delay_ms(50);

LCD_WriteReg(0x0044,0xEF00);    delay_ms(50);

LCD_WriteReg(0x0045,0x0000);    delay_ms(50);

LCD_WriteReg(0x0046,0x013F);    delay_ms(50);

LCD_WriteReg(0x0030,0x0707);    delay_ms(50);

LCD_WriteReg(0x0031,0x0204);    delay_ms(50);

LCD_WriteReg(0x0032,0x0204);    delay_ms(50);

LCD_WriteReg(0x0033,0x0502);    delay_ms(50);

LCD_WriteReg(0x0034,0x0507);    delay_ms(50);

LCD_WriteReg(0x0035,0x0204);    delay_ms(50);

LCD_WriteReg(0x0036,0x0204);    delay_ms(50);

LCD_WriteReg(0x0037,0x0502);    delay_ms(50);

LCD_WriteReg(0x003A,0x0302);    delay_ms(50);

LCD_WriteReg(0x003B,0x0302);    delay_ms(50);

LCD_WriteReg(0x0023,0x0000);    delay_ms(50);

LCD_WriteReg(0x0024,0x0000);    delay_ms(50);

LCD_WriteReg(0x0025,0x8000);    delay_ms(50);

LCD_WriteReg(0x004f,0);        /* 行首址0 */

  LCD_WriteReg(0x004e,0); //列首址0

  }else if(DeviceCode==0x4531){

  LCD_WriteReg(0X00,0X0001);

  LCD_Delay(50);

  LCD_WriteReg(0X10,0X1628);

  LCD_WriteReg(0X12,0X000e);//0x0006

  LCD_WriteReg(0X13,0X0A39);

  LCD_Delay(10);

  LCD_WriteReg(0X11,0X0040);

  LCD_WriteReg(0X15,0X0050);

  LCD_Delay(40);

  LCD_WriteReg(0X12,0X001e);//16

  LCD_Delay(40);

  LCD_WriteReg(0X10,0X1620);

  LCD_WriteReg(0X13,0X2A39);

  LCD_Delay(10);

  LCD_WriteReg(0X01,0X0100);

  LCD_WriteReg(0X02,0X0300);

  LCD_WriteReg(0X03,0X1030);//改变方向的

  LCD_WriteReg(0X08,0X0202);

  LCD_WriteReg(0X0A,0X0008);

  LCD_WriteReg(0X30,0X0000);

  LCD_WriteReg(0X31,0X0402);

  LCD_WriteReg(0X32,0X0106);

  LCD_WriteReg(0X33,0X0503);

  LCD_WriteReg(0X34,0X0104);

  LCD_WriteReg(0X35,0X0301);

  LCD_WriteReg(0X36,0X0707);

  LCD_WriteReg(0X37,0X0305);

  LCD_WriteReg(0X38,0X0208);

  LCD_WriteReg(0X39,0X0F0B);

  LCD_WriteReg(0X41,0X0002);

  LCD_WriteReg(0X60,0X2700);

  LCD_WriteReg(0X61,0X0001);

  LCD_WriteReg(0X90,0X0210);

  LCD_WriteReg(0X92,0X010A);

  LCD_WriteReg(0X93,0X0004);

  LCD_WriteReg(0XA0,0X0100);

  LCD_WriteReg(0X07,0X0001);

  LCD_WriteReg(0X07,0X0021);

  LCD_WriteReg(0X07,0X0023);

  LCD_WriteReg(0X07,0X0033);

  LCD_WriteReg(0X07,0X0133);

  LCD_WriteReg(0XA0,0X0000);

  }

  LCD_Delay(5000);

  Set_LED;//点亮背光

  LCD_Clear(WHITE);

  }

  //清屏函数

  //Color:要清屏的填充色

  void LCD_Clear(u16 Color)

  {

  u32 index=0;

  LCD_SetCursor(0x00,0x0000);//设置光标方位

  LCD_WriteRAM_Prepare(); //开端写入GRAM

  for(index=0;index《76800;index++)

  {

  LCD_WR_DATA(Color); //向每个GRAM写入数据

  }

  }

  //在指定区域内填充指定色彩

  //区域巨细:

  // (xend-xsta)*(yend-ysta)

  void LCD_Fill(u8 xsta,u16 ysta,u8 xend,u16 yend,u16 color)

  {

  #if USE_HORIZONTAL //横屏

  u16 colortemp=POINT_COLOR;

  u16 ytemp=ysta;

  POINT_COLOR=color;

  for(;xsta《=xend;xsta++)

  {

  for(;ysta《=yend;ysta++)LCD_DrawPoint(xsta,ysta);

  ysta=ytemp;

  }

  POINT_COLOR=colortemp;

  #else //竖屏

  u32 n;

  //设置窗口

  LCD_WriteReg(R80, xsta); //水平方向GRAM开端地址

  LCD_WriteReg(R81, xend); //水平方向GRAM完毕地址

  LCD_WriteReg(R82, ysta); //笔直方向GRAM开端地址

  LCD_WriteReg(R83, yend); //笔直方向GRAM完毕地址

  LCD_SetCursor(xsta,ysta);//设置光标方位

  LCD_WriteRAM_Prepare(); //开端写入GRAM

  n=(u32)(yend-ysta+1)*(xend-xsta+1);

  while(n–){LCD_WR_DATA(color);}//显现所填充的色彩。

  //康复设置

  LCD_WriteReg(R80, 0x0000); //水平方向GRAM开端地址

  LCD_WriteReg(R81, (LCD_WIDTH-1)); //水平方向GRAM完毕地址

  LCD_WriteReg(R82, 0x0000); //笔直方向GRAM开端地址

  LCD_WriteReg(R83, (LCD_HEIGHT-1)); //笔直方向GRAM完毕地址

  #endif

  }

  //画线

  //x1,y1:起点坐标

  //x2,y2:结尾坐标

  void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)

  {

  u16 t;

  int xerr=0,yerr=0,delta_x,delta_y,distance;

  int incx,incy,uRow,uCol;

  delta_x=x2-x1; //核算坐标增量

  delta_y=y2-y1;

  uRow=x1;

  uCol=y1;

  if(delta_x》0)incx=1; //设置单步方向

  else if(delta_x==0)incx=0;//笔直线

  else {incx=-1;delta_x=-delta_x;} //结尾坐标小于开端坐标,反方向,将坐标从头定位为正坐标

  if(delta_y》0)incy=1;

  else if(delta_y==0)incy=0;//水平线

  else{incy=-1;delta_y=-delta_y;} //结尾坐标小于开端坐标,反方向,将坐标从头定位为正坐标

  if( delta_x》delta_y)distance=delta_x; //选取根本增量坐标轴

  else distance=delta_y;

  for(t=0;t《=distance+1;t++ )//画线输出

  {

  LCD_DrawPoint(uRow,uCol);//依据坐标画点

  xerr+=delta_x ; //X坐标增量

  yerr+=delta_y ; //Y坐标增量

  if(xerr》distance)

  {

  xerr-=distance;

  uRow+=incx;

  }

  if(yerr》distance)

  {

  yerr-=distance;

  uCol+=incy;

  }

  }

  }

  //画矩形

  void LCD_DrawRectangle(u8 x1, u16 y1, u8 x2, u16 y2)

  {

  LCD_DrawLine(x1,y1,x2,y1);

  LCD_DrawLine(x1,y1,x1,y2);

  LCD_DrawLine(x1,y2,x2,y2);

  LCD_DrawLine(x2,y1,x2,y2);

  }

  //在指定方位画一个指定巨细的圆

  //(x,y):中心点

  //r :半径

  void Draw_Circle(u8 x0,u16 y0,u8 r)

  {

  int a,b;

  int di;

  a=0;b=r;

  di=3-(r《《1); //判别下个点方位的标志

  while(a《=b)

  {

  LCD_DrawPoint(x0-b,y0-a); //3

  LCD_DrawPoint(x0+b,y0-a); //0

  LCD_DrawPoint(x0-a,y0+b); //1

  LCD_DrawPoint(x0-b,y0-a); //7

  LCD_DrawPoint(x0-a,y0-b); //2

  LCD_DrawPoint(x0+b,y0+a); //4

  LCD_DrawPoint(x0+a,y0-b); //5

  LCD_DrawPoint(x0+a,y0+b); //6

  LCD_DrawPoint(x0-b,y0+a);

  a++;

  //运用Bresenham算法画圆

  if(di《0){

  di +=4*a+6;

  }else{

  di+=10+4*(a-b);

  b–;

  }

  LCD_DrawPoint(x0+a,y0+b);

  }

  }

  //在指定方位显现一个字符

  //x:0~234

  //y:0~308

  //num:要显现的字符:“ ”—》“~”

  //size:字体巨细 12/16

  //mode:叠加方法(1)还对错叠加方法(0)

  void LCD_ShowChar(u8 x,u16 y,u8 num,u8 size,u8 mode)

  {

  #if USE_HORIZONTAL

  #define MAX_CHAR_POSX 312

  #define MAX_CHAR_POSY 232

  u8 temp;

  u8 pos,t;

  u16 x0=x;

  u16 colortemp=POINT_COLOR;

  if(x》MAX_CHAR_POSX||y》MAX_CHAR_POSY)return;

  //设置窗口

  num=num-‘ ’;//得到偏移后的值

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/zhizao/347893.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部