专业编程基础技术教程

网站首页 > 基础教程 正文

SPI_FLASH编程_读ID spi flash 编程器

ccvgpt 2024-11-13 09:58:49 基础教程 9 ℃


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

SPI_FLASH编程_读ID spi flash 编程器

作者:韦东山

本文字数: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 = 0x%02x, PID = 0x%02x\n\r", mid, pid);

    sprintf(str, "SPI : %02x, %02x", mid, pid);
    OLEDPrint(4,0,str);

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

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

Tags:

最近发表
标签列表