这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 学习AI8051开发板例程:20AI8051的软件SPI读取FLASH芯片

共1条 1/1 1 跳转至

学习AI8051开发板例程:20AI8051的软件SPI读取FLASH芯片

高工
2026-01-19 18:56:27     打赏

    在之前的帖子中,使用硬件的SPI读取板载的FLASH芯片,在本次例子中,使用模拟的SPI方式读取板载的存储芯片。

一:硬件连接:

    首先需要确定使用的GPIO引脚,通常包括:

    SCK:时钟引脚(输出)

    MOSI:主机输出从机输入引脚(输出)

    MISO:主机输入从机输出引脚(输入)

    SS/CS:片选引脚(输出,可选)

二:SPI的模式配置

    根据设备要求选择SPI模式(时钟极性和相位):

    CPOL:时钟极性(0 = 空闲低电平,1 = 空闲高电平)

    CPHA:时钟相位(0 = 数据在第一个时钟沿采样,1 = 数据在第二个时钟沿采样)

    常见模式:

    模式0:CPOL=0, CPHA=0

    模式3:CPOL=1, CPHA=1

三:软件代码:

3.1 GPIO口的定义:

sbit SPI_CE  = P4^0;     //PIN1
sbit SPI_SO  = P4^2;     //PIN2
sbit SPI_SI  = P4^1;     //PIN5
sbit SPI_SCK = P4^3;     //PIN6

3.2 SPI的使用的延时函数

void SPI_Delay(u8 cnt)
{
    while(cnt--);
}

3.3 SPI的初始化部分

void SPI_init(void)
{
    SPI_CE_High();
    SPI_SCK = 0;    // set clock to low initial state
    SPI_SI = 1;
}

3.4 SPI 写入一个字节函数:

void SPI_WriteByte(u8 out)
{
    u8 i;
    i = 8;
    do{
        out <<= 1;
        SPI_SI  = CY;
        SPI_SCK = 1;
        SPI_Delay(3);
        SPI_SCK = 0;
    }while(--i);
    SPI_SI = 1;
}

3.5 SPI 读取一个字节函数:

u8 SPI_ReadByte(void)
{
    u8 i, in;
    i = 8;
    do{
        in <<= 1;
        if (SPI_SO) in++;
        SPI_SCK = 1;
        SPI_Delay(3);
        SPI_SCK = 0;
    }while(--i);
    return in;
}

3.5  擦除扇区的函数,这里需要每次擦写4k字节

void FlashSectorErase(u32 addr)
{
    if(B_FlashOK)
    {
        FlashWriteEnable();             //使能Flash写命令
        SPI_CE_Low();
        if(B_FlashOK == 1)
        {
            SPI_WriteByte(SFC_SECTORER1);    //发送扇区擦除命令
        }
        else
        {
            SPI_WriteByte(SFC_SECTORER2);    //发送扇区擦除命令
        }
        SPI_WriteByte(((u8 *)&addr)[1]);           //设置起始地址
        SPI_WriteByte(((u8 *)&addr)[2]);
        SPI_WriteByte(((u8 *)&addr)[3]);
        SPI_CE_High();
    }
}

3.6 写入多个字节到存储的FLASH里面

void SPI_Write_Nbytes(u32 addr, u8 *buffer, u8 size)
{
    if(size == 0)   return;
    if(!B_FlashOK)  return;
    while(CheckFlashBusy() > 0);        //Flash忙检测

    FlashWriteEnable();                 //使能Flash写命令

    SPI_CE_Low();                       // enable device
    SPI_WriteByte(SFC_PAGEPROG);        // 发送页编程命令
    SPI_WriteByte(((u8 *)&addr)[1]);    //设置起始地址
    SPI_WriteByte(((u8 *)&addr)[2]);
    SPI_WriteByte(((u8 *)&addr)[3]);
    do{
        SPI_WriteByte(*buffer++);       //连续页内写
        addr++;
        if ((addr & 0xff) == 0) break;
    }while(--size);
    SPI_CE_High();                      // disable device
}

3.6 读取多个字节到存储的FLASH里面

void SPI_Read_Nbytes(u32 addr, u8 *buffer, u16 size)
{
    if(size == 0)   return;
    if(!B_FlashOK)  return;
    while(CheckFlashBusy() > 0);        //Flash忙检测

    SPI_CE_Low();                       //enable device
    SPI_WriteByte(SFC_READ);            //read command

    SPI_WriteByte(((u8 *)&addr)[1]);    //设置起始地址
    SPI_WriteByte(((u8 *)&addr)[2]);
    SPI_WriteByte(((u8 *)&addr)[3]);

    do{
        *buffer = SPI_ReadByte();       //receive byte and store at buffer
        buffer++;
    }while(--size);                     //read until no_bytes is reached
    SPI_CE_High();                      //disable device
}

4. 扩展功能

        双工通信:发送和接收同时进行(如上例)。

        仅发送/接收:可简化函数以节省时间。

        高速优化:使用循环展开或汇编代码提高速度。

5. 注意事项

        时序要求:确保时钟频率符合从设备要求(通过延时或NOP调整)。

        中断处理:若在中断中使用,注意保护关键代码段。

        多从机支持:每个从机需独立片选引脚。




关键词: AI8051     软件     FLASH    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]