NIOS II软核下使用SPI接口驱动W25QXX芯片

之前使用STM32驱动W25Q128,驱动程序用的是github上下载的一个W25QXX的文件,对该系列的芯片通用。

现在使用NIOS II软核为控制核心,添加了SPI外设,配置其实很简单:

添加后,BSP内部会提供一个写好的SPI函数,实现SPI数据的收发,但是使用过程中需要注意一些问题。

第一个要注意的问题是SPI的收发函数。

uint8_t	W25qxx_Spi(uint8_t	Data)
{
	uint8_t	ret;
	HAL_SPI_TransmitReceive(&_W25QXX_SPI,&Data,&ret,1,100);
	return ret;	
}

这个函数是在STM32环境下使用的,没有任何问题。关键在于这个函数:

HAL_SPI_TransmitReceive(&_W25QXX_SPI,&Data,&ret,1,100);

注意看它的参数,它是同时进行SPI数据的发送和接收,在发送Data里面的数据的同时,也会把收到的数据存入ret。并不是先把Data里面的数据发出去,然后在进行接收操作。

而NIOS II的BSP里面提供的函数如下:

int alt_avalon_spi_command(alt_u32 base, alt_u32 slave,
                           alt_u32 write_length, const alt_u8 * write_data,
                           alt_u32 read_length, alt_u8 * read_data,
                           alt_u32 flags)

这个函数会先发送指定数量的数据,然后接收指定数量的数据,和STM32的函数是不一样的。并非无法实现STM32的效果,而是官方只提供了这一个函数,所以要想办法自己修改。

另一个要注意的地方也和这个函数有关系。实际应用中,使用STM32的SPI外设时,通常是不用硬件的NSS片选信号的,而是自己定义一个GPIO,用来做片选。用到W25QXX的驱动里,效果是这样:

void W25qxx_ReadUniqID(void)
{
  HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_RESET);
  W25qxx_Spi(0x4B);
	for(uint8_t	i=0;i<4;i++)
		W25qxx_Spi(W25QXX_DUMMY_BYTE);
	for(uint8_t	i=0;i<8;i++)
		w25qxx.UniqID[i] = W25qxx_Spi(W25QXX_DUMMY_BYTE);
  HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_SET);
}

如上,不管什么操作,先开片选,然后各种读写,然后关片选。

而NIOS II官方提供的这个SPI函数,把片选写在了里面。每调用一次,函数内部就会执行打开片选、关闭片选的操作。而要实现一些比较复杂的操作时,需要反复读写,中间是不能关闭片选的,一旦关掉,操作就被中断了。这就是导致读写失败的主要原因。

因此也要注意这个地方,解决方法很简单,注释掉里面的开关片选就行了,在外面自己宏定义一个开片选、一个关片选即可。

大致就这些,只讲了原理,没提供源码,打完收工。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据