当前位置: 首页 > news >正文

FSMC(STM32)

(一)FSMC:Flexible Static Memory Controller,可变(灵活)静态存储控制器

小容量产品是指闪存存储器容量在1 6K32K 字节之间的STM32F101xxSTM32F102xx

STM32F103xx微控制器。 

中容量产品是指闪存存储器容量在 64K128K 字节之间的STM32F101xxSTM32F102xx

STM32F103xx微控制器。 

容量产品是指闪存存储器容量在 256K512K 字节之间的STM32F101xxSTM32F103xx微控

制器。 

互联型产品是指STM32F105xxSTM32F107xx微控制器。

 

 

对于M3来说

 

 然后将这1.0GB的外存分为4个大块

 

1,为什么每一块中每一片是64M?

答:我们知道地址线26跟,2的26次方等于64M,所以每个块是64M,

2,为什么每一块中是4片?

答:它这里有一个很巧妙的方法每一个块有4个片选,以方便我们使用那一片;

 

故:1.0GB =  (4*64)*4

 

以下例程我们的液晶是接在Bank1中的第4片;

先看下接口图(野火板子)

1,为什么是片4?

答:

 

我们的LCD_CS接在了FSMC_NE4的片选4端(说白了是:液晶的内存与FSMC要相互对应)

2,为什么是块1?

答:因为液晶里面的RAM相当于NOR FLASH,或者PSRAM,所以最好用块1

3,为什么低电平电量点亮屏幕呢?

答:看下图

 

 对于38,39管脚的控制使用一个PNP三极管,当LIGHT低电平时 导通。

为什么接PB1?

答:PB1通过有PWM调制功能

4,对于读写控制可参考图中注解,但主要对于不同的液晶控制芯片读写控制可能有所差异。

如图9341

 

RS 我们接的是FSMC_A23,那么我们控制FSMC的地址线23就可以控制发送命令还是数据了

 

程序讲解:

1,加载ili9341驱动文件

2,打开

/* #include "stm32f10x_flash.h" */
#include "stm32f10x_fsmc.h"

 3,端口配置

 4,工作模式配置(参考ili9341手册)

void LCD_FSMC_Config(void)
{
    FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef  p; 
    
    
    p.FSMC_AddressSetupTime = 0x02;	 //地址建立时间
    p.FSMC_AddressHoldTime = 0x00;	 //地址保持时间
    p.FSMC_DataSetupTime = 0x05;		 //数据建立时间
    p.FSMC_BusTurnAroundDuration = 0x00;
    p.FSMC_CLKDivision = 0x00;
    p.FSMC_DataLatency = 0x00;
    p.FSMC_AccessMode = FSMC_AccessMode_B;	 // 一般使用模式B来控制LCD
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4; FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; //FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;   FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR; FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p; FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); }

FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;//此处我们用到了bank1的第四片

FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;//此处我们用到了bank1的第四片

 

5,液晶软件复位(低电平复位,切记高电平要保持一下)

void LCD_Rst(void)
{			
		GPIO_ResetBits(GPIOG, GPIO_Pin_11);	 //低电平复位
    Lcd_Delay(0xAFFf<<2); 					   
    GPIO_SetBits(GPIOG, GPIO_Pin_11);		 	 
    Lcd_Delay(0xAFFf<<2); 	
}

 6,写命令、数据

void LCD_REG_Config(void)

这里介绍一下写命令与写数据函数

	LCD_ILI9341_CMD(0xCF);      //写命令
	LCD_ILI9341_Parameter(0x00);   //写数据

 如下:

#define Bank1_LCD_C    ((u32)0x6C000000)	   //Disp Reg ADDR
#define Bank1_LCD_D    ((u32)0x6D000000)       //Disp Data ADDR       // A23 PE2

//选定LCD指定寄存器
#define LCD_WR_REG(index)    ((*(__IO u16 *) (Bank1_LCD_C)) = ((u16)index))
//往LCD GRAM写入数据
#define LCD_WR_Data(val)       ((*(__IO u16 *) (Bank1_LCD_D)) = ((u16)(val)))

#define LCD_ILI9341_CMD(index)       LCD_WR_REG(index)
#define LCD_ILI9341_Parameter(val)	 LCD_WR_Data(val)

 解释如下:

 当主控对指针量(地址)0x6D000000操作,FSMC_A23为高电平,此时为写数据;

操作顺序: CPU作用于FSMC外设,FSMC内存块作用于TFT的GRAM。

可理解CPU向0x6C000000,0x6D000000该地址写入数据,即使操作FSMC的块1的片选4,后导致FSMC外设地址线和数据线管脚的变化;

 为什么2^23 还要*2 ?

答:

 

 在外部设备是16位时,连接到内部地址总线 HADDR时 左移一位,0-1,,,,24-25;所以为了满足对应关系,我们要将指针量*2,才能找出正确的地址后与之对应;

若连接其他的地址线,那么计算方式一样。

 7,扫描方式

	DEBUG_DELAY();
	LCD_ILI9341_CMD(0x36); 	
	LCD_ILI9341_Parameter(0xC8);    //竖屏  左上角(起点)到右下角(终点)扫描方式
	DEBUG_DELAY();

 向“36” 寄存器 写对应指令就成

	/* column address control set */   X轴
	LCD_ILI9341_CMD(0X2A); 
	LCD_ILI9341_Parameter(0x00);    //低八位  0
	LCD_ILI9341_Parameter(0x00);   //高八位
	LCD_ILI9341_Parameter(0x00);  
	LCD_ILI9341_Parameter(0xEF);       0XEF = 239
	
	/* page address control set */   Y轴
	DEBUG_DELAY();
	LCD_ILI9341_CMD(0X2B); 
	LCD_ILI9341_Parameter(0x00);        0
	LCD_ILI9341_Parameter(0x00);
	LCD_ILI9341_Parameter(0x01);
	LCD_ILI9341_Parameter(0x3F);       0X13F = 319  

 ---------------------------------------------------------------------------

函数部分:

①清屏函数(源)

void LCD_Clear(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color)

 如清掉整个屏幕

LCD_Clear(0, 0, 240, 320, BACKGROUND);

②设置坐标点(源)

void LCD_SetCursor(uint16_t x, uint16_t y)

③ 开窗(源)

界限设置,不然就不会反过来写(第一行写完,然后从第二行写),调整地址指针

void LCD_OpenWindow(uint16_t x, uint16_t y, uint16_t width, uint16_t height)

 ④画点(源)

一切一切的本源

void LCD_SetPoint(uint16_t x , uint16_t y , uint16_t color)	
{	
	LCD_SetCursor(x, y);
	LCD_ILI9341_CMD(0x2c);	    
	LCD_WR_Data(color);
}

 ⑤颜色(源)

uint16_t LCD_RD_data(void)	
{	
	uint16_t R=0, G=0, B=0 ;

	R = *(__IO uint16_t *)Bank1_LCD_D; 	  /*FIRST READ OUT DUMMY DATA*/
	R = *(__IO uint16_t *)Bank1_LCD_D;  	/*READ OUT RED DATA  */
	B = *(__IO uint16_t *)Bank1_LCD_D;  	/*READ OUT BLACK DATA*/
	G = *(__IO uint16_t *)Bank1_LCD_D;  	/*READ OUT GREEN DATA*/
      //将地址转换成指针,对指针进行操作 return (((R>>11)<<11) | ((G>>10)<<5) | (B>>11)); //转换成16位宽度 }

 ⑥显示一个字符(源)

void LCD_DispChar(uint16_t x, uint16_t y, uint8_t ascii, uint16_t color)

如:LCD_DispChar(60, 60, 'A', RED); //对应有效的地方写该颜色,这个函数也是独立的;

当然在用之前要有自己对应的的字库

 ⑦显示一个字符串

void LCD_DispStr(uint16_t x, uint16_t y, uint8_t *pstr, uint16_t color)

 如:

 LCD_DispStr(10, 10, (uint8_t *)"This is a lcd demo to display ascii", RED); 

 

 ⑧显示数字

这个说白还是用到LCD_DispChar

void LCD_DisNum(uint16_t x, uint16_t y, uint32_t num, uint16_t color)

 

 

                                                             瘋子笔录

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/Ph-one/p/4028845.html

相关文章:

  • 自动挡汽车档位介绍
  • SD卡
  • Java中的三大框架分别有什么用
  • DDR2是什么意思
  • FATFS(A)
  • 三星核S5PV210AH-A0 SAMSUNG
  • flash
  • RAM,ROM,NAND Flash,NOR Flash(A)
  • Android移植学习笔记
  • NRF24L01通信频率
  • 利用.bat(批处理)来删除KEIL编译生成的无用文件
  • SVC(STM32)
  • 关于STM32 MDK中USE_STDPERIPH_DRIVER问题的解释
  • 鬼谷子七十二术(完整版)值得永久收藏!终生研读!
  • assert_param
  • [译]CSS 居中(Center)方法大合集
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • AHK 中 = 和 == 等比较运算符的用法
  • angular学习第一篇-----环境搭建
  • Consul Config 使用Git做版本控制的实现
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • JS专题之继承
  • LeetCode算法系列_0891_子序列宽度之和
  • Promise面试题,控制异步流程
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • SpringBoot 实战 (三) | 配置文件详解
  • spring学习第二天
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 给第三方使用接口的 URL 签名实现
  • 机器学习中为什么要做归一化normalization
  • 今年的LC3大会没了?
  • 开发基于以太坊智能合约的DApp
  • 前嗅ForeSpider采集配置界面介绍
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 使用Swoole加速Laravel(正式环境中)
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 树莓派 - 使用须知
  • 思否第一天
  • 小而合理的前端理论:rscss和rsjs
  • 用Python写一份独特的元宵节祝福
  • 扩展资源服务器解决oauth2 性能瓶颈
  • # include “ “ 和 # include < >两者的区别
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (42)STM32——LCD显示屏实验笔记
  • (day6) 319. 灯泡开关
  • (搬运以学习)flask 上下文的实现
  • (六)软件测试分工
  • (转)3D模板阴影原理
  • .Mobi域名介绍
  • .net 7 上传文件踩坑
  • .NET Core 通过 Ef Core 操作 Mysql