[STM32L1] STM8L151 使用硬件SPI驱动W25Q16 Flash

[复制链接]
 楼主| gejigeji521 发表于 2017-6-10 20:43 | 显示全部楼层 |阅读模式
SPI:有四根线的串行通信协议,允许与其他设备以半、全双工、同步、串行方式通信。MISO:主模式输入、从模式输出线
MOSI:主模式输出、从模式输入线
CLK:时钟线
NSS:从设备选择引脚,主设备标准IO驱动,并用来区分从设备
以STM8L 驱动SPI Flash W25Q16 为例说明记录下,使用STM8L 的SPI该注意哪些地方,以及如何简单驱动W25Q16。
华邦的W25Q16 SPI Flash芯片是采用SPI接口,至于该芯片的优缺点就不说了,STM8L上有一个硬件SPI,可以很方便的来驱动W25Q16,下面就来看看该如何配置STM8L的SPI 外设。

 楼主| gejigeji521 发表于 2017-6-10 20:44 | 显示全部楼层
  1. void SPI_FLASH_Init(void)  
  2. {   
  3.     //SPI_CLOCK:PB5, SPI_MOSI: PB6, SPI_MISO: PB7  
  4.     GPIO_Init(GPIOB, GPIO_Pin_5, GPIO_Mode_Out_PP_High_Fast);  
  5.     GPIO_Init(GPIOB, GPIO_Pin_6, GPIO_Mode_Out_PP_High_Fast);  
  6.     //主机模式,配置为输入 该设置很关键  
  7.     GPIO_Init(GPIOB, GPIO_Pin_7, GPIO_Mode_In_PU_No_IT);  
  8.     /* 初始化SPI */  
  9.     SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_4, SPI_Mode_Master,\  
  10.          SPI_CPOL_High, SPI_CPHA_2Edge, \  
  11.         SPI_Direction_2Lines_FullDuplex, SPI_NSS_Soft, 0x07);  
  12.       
  13.     SPI_Cmd(SPI1, ENABLE);  /* 使能SPI */  
  14.       
  15.     /* 配置CS管脚 */  
  16.     GPIO_Init(SPI_CS , SPI_Pin_CS, GPIO_Mode_Out_PP_High_Fast);  
  17.     GPIO_WriteBit(SPI_CS, SPI_Pin_CS, SET);     /* 拉高不使能外部SPI设备 */  
  18. }  
 楼主| gejigeji521 发表于 2017-6-10 20:44 | 显示全部楼层
在上面中要注意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,如果为其他组合那么就会导致通信数据错位不正确。




 楼主| gejigeji521 发表于 2017-6-10 20:45 | 显示全部楼层
下面是读取Flash 厂商ID和设备ID的函数:
  1. uint8_t SPI_FLASH_SendByte(u8 byte)  
  2. {  
  3.   /* Loop while DR register in not emplty */  
  4.   while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET);  
  5.   /* Send byte through the SPI1 peripheral */  
  6.   SPI_SendData(SPI1, byte);  
  7.   /* Wait to receive a byte */  
  8.   while (SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);  
  9.   /* Return the byte read from the SPI bus */  
  10.   return SPI_ReceiveData(SPI1);   
  11. }  

  1. uint16_t SPI_FLASH_ReadID(void)  
  2. {  
  3.     u16 Device_ID = 0;  
  4.     /* Select the FLASH: Chip Select low */  
  5.     SPI_FLASH_CS_LOW(); //拉低片选管脚电平,选中外设  
  6.     /* Send "RDID " instruction */  
  7.     SPI_FLASH_SendByte(0x90); //读取设备ID指令  
  8.     SPI_FLASH_SendByte(0X00);  
  9.     SPI_FLASH_SendByte(0X00);  
  10.     SPI_FLASH_SendByte(0X00);  
  11.     /* Read a byte from the FLASH */  
  12.     Device_ID = (SPI_FLASH_SendByte(Dummy_Byte)<<8);  
  13.     Device_ID |= SPI_FLASH_SendByte(Dummy_Byte);  
  14.     SPI_FLASH_CS_HIGH();//拉高片选管脚电平,  
  15.     return Device_ID;  
  16. }  



 楼主| gejigeji521 发表于 2017-6-10 20:45 | 显示全部楼层
看到不错的,我就喜欢转转
643757107 发表于 2017-6-10 23:34 | 显示全部楼层
SPI用处太多了,这个不会,真是没法
您需要登录后才可以回帖 登录 | 注册

本版积分规则

195

主题

2460

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部