zengxing3624 发表于 2021-11-11 15:49

HC32F460单片机写SPIFlash

项目中需要用到一片SPIFlash,我用的是SST25VF016B,用单片机自带的SPI接口几天一直没弄通,索性就直接用IO来模拟,以下是代码,也欢迎用SPI接口弄通的兄弟指教。#include "hc32_ddl.h"



#define uchar unsigned char
#define uint unsigned int
#define ulong   unsigned long        
///////////引脚定义

#defineSPI_CLK_Port      (PortC)
#defineSPI_CLK_Pin         (Pin03)

#defineSPI_MISO_Port      (PortC)
#defineSPI_MISO_Pin         (Pin02)

#defineSPI_MISI_Port      (PortC)
#defineSPI_MISI_Pin         (Pin01)

#defineSPI_CS_Port      (PortC)
#defineSPI_CS_Pin         (Pin00)

#defineSPI_WR_Port      (PortC)
#defineSPI_WR_Pin         (Pin15)






char dat={1,2,3,4,5,6,7,8,9,1};
char add={1,0,1};
char R_dat;
char num;

void Flash_init();        /* 程序功能:    用来将时钟线初始化为低. 必须在将设备设置为模式0之前调用*/
void Flash_WRSR(uchar byte);//写状态寄存器
uchar Flash_Read_Status_Register(void);   //读状态寄存器的值
void Flash_WREN_Check(void);                /* 功能: 检查擦写操作前WEL位是否为1*/   
voidFlash_WREN(void) ;       //写使能命令
void Flash_Sector_Erase(ulong Dst) ;/* 功能: Sector Erases the Chip.   4K         */
void Flash_Wait_Busy(void);//等待 FLASH空闲
void Flash_Chip_Erase(void)   ;           /* 功能: 擦除整个芯片               */
void Flash_Block_Erase_32K(ulong Dst) ;/* 功能: Block Erases 32 KByte of the Chip.         */
void Flash_Block_Erase_64K(ulong Dst) ;
void Flash_EWSR(void) ; //;使能改写状态寄存器
void   Flash_WRDI(void)   ;//        禁止写使能

void Flash_Send_Byte(uchar dat) ;//发送一个数据char 型 的从51到FLASH
ucharFlash_Get_Byte(void);// 接收一个char型的数据         51接收
ucharFlash_Read(ulong Dst);//读取一个措定地址内的一个数据作为函数返回值
void Flash_Write(ulong Dst,uchar dat);        //向flash 内的一个地址内写入一个数据

void Flash_Write_data(ucharadd[],uchar dat[],uchar size);        //向flash 内的一个基地址 add,add放地址高八位         内写入size个数据。

//向从flash 内的一个基地址 add,add放地址高八位         内读出size个数据。           放到dat[]中
void Flash_Read_data(ucharadd[],uchar R_dat[],uchar size);

//向从flash 内的一个基地址 add,      内读出size个数据。           放到dat[]中
void Flash_Read_data_add(ulong Dst,uchar R_dat[],uchar size);
void Flash_Write_data_add(ulong Dst,uchar dat[],uchar size);//向flash 内的一个基地址 add   








////////////////////////////////////SPI读写驱动////////////////////////////////////////////////////////////////////////////////
void Flash_Send_Byte(uchar dat) //发送一个数据char 型 的从51到FLASH
{
uchar i;
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
for(i=0;i<8;i++)
    {
      if(dat & 0x80)
         {
             PORT_SetBits(SPI_MISI_Port,SPI_MISI_Pin);
         }
      else
             PORT_ResetBits(SPI_MISI_Port,SPI_MISI_Pin);
      dat<<=1;
      PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin);           //信号拉高读进数据
      Ddl_Delay1us(1);

          PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);    //将信号拉低
      Ddl_Delay1us(1) ;   
      }
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
}

uchar Flash_Get_Byte(void)   //接收一个char型的数据
{
uchar i;
uchar one_data=0;
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
// PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin;
for(i=0;i<8;i++)
{       
        one_data=one_data<<1;
        PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
        Ddl_Delay1us(1);
           Ddl_Delay1us(1);
       if(PORT_GetBit(SPI_MISO_Port,SPI_MISO_Pin)==1)
       {
       one_data=one_data | 0x01;
       }
    PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin);
    Ddl_Delay1us(1)        ;
}
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
//CS=1;
return one_data;
}

/************************************************************************/   
        /* 名称: Read                         */   
        /* 功能: 读取一个地址内一个字节的数据.返回读取的数据*/   
        /* 输入:      Dst:    Destination Address 000000H - 1FFFFFH       */   
        /* 返回:      byte                            */   
        /************************************************************************/   
uchar Flash_Read(ulong Dst)   
        {   
          uchar byte = 0;
               
                PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin);   
          PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
                        /* enable device */   
          Flash_Send_Byte(0x03);      /* read command */   
          Flash_Send_Byte(((Dst & 0xFFFFFF) >> 16));/* send 3 address bytes */   
          Flash_Send_Byte(((Dst & 0xFFFF) >> 8));   
          Flash_Send_Byte(Dst & 0xFF);   
          byte = Flash_Get_Byte();   
          PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);          /* disable device */   
          return byte;            /* return one byte read */   
        }   
////////////////////////////////////////////////////////////////////////////////////////////////
void Flash_Write(ulong Dst,uchar dat)        //向flash 内的一个地址内写入一个数据。
{
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
      Flash_Send_Byte(0x02);      /* read command */   
          Flash_Send_Byte(((Dst & 0xFFFFFF) >> 16));/* send 3 address bytes */   
          Flash_Send_Byte(((Dst & 0xFFFF) >> 8));   
          Flash_Send_Byte(Dst & 0xFF);
      Flash_Send_Byte(dat);///secd data to flash
PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);

}

void Flash_Write_data(ucharadd[],uchar dat[],uchar size)        //向flash 内的一个基地址 add,add放地址高八位         内写入size个数据。
{
uchar i;
ulong Dst=0;
for(i=0;i<2;i++)
{
Dst|=add;
Dst=Dst<<8;
}
Dst|=add;
                for(i=0;i<size;i++)
                {
               Flash_WREN();
               PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
                  Flash_Send_Byte(0x02);      /* read command */   
                  Flash_Send_Byte(((Dst & 0xFFFFFF) >> 16));/* send 3 address bytes */   
              Flash_Send_Byte(((Dst & 0xFFFF) >> 8));   
              Flash_Send_Byte(Dst & 0xFF);
          Flash_Send_Byte(dat);///secd data to flash
                  Dst++;
                  PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);
                  Flash_WRDI();
                }
//CS=1;

}

//向从flash 内的一个基地址 add,add放地址高八位         内读出size个数据。           放到dat[]中
void Flash_Read_data(ucharadd[],uchar R_dat[],uchar size)
{
uchar i;
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
      Flash_Send_Byte(0x03);      /* read command */   
                for(i=0;i<3;i++)
                {
                  Flash_Send_Byte(add);
                }
                for(i=0;i<size;i++)
                {
       R_dat=Flash_Get_Byte();   ///secd data to flash
                }
PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);

}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Flash_init()            /* 程序功能:    用来将时钟线初始化为低. 必须在将设备设置为模式0之前调用*/
{   
          stc_port_init_t stcPortInit;

    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcPortInit);

    stcPortInit.enPinMode = Pin_Mode_Out;
    stcPortInit.enExInt = Enable;
    stcPortInit.enPullUp = Enable;
                PORT_Init(SPI_CLK_Port, SPI_CLK_Pin, &stcPortInit);
                PORT_Init(SPI_MISI_Port, SPI_MISI_Pin, &stcPortInit);
                PORT_Init(SPI_CS_Port, SPI_CS_Pin, &stcPortInit);
                PORT_Init(SPI_WR_Port, SPI_WR_Pin, &stcPortInit);
       
                  stc_port_init_t stcPortInit_in;

    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcPortInit_in);

    stcPortInit_in.enPinMode = Pin_Mode_In;
    stcPortInit_in.enExInt = Enable;
    stcPortInit_in.enPullUp = Enable;
        PORT_Init(SPI_MISO_Port, SPI_MISO_Pin, &stcPortInit_in);

          char i;   
           // P7 |= 0x7f; /* 设置SCK为低电平初始化状态 */   
           PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
          for(i=255;i>0;i--);   
           // P7 &= 0x80;   
           PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin);
}   

void Flash_WREN_Check(void)                  /* 功能: 检查擦写操作前WEL位是否为1*/   
{   
          uchar byte;   
          byte = Flash_Read_Status_Register();/* 读取状态register */   
          if ((byte&0x02) != 0x02)      /* 检查WEL位置位 */   
          {   
                Flash_WREN();   
                    //如果未置1进行相应处理,如对其进行写使得操作   
          }   
}   

void Flash_Chip_Erase(void)              /* 功能: 擦除整个芯片               */
{   
        Flash_EWSR();
        Flash_WRSR(0);//(Read_Status_Register())&0x83 );


          Flash_WREN_Check();   
          PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);         
          Flash_Send_Byte(0xc7);            /* 发送 Chip Erase命令 (60h or C7h) */   
                  PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);
          Flash_Wait_Busy();      
          //CE =1;               
}   

void Flash_Sector_Erase(ulong Dst)   /* 功能: Sector Erases the Chip.   4K         */
{   
          uchar i;   
          Flash_WREN_Check();   
          Flash_init();   
          PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);               
          Flash_Send_Byte(0x20);            /* 发送Sector Erase 命令 */   
          Flash_Send_Byte(((Dst & 0xFFFFFF) >> 16));/* 发送地址 */   
          Flash_Send_Byte(((Dst & 0xFFFF) >> 8));   
          Flash_Send_Byte(Dst & 0xFF);   
          for(i=100;i>0;i--);   
          PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);   
          Flash_Wait_Busy();
        //        CS=1;            
}   




天天向善 发表于 2022-9-15 11:30

看代码的样子应该没问题,所以读写成功了吧?

Bowclad 发表于 2022-9-16 19:01

读写成功了吗
页: [1]
查看完整版本: HC32F460单片机写SPIFlash