来源:百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版),我来为大家科普一下关于如何确定flash和spi连接?下面希望有你要的答案,我们一起来看看吧!

如何确定flash和spi连接(SPIFLASH编程读ID)

如何确定flash和spi连接

来源:百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版)

作者:韦东山

本文字数:1277,阅读时长:1.5分钟

这节讲解如何使用SPI操作Flash,我们在上节课的代码上进行修改,添加一个文件 spi_flash.c 和其头文件 spi_flash.h 。

我们先做一个最简单的spi操作,读取Flash的ID, SPIFlashID() 。

Flash的ID有厂家ID和设备ID,分别用pMID和pDID来保存。

根据Flash的芯片手册 W25Q16DV.pdf 可以知道需要先发出一个指令0x90,再发送24位的地址0,再读取数据前8位是设备ID,然后是8位设备ID。进行操作前必须要片选SPI Flash,片选完还是释放SPI Flash:

void SPIFlashReadID(int *pMID, int *pDID) { SPIFlash_Set_CS(0); /* 选中SPI FLASH */ SPISendByte(0x90); SPIFlashSendAddr(0); *pMID = SPIRecvByte(); *pDID = SPIRecvByte(); SPIFlash_Set_CS(1); }

把其中的发送24地址封装成了一个函数 SPIFlashSendAddr() :

static void SPIFlashSendAddr(unsigned int addr) { SPISendByte(addr >> 16); SPISendByte(addr >> 8); SPISendByte(addr & 0xff); }

依次完成上面的子函数,先是SPI片选,上一节的原理图可以看到SPI Flash的片选是GPG2:

static void SPIFlash_Set_CS(char val) { if (val) GPGDAT |= (1<<2); else GPGDAT &= ~(1<<2); }

SPISendByte() 和前面OLED的是一样的,就不用写了,因此就只剩下 SPIRecvByte() ,放在 gpio_spi.c 里面实现:

unsigned char SPIRecvByte(void) { int i; unsigned char val = 0; for (i = 0; i < 8; i ) { val <<= 1; SPI_Set_CLK(0); if (SPI_Get_DI()) val |= 1; SPI_Set_CLK(1); } return val; }

在每个时钟周期读取DI引脚上的值,对于SOC就是MISO引脚:

static char SPI_Get_DI(void) { if (GPGDAT & (1<<5)) return 1; else return 0; }

至此,读取Flash的ID基本实现,最后在主函数里调用打印,分别在串口和OLED上显示:

SPIFlashReadID(&mid, &pid); printf("SPI Flash : MID = 0xx, PID = 0xx\n\r", mid, pid); sprintf(str, "SPI : x, x", mid, pid); OLEDPrint(4,0,str);

Makefile记得加上新生成的 spi_flash.o 。

「新品首发」STM32MP157开发板火爆预售!首批仅300套