STM32的FSMC驱动TFT笔记

发布者:悦耳旋律最新更新时间:2018-04-22 来源: eefocus关键字:STM32  FSMC  驱动TFT 手机看文章 扫描二维码
随时随地手机看文章

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 */

 

}

 

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

* Function Name  : LCD_Clear

* Description    : 将屏幕填充成指定的颜色,如清屏,则填充 0xffff

* Input          : - Color: Screen Color

* Output         : None

* Return         : None

* Attention  : None

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

void LCD_Clear(uint16_t Color)

{

uint32_t index=0;

 

Clr_Cs; 

LCD_WriteIndex(0x0022);

for( index = 0; index < MAX_X * MAX_Y; index++ )

{

LCD_WriteData(Color);

}

Set_Cs;

}

 

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

* Function Name  : LCD_GetPoint

* Description    : 获取指定座标的颜色值

* Input          : - Xpos: Row Coordinate

*                  - Xpos: Line Coordinate 

* Output         : None

* Return         : Screen Color

* Attention  : None

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

uint16_t LCD_GetPoint(uint16_t Xpos,uint16_t Ypos)

{

uint16_t dummy;

 

LCD_SetCursor(Xpos,Ypos);

Clr_Cs;

LCD_WriteIndex(0x0022);  

 

 

             dummy = LCD_ReadData();   /* 空读一次 */

             dummy = LCD_ReadData(); 

    Set_Cs; 

       return  dummy;

      

}


关键字:STM32  FSMC  驱动TFT 引用地址:STM32的FSMC驱动TFT笔记

上一篇:STM32 F207的PWM输入捕获频率和占空比
下一篇:stm32f4开发板驱动LCD液晶屏的个人总结

推荐阅读最新更新时间:2024-03-16 16:00

STM32应用简章之外部中断
①初始化IO口为输入。 GPIO_Init(); ② 开启IO口复用时钟。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); ③设置IO口与中断线的映射关系。 void GPIO_EXTILineConfig(); ④初始化线上中断,设置触发条件等。 EXTI_Init(); ⑤配置中断分组(NVIC),并使能中断。 NVIC_Init(); ⑥ 编写中断服务函数。 EXTIx_IRQHandler(); ⑦清除中断标志位 EXTI_ClearITPendingBit();
[单片机]
STM32_ps2键盘显示测试程序
//PS2键盘测试程序,可换行,按shift不放接着输入 //可输出大写,按下CAPS输出大写,再次按下输出小写 //此程序只用来测试,代码冗余,仅供参考,可根据需要自行删减 //PA13- PS2.CLK PA15- PS2.DATA #include stm32f10x_lib.h #include sys.h #include usart.h #include delay.h #include led.h #include key.h #include exti.h #include wdg.h #include timer.h #include lcd.h
[单片机]
干货 | 用GD32替换STM32,这些细节你一定要知道!
GD32是国内开发的一款单片机,据说开发的人员是来自ST公司的,GD32也是以STM32作为模板做出来的。所以GD32和STM32有很多地方都是一样的。 不过GD32毕竟是不同的产品,不可能所有东西都沿用STM32,有些自主开发的东西还是有区别的。 相同的地方我们就不说了,下面列一下不同的地方。 01 内核 GD32采用二代的M3内核,STM32主要采用一代M3内核,下图是ARM公司的M3内核勘误表,GD使用的内核只有752419这一个BUG。 02 主频 使用HSE(高速外部时钟):GD32的主频最大108M,STM32的主频最大72M 使用HSI(高速内部时钟):GD32的主频最大10
[单片机]
stm32 一上电串口发送0x00
现象:stm32 一上电串口发送0x00。 (1)STATUS寄存器的上电初始值有问题造成的,Usart的发送数据寄存器有一个缓冲移位寄存器。并且发送有两个状态,一个是发送数据寄存器为空,一个是移位寄存器发送完成。上电后Usart的状态寄存器的发送完成位为0,造成了上电以后会始终会有一个值被发送,这个值就是发送移位寄存器中的值,而这个值有时候是0X00有时候是0XFE 。 (2)在上电后至端口初始化,STM32的I/O端口处于高阻状态,有些RS232转换芯片在输入端为高阻时,可能会输出0,从而造成接收端收到0,我们已经多次看到这种现象;这时只需要在STM32的TX端加一个上拉电阻就可以解决(还未验证)。 解决方法:
[单片机]
STM32入门学习之GPIO(STM32F030F4P6基于CooCox IDE)(一)
1、CooCox IDE当前最新版本为V2,不过个人看网上的示例大都是基于旧版本的,个人也试过新版本,发现一些操作还不习惯,在此也还是介绍旧版本1.7.8。 http://www.coocox.org/software/coide.php 2、运行CoIDE,点击菜单栏的Project——New Project,填写项目名称HelloGPIO 3、选择Chip 4、选择ST——STM32F03x——STM32F030F4P6 5、系统将弹出 Repository,这里可直接选择程序需要的库,勾选GPIO,系统将自动勾选RCC、CMSIS BOOT、M0 Cmsis Core等,并直接生成对应 6、
[单片机]
STM32固件库详解
1.1 基于标准外设库的软件开发 1.1.1 STM32标准外设库概述 STM32标准外设库之前的版本也称固件函数库或简称固件库,是一个固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。该函数库还包括每一个外设的驱动描述和应用实例,为开发者访问底层硬件提供了一个中间API,通过使用固件函数库,无需深入掌握底层硬件细节,开发者就可以轻松应用每一个外设。因此,使用固态函数库可以大大减少用户的程序编写时间,进而降低开发成本。每个外设驱动都由一组函数组成,这组函数覆盖了该外设所有功能。每个器件的开发都由一个通用API (application programming interface 应用编程界面)驱动,API对
[单片机]
stm32 DAC+DMA 输出100K正弦波杠杠的
之前想用stm32的DAC输出正弦波,才用的方案是在死循环里面用for循环输出36点的电压值模拟成一个完整的正弦波。发现最多只能输出个20KHz的波形,在示波器下面能够看到明显的梯度。后来用DMA+ADC的模式发现可以上100K(不过频率有点飘),下面吧代码贴出来 void DAC_DMA_Configuration(void) { DAC_InitTypeDef DAC_InitStructure; DMA_InitTypeDef DMA_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; GPIO_InitTypeDef GPIO
[单片机]
怎样在Linux上开发STM32程序
步骤1:下载所需的一切 您需要下载三个部分才能正常工作: 用于ARM的GCC编译器 STM32固件文件 St-link实用程序 Sample Project 编译器是将我们的C代码和所有其他库文件编译成stm32控制器可以理解的机器语言的主要软件。下载此编译器的最新预编译版本。 包含STM32固件的文件夹是保存主处理器运行所需的所有启动文件和核心文件的文件夹。我们将使用HAL已超越的标准外围设备库。我更喜欢StPeriphLibrary,因为使用该处理器的公司都在使用它们,因为它功能强大,更老旧并且受支持。它也更坚固。它不会减少初始化外围设备或打开LED所需的工作,但是会迫使您学习这些处理器的工作方式。这样一来,您将对内部工作
[单片机]
怎样在Linux上开发<font color='red'>STM32</font>程序
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved