历史上的今天
今天是:2024年09月08日(星期日)
2018年09月08日 | STM8L151 使用硬件SPI驱动W25Q16 Flash
2018-09-08 来源:eefocus
SPI:有四根线的串行通信协议,允许与其他设备以半、全双工、同步、串行方式通信。
MISO:主模式输入、从模式输出线
MOSI:主模式输出、从模式输入线
CLK:时钟线
NSS:从设备选择引脚,主设备标准IO驱动,并用来区分从设备
以STM8L 驱动SPI Flash W25Q16 为例说明记录下,使用STM8L 的SPI该注意哪些地方,以及如何简单驱动W25Q16。
华邦的W25Q16 SPI Flash芯片是采用SPI接口,至于该芯片的优缺点就不说了,STM8L上有一个硬件SPI,可以很方便的来驱动W25Q16,下面就来看看该如何配置STM8L的SPI 外设。
void SPI_FLASH_Init(void)
{
//SPI_CLOCK:PB5, SPI_MOSI: PB6, SPI_MISO: PB7
GPIO_Init(GPIOB, GPIO_Pin_5, GPIO_Mode_Out_PP_High_Fast);
GPIO_Init(GPIOB, GPIO_Pin_6, GPIO_Mode_Out_PP_High_Fast);
//主机模式,配置为输入 该设置很关键
GPIO_Init(GPIOB, GPIO_Pin_7, GPIO_Mode_In_PU_No_IT);
/* 初始化SPI */
SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_4, SPI_Mode_Master,\
SPI_CPOL_High, SPI_CPHA_2Edge, \
SPI_Direction_2Lines_FullDuplex, SPI_NSS_Soft, 0x07);
SPI_Cmd(SPI1, ENABLE); /* 使能SPI */
/* 配置CS管脚 */
GPIO_Init(SPI_CS , SPI_Pin_CS, GPIO_Mode_Out_PP_High_Fast);
GPIO_WriteBit(SPI_CS, SPI_Pin_CS, SET); /* 拉高不使能外部SPI设备 */
}
在上面中要注意SPI 使用到的管脚PB5, PB6, PB7 的设置,在SPI主机模式中,PB5、PB6根据外围电路可以设置为外部上拉输出,也可设置为上面的内部上拉输出,而PB7则要设置为内部上拉输入或浮空输入(外加上拉电阻),这些设置完还要开启SPI外设的时钟。
其中W25Q16的SPI总线模式是Mode0 或Mode3 ,这个在手册中或本文中下面的时序图中可以看出,那么对于SPI的初始化就要考虑了,当
SPI_Init中参数为SPI_CPOL_High, SPI_CPHA_2Edge表示Mode0,为SPI_CPOL_Low, SPI_CPHA_1Edge表示Mode3,如果为其他组合那么就会导致通信数据错位不正确。
下面是读取Flash 厂商ID和设备ID的函数,
uint8_t SPI_FLASH_SendByte(u8 byte)
{
/* Loop while DR register in not emplty */
while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_SendData(SPI1, byte);
/* Wait to receive a byte */
while (SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_ReceiveData(SPI1);
}
uint16_t SPI_FLASH_ReadID(void)
{
u16 Device_ID = 0;
/* Select the FLASH: Chip Select low */
SPI_FLASH_CS_LOW(); //拉低片选管脚电平,选中外设
/* Send "RDID " instruction */
SPI_FLASH_SendByte(0x90); //读取设备ID指令
SPI_FLASH_SendByte(0X00);
SPI_FLASH_SendByte(0X00);
SPI_FLASH_SendByte(0X00);
/* Read a byte from the FLASH */
Device_ID = (SPI_FLASH_SendByte(Dummy_Byte)<<8);
Device_ID |= SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_CS_HIGH();//拉高片选管脚电平,
return Device_ID;
}
在W25Q16的手册中,
函数读回来的数据应该是上面的值,再看看手册上的ID读取指令0x90
获取设备ID的指令发送顺序如上图,第一字节先发0x90,然后发两个dummy Byte(任何数值都可)和0x00,之后再读取厂商ID和设备ID,上面的函数基本实现的就是这个时序。
实测的测试结果如下,
结果与手册给的ID一致。
史海拾趣
|
1 TM卡简介 TM(Touch Memory)卡是美国Dallas公司的专利产品。它采用单线协议通信,通过瞬间碰触完成数据读写,既具有非接触式IC卡的易操作性,又具有接触式IC 卡的廉价性,是当前性价比最优秀的IC卡之一。它的外形类似于一个钮扣(button) ...… 查看全部问答> |
|
快速获得芯币的另一种方法,就是与博客紧密结合。规则如下,请大家详细阅读啊! 1、注册博客 + 20 芯币 2、在论坛签名中注明自己博客地址 +5 芯币 3、博客个人信息注册完全,其中上传电子相片 +5芯币 4、 ...… 查看全部问答> |
|
提示的是 bad crc or nand 在网上查了下,应该是env的问题!麻烦各位有经验的朋友,说一下具体怎么改! 我用的是mini2440,page size应该是2048的,但是u-boot启动输出的还是512~已经进行过CONFIG_了… 查看全部问答> |
|
请教高手:如何在扫描输入完成后,光标自动跳到下一个TEXTBOX 我想让程序在扫描输入完成后,光标自动跳到下一个TEXTBOX 可是我在WINCE上捕捉不到扫描键,也不知道如何区分 输入 是由键盘上输入的还是扫描读入的 哪位高手知道的帮帮我,谢谢 啦 … 查看全部问答> |
|
GBLS MainEntry MainEntry SETS \"Main\" IMPORT $MainEntry MainEntry不是已经在第一行就已经定 ...… 查看全部问答> |




