esp8266 RTOS驱动 MX25L12835E

esp8266 RTOS驱动 MX25L12835E

硬件方面 MX251L12835E的 RESET引脚与WP引脚要接入高电平(3.3V),其它对着连就好了
因esp8266 RTOS下的SPI传输只能最多64位字节,另外其传输时是低位先行。
无奈的调试了一多次,完成如下代码,具体的请各位大神自己体会吧
已知写入前要保证存储的内容已重置

头文件user_25l12835.h

#ifndef _USER_25L12835E_h_
#define _USER_25L12835E_h_
/*
 *使用说明
 * uint8_t send_data[] = "abcdafghejklimopnrstqvwsuz";
 * uint8_t Read_data[313];
 * user_spi_master_init();
 * get_Manufacturer_ID();
 * SPI_FLASH_SectorErase(FLASH_WriteAddress);
 * SPI_FLASH_BufferWrite(send_data,FLASH_WriteAddress,countof(send_data)-1);
 * SPI_FLASH_BufferRead(Read_data,FLASH_WriteAddress,countof(Read_data)-1);
 * Read_data[313-1] ='\0'; //字符串与字节类型注意一下
 * user_uart0_print ("data=%s\r\n",Read_data);
 * vTaskDelay(1000);
 * user_uart0_print ("OK");
*/

#define SPI_FLASH_PageSize              256
#define SPI_FLASH_Transport_MAX_Size    64 //esp8266一次只能送输64字节
#define W25l_WriteEnable		      0x06 //写入模式使能
#define W25l_WriteDisable		      0x04 
#define W25l_ReadStatusReg		      0x05 //寄存器状态
#define W25l_WriteStatusReg		      0x01 
#define W25l_ReadData			      0x03 //读取数据
#define W25l_FastReadData		      0x0B 
#define W25l_FastReadDual		      0x3B 
#define W25l_PageProgram		      0x02 //写入一页的数据
#define W25l_BlockErase			      0xD8 //擦除块
#define W25l_SectorErase		      0x20 //擦除扇区
#define W25l_ChipErase			      0xC7 //擦除整个falsh
#define W25l_PowerDown			      0xB9 
#define W25l_ReleasePowerDown	      0xAB 
#define W25l_DeviceID			      0xAB 
#define W25l_ManufactDeviceID   	  0x90 
#define W25l_JedecDeviceID		      0x9F
#define W25l_Block_Unlock             0x98

esp_err_t user_spi_master_init();
void  get_Manufacturer_ID();
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void get_flash_status();
void FLASH_Write_Enable();
void FLASH_Block_Unlock();
void SPI_FLASH_ChipErase();
void SPI_FLASH_WaitForWriteEnd();
void SPI_FLASH_SectorErase(uint32_t sector_addr);
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);

#endif

C文件

#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/stream_buffer.h"

#include "esp8266/spi_struct.h"

#include "esp8266/gpio_struct.h"
#include "esp_system.h"
#include "esp_log.h"
#include "user_uart.h"
#include "driver/gpio.h"
#include "driver/spi.h"
#include "user_25l12835e.h"

#include "time.h"
//反转32bit位
void turnbit(uint32_t*nun,uint32_t len)
{
  for (size_t i = 0; i < (len/4); i++)
  {
  *nun= (((*nun & 0xff00ff00) >> 8) | ((*nun& 0x00ff00ff) << 8));
  *nun= *nun>>16|*nun<<16;
  nun++;
  }
}
//这里的事件为空的
static void  spi_event_callback(int event, void *arg)
{
  switch (event) {
        case SPI_INIT_EVENT: {
 
        }
        break;
 
        case SPI_TRANS_START_EVENT: {
        }
        break;
 
        case SPI_TRANS_DONE_EVENT: {
 
        }
        break;
 
        case SPI_DEINIT_EVENT: {
        }
        break;
    }
}
//初始化spi接口
esp_err_t user_spi_master_init()
{
    spi_config_t spi_config;
  // 加载默认配置
  // CS_EN:1, MISO_EN:1, MOSI_EN:1, BYTE_TX_ORDER:1, BYTE_TX_ORDER:1, BIT_RX_ORDER:0, BIT_TX_ORDER:0, CPHA:0, CPOL:0
  spi_config.interface.val = SPI_DEFAULT_INTERFACE;
  spi_config.intr_enable.val = SPI_MASTER_DEFAULT_INTR_ENABLE;
  spi_config.interface.cpol = 1;
  spi_config.interface.cpha = 1;
  spi_config.mode = SPI_MASTER_MODE;
  spi_config.clk_div = SPI_8MHz_DIV;
  spi_config.event_cb = spi_event_callback;   // 注册回调函数,这里没什么用处!
  return spi_init(HSPI_HOST, &spi_config);
}
//写入模式使能
void  FLASH_Write_Enable()
{
    uint16_t data_cmd =W25l_WriteEnable;
    spi_trans_t trans;
    trans.cmd = &data_cmd;
    trans.bits.val = 0;
    trans.bits.cmd = 8;
    trans.bits.addr = 0;
    trans.bits.mosi = 0;
    trans.bits.miso = 0;   
    spi_trans(HSPI_HOST, &trans);
}
//块去保护
void  FLASH_Block_Unlock()
{
    uint16_t data_cmd =W25l_Block_Unlock;
    spi_trans_t trans;
    trans.cmd = &data_cmd;
    trans.bits.val = 0;
    trans.bits.cmd = 8;
    trans.bits.addr = 0;
    trans.bits.mosi = 0;
    trans.bits.miso = 0;   
    spi_trans(HSPI_HOST, &trans);
}
//擦除整个Flash
void SPI_FLASH_ChipErase()
{
    FLASH_Write_Enable();
    uint16_t data_cmd=W25l_ChipErase;
    //uint32_t data_addr = sector_addr<<8;//转换24位为32位
    spi_trans_t trans;
    trans.cmd = &data_cmd;
  //  trans.addr = &data_addr;
    trans.bits.val = 0;
    trans.bits.cmd = 8;
    trans.bits.addr = 0;
    trans.bits.mosi = 0;
    trans.bits.miso = 0;
    spi_trans(HSPI_HOST, &trans);
}

//擦除指定地址的扇区(注意地址为32位,请补全后面二位)
void SPI_FLASH_SectorErase(uint32_t sector_addr)
{
    FLASH_Write_Enable();
    uint16_t data_cmd=W25l_SectorErase;
    uint32_t data_addr = sector_addr<<8;//转换24位为32位
    spi_trans_t trans;
    trans.cmd = &data_cmd;
    trans.addr = &data_addr;
    trans.bits.val = 0;
    trans.bits.cmd = 8;
    trans.bits.addr = 8*3;
    trans.bits.mosi = 0;
    trans.bits.miso = 0;
    spi_trans(HSPI_HOST, &trans);
}

void SPI_FLASH_WaitForWriteEnd()
{
  uint32_t get_data;
  uint16_t data_cmd =W25l_ReadStatusReg;
  spi_trans_t trans;
  trans.miso = &get_data;
  trans.cmd = &data_cmd;
  // trans.addr = &data_add;
  trans.bits.val = 0;
  trans.bits.cmd = 8;
  trans.bits.addr = 0;
  trans.bits.mosi = 0;
  trans.bits.miso = 8;
  do{
  spi_trans(HSPI_HOST, &trans);
 vTaskDelay(1);
  } while ((get_data&0x01)==0x01);
}
//取得flash的ID号
void  get_Manufacturer_ID()
{
  SPI_FLASH_WaitForWriteEnd();//等待BUSY标志位被置0
        spi_trans_t trans;
        uint32_t get_data;
        uint32_t data_add = 0x12345600; //3*8位地址补全后面二位,不然不正确
        uint16_t data_cmd =W25l_ManufactDeviceID;
        trans.miso = &get_data;
        trans.cmd = &data_cmd;
        trans.addr = &data_add;
        trans.bits.val = 0;
        trans.bits.cmd = 8;
        trans.bits.addr = 8*3;
        trans.bits.mosi = 0;
        trans.bits.miso = 8*2;
     spi_trans(HSPI_HOST, &trans);     
    user_uart0_print("Manufacturer ID =%#x,Device ID=%#x\r\n",(get_data&0x0000ff00)>>8,get_data&0x000000ff);
}

//单次传输出去的数据 u单次不能超SPI_FLASH_Transport_MAX_Size64位
void SPI_FLASH_Transfer_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
    SPI_FLASH_WaitForWriteEnd();//等待BUSY标志位被置0
    FLASH_Write_Enable(); //写入使能
    uint16_t data_cmd =W25l_PageProgram;//写入代码
    uint32_t data_add =WriteAddr<<8; //3*8位地址补全后面二位,不然不正确(这里的writeadd位移8位,24转32位的数据)
    uint32_t write_data[16];
    memset(write_data,0,sizeof(write_data));
    uint32_t * P_write_data =write_data;
     for (size_t i = 0; i < NumByteToWrite; i++)
    {
        if((i)%4 ==0 && i!=0)
        {
            P_write_data++;
        }
        //因为esp8266是低位先发,所以高位放到32位的低位
        *P_write_data = (*pBuffer)<<((i%4)*8)|*P_write_data;
        pBuffer++;
    }
    spi_trans_t trans;
     P_write_data =write_data; 
    trans.mosi = P_write_data;
    trans.cmd = &data_cmd;
    trans.addr = &data_add;
    trans.bits.val = 0;
    trans.bits.cmd = 8;
    trans.bits.addr = 8*3;
    trans.bits.mosi = 8*NumByteToWrite;

    spi_trans(HSPI_HOST, &trans);
}

 /**
  * @brief  对FLASH按页写入数据,调用本函数写入数据前需要先擦除扇区
  * @param	pBuffer,要写入数据的指针
  * @param WriteAddr,写入地址
  * @param  NumByteToWrite,写入数据长度,因为esp8266的问题,不能超过SPI_FLASH_Transport_MAX_Bit/8=64
  * @retval 无
  */
void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
    uint8_t NumOfTransfer  = 0, /*计算出要传送几次*/
    NumOfSingle = 0; /*计算出剩余不满一页的字节数*/
    NumOfTransfer =  NumByteToWrite / SPI_FLASH_Transport_MAX_Size;	
    NumOfSingle = NumByteToWrite % SPI_FLASH_Transport_MAX_Size;
    if (NumOfTransfer==0)
    {
      SPI_FLASH_Transfer_Write(pBuffer, WriteAddr, NumByteToWrite);
    }
    else
    {
      while (NumOfTransfer--)
      {
        SPI_FLASH_Transfer_Write(pBuffer, WriteAddr, SPI_FLASH_Transport_MAX_Size);
        WriteAddr +=  SPI_FLASH_Transport_MAX_Size;
        pBuffer += SPI_FLASH_Transport_MAX_Size;
      }
      if (NumOfSingle != 0)
      {
        SPI_FLASH_Transfer_Write(pBuffer, WriteAddr, NumOfSingle);
      }
    }
}
 /**
  * @brief  对FLASH按页写入数据,调用本函数写入数据前需要先擦除扇区
  * @param	pBuffer,要写入数据的指针
  * @param WriteAddr,写入地址为24位的地址,如0x00100,增加一页等于0x00100+256(0x00100)得到第二页的地址
  * @param  NumByteToWrite,写入数据长度
  * @retval 无
  */
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
    uint8_t NumOfPage = 0, /*计算出要写多少整数页*/
    NumOfSingle = 0, /*计算出剩余不满一页的字节数*/
    Addr = 0, //地址偏移量,用于看地址是否对齐 判定是否为0x00100这样的地址
    count = 0,/*差count个数据值,刚好可以对齐到页地址*/
     temp = 0;
	/*mod运算求余,若writeAddr是SPI_FLASH_PageSize整数倍,运算结果Addr值为0*/
  Addr = WriteAddr % SPI_FLASH_PageSize;	
  count = SPI_FLASH_PageSize - Addr;
  NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;	
  NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
	
	/* Addr=0,则WriteAddr 刚好按页对齐 aligned  */
  if (Addr == 0)
  {
		/* NumByteToWrite < SPI_FLASH_PageSize */
    if (NumOfPage == 0) 
    {
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
    }
    else /* NumByteToWrite > SPI_FLASH_PageSize */
    { 
			/*先把整数页都写了*/
      while (NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }
			/*若有多余的不满一页的数据,把它写完*/
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
    }
  }
	/* 若地址与 SPI_FLASH_PageSize 不对齐  */
  else 
  {
		/* NumByteToWrite < SPI_FLASH_PageSize */
    if (NumOfPage == 0)
    {
			/*当前页剩余的count个位置比NumOfSingle小,一页写不完*/
      if (NumOfSingle > count) 
      {
        temp = NumOfSingle - count;
				/*先写满当前页*/
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
				
        WriteAddr +=  count;
        pBuffer += count;
				/*再写剩余的数据*/
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
      }
      else /*当前页剩余的count个位置能写完NumOfSingle个数据*/
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
      }
    }
    else /* NumByteToWrite > SPI_FLASH_PageSize */
    {
			/*地址不对齐多出的count分开处理,不加入这个运算*/
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
      NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
			
			/* 先写完count个数据,为的是让下一次要写的地址对齐 */
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
			
			/* 接下来就重复地址对齐的情况 */
      WriteAddr +=  count;
      pBuffer += count;
			/*把整数页都写了*/
      while (NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }
			/*若有多余的不满一页的数据,把它写完*/
      if (NumOfSingle != 0)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      }
    }
  }
}

//读取单次传输数据最多64字节 
void SPI_FLASH_Transfer_Read(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
    //FLASH_Write_Enable(); //写入使能
    uint16_t data_cmd =W25l_ReadData;
    uint32_t data_add = ReadAddr<<8; //3*8位地址补全后面二位,不然不正确
    spi_trans_t trans;
    uint32_t get_data[16];
    uint32_t * p_get_data =get_data;
    memset(get_data,0,sizeof(get_data));
    trans.miso = p_get_data;
    trans.cmd = &data_cmd;
    trans.addr = &data_add;
    trans.bits.val = 0;
    trans.bits.cmd = 8;
    trans.bits.addr = 8*3;
    trans.bits.mosi = 0;
    trans.bits.miso = 8*NumByteToRead;//最多512bit
    spi_trans(HSPI_HOST, &trans);
   // turnbit(get_data,sizeof(get_data));
    p_get_data =get_data;
    //user_uart0_print("p_get_data=%x",*p_get_data);
    for (size_t i = 0; i < NumByteToRead; i++)
    {
      if((i)%4 ==0 && i!=0)
        {
            p_get_data++;
        }
      //因为esp8266是低位先发,所以高位放到32位的低位
      *pBuffer = (*p_get_data>>((i%4)*8))&0x000000ff; 
      pBuffer++;
    }

       
}
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
  SPI_FLASH_WaitForWriteEnd();//等待BUSY标志位被置0
  // uint8_t tempbuffer[SPI_FLASH_Transport_MAX_Size];
  
  uint8_t   NumOfTransfer  = 0, /*计算出要传送几次*/
    NumOfSingle = 0; /*计算出剩余不满一页的字节数*/
    NumOfTransfer =  NumByteToRead / SPI_FLASH_Transport_MAX_Size;	
    NumOfSingle = NumByteToRead % SPI_FLASH_Transport_MAX_Size;
    /*mod运算求余,若writeAddr是SPI_FLASH_PageSize整数倍,运算结果Addr值为0*/

   if(NumOfTransfer==0)
   {
   SPI_FLASH_Transfer_Read(pBuffer, ReadAddr, NumByteToRead);
   }
   else
   {
     for (size_t i = 0; i < NumOfTransfer; i++)
    {
      SPI_FLASH_Transfer_Read(pBuffer, ReadAddr, SPI_FLASH_Transport_MAX_Size);
      ReadAddr +=  SPI_FLASH_Transport_MAX_Size;
      pBuffer += SPI_FLASH_Transport_MAX_Size;    
    }
    if (NumOfSingle != 0)
    {
      SPI_FLASH_Transfer_Read(pBuffer, ReadAddr, NumOfSingle);
    }    
   }  

}



void get_flash_status()
{
    uint32_t data ='\0';
    spi_slave_get_status(HSPI_HOST, &data);
    user_uart0_print ("status=%x",data);
} 

posted @ 2020-07-17 16:33  天祈笨笨  阅读(404)  评论(0编辑  收藏  举报