FSMC

FSMC—-灵活的静态存储控制器

能够与同步或异步存储器和16位PC存储器卡连接,STM32的FSMC接口支持包括 SRAMNANDFLASHNORFLASHPSRAM等存储器,支持8/16/32/位数据宽度。

fsmc框图

fsmc驱动LCD的原理——->nor存储控制器把TFTLCD当成一个SRAM来用,有两个地址的SRAM

fsmc存储块

!注意:

当Bank1接的是16位宽度存储器的时候:HADDR[25:1]->FSMC_A[24:0];

当Bank1接的是8位宽度存储器的时候:HADDR[25:0]->FSMC_A[25:0];

不论外部接8位/16位宽设备,FSMC_A[0]永远接在外部设备地址A[0]。

STM32F4仅写时序DATAST需要+1

SRAM模式A

模式A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//LCD地址结构体
typedef struct
{
vu16 LCD_REG; // 0110 1100 0000 0000 0000 0111 1111 1110
vu16 LCD_RAM; //0110 1100 0000 0000 0000 1000 0000 0000 16进制+1--->8进制加2
} LCD_TypeDef;

//使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11 A10作为数据命令区分线
#define LCD_BASE ((u32)(0x6C000000 | 0x000007FE))
//注意当Bank1接的是16位宽度存储器的时候:HADDR[25:1] ---> FSMC_A[24:0]
//右移一位对齐,对应到地址引脚即A10:A0 --- > 0011 1111 1110 A10是 0
//0x6C000000 ---> 0110 1100 0000 0000 0000 0000 0000 0000
//0x000007FE ---> 0000 0000 0000 0000 0000 0111 1111 1110
//相与的结果
// 0110 1100 0000 0000 0000 0111 1111 1110
#define LCD ((LCD_TypeDef *) LCD_BASE)
1
2
3
4
5
6
LCD_BASE,根据外部电路的连接来确定,如Bank1.sector4就是从地址0X6C000000开始,而0X000007FE,则是A10的偏移量
7FE ---> 0111 1111 1110
16位数据,地址右移一位对齐,对应到地址引脚 ---> 0011 1111 1111
#define LCD ((LCD_TypeDef *) LCD_BASE)强制转换后,LCD_REG---> 0110 1100 0000 0000 0000 0111 1111 1110
对应到A10是016位+18位加2 得到0110 1100 0000 0000 0000 1000 0000 0000 A10是1
从而实现对RS的控制

c语言位运算

按位与运算 &

&0是屏蔽该位(使该位清0),&1是该位不变

常用来查看或分离某一位的值

举例

1
2
3
4
TIM2ch1_cap_sta&0x40

# 0x40 0100 0000
# 第七位是捕获到高电平标志位,和0x40&就是为了查看TIM2ch1_cap_sta第七位是不是1,是不是捕获到了高电平

按位或运算 |

|0是不变,|1是置1

常用来把某一位设置为1

举例

1
2
3
TIM2ch1_cap_sta |= 0x80;
# 0x80 1000 0000
# 时间太长了无法计数了,强制拔第八位置1,使这次捕获完成

按位异或 ^

^0是不变,^1是反转

常用来反转某一位的值,比如把0变成1,1变成0

1
2
0000 1111 & 0000 0011 = 0000 0011
# 1111的前两位被翻转为0

异或运算的四条性质

  1. 任意一个变量X与其自身进行异或运算,结果为0,即X^X=0

  2. 任意一个变量X与0进行异或运算,结果不变,即X^0=X

  3. 异或运算具有可结合性,即a^b^c=(a^b)^c=a^(b^c)

  4. 异或运算具有可交换性,即a^b=b^a

左移 <<

向左移动相应的位数

1
2
1 1 1 1 1 1 1 1 << 1  ----> 
1 1 1 1 1 1 1 0

右移 >>

向右移动相应的位数

1
2
1 1 1 1 1 1 1 1  >> 1     ---->
0 1 1 1 1 1 1 1

综合运用举例

设置寄存器的值

1
2
GPIOA -> CRL &= 0XFFFFFF0F;// 将第 4-7 位清 0
GPIOA -> CRL |= 0X00000040;// 设置相应位的值,且不改变其他位的值

移位操作提高代码可读性

1
2
3
4
GPIOx -> BSRR = (((uint32_t)0x01) << pinpos);
# 0x01 0000 0001
# 这行代码可以直观明了的知道,是将第 pinpos 位设置为 1
GPIOA -> ORT |= 1<<5;// PA.5 输出高,不改变其他位