Stm32的io口模拟spi例程分析



微信ID:niceli123


以下是硬件电路图,主芯片为stm32rbt6.

1.jpg

贴上代码

void SPI_FLASH_Init1(void)//io初始化配置
{

  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_9;//CS  CLK
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //MOSI要用模拟输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//MISO
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

//关键在读取函数
//包括读取和发送
u8 SPIx_FLASH_SendByte(u8 byte)
{
uint8_t i; 
u8 Temp=0x00;
unsigned char SDI; 
    for (i = 0; i < 8; i++)
    {
       GPIO_SetBits(GPIOC, GPIO_Pin_9);//sclk = 0;//先将时钟拉高
        if (byte&0x80)      
        {
          GPIO_SetBits(GPIOC, GPIO_Pin_7); //    //SO=1 
        }
        else
        {
           GPIO_ResetBits(GPIOC, GPIO_Pin_7);//     //SO=0
        }
         byte <<= 1;  
         GPIO_ResetBits(GPIOC, GPIO_Pin_9);//    //sclk = 1; 拉低时钟
         SDI = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8);//判断si是否有输入
         Temp<<=1;

if(SDI)       //读到1时
{
Temp++;  //置1  即向右移动一位同时加1   因上边有<<=1
}
         GPIO_SetBits(GPIOC, GPIO_Pin_9);//sclk = 0;//   拉高时钟 
    }

    return Temp; //返回读到miso输入的值     

}          
}
//下面是以读写spi flash为例具体的实现
//此函数中 时钟机时序很重要。Cs在读写中只能出现一次,不能在sendwrite
//读写里边有,被调用时还出现,就肯定不行了。
//其它函数宏定义
#define BUFFER_1_WRITE 0x84                 // buffer 1 write
#define BUFFER_2_WRITE 0x87                 // buffer 2 write
#define BUFFER_1_READ  0x54                          // buffer 1 read (change to 0xD4 for SPI mode 0,3)
#define BUFFER_2_READ  0x56                          // buffer 2 read (change to 0xD6 for SPI mode 0,3)
#define B1_TO_PAGE_WITH_ERASE 0x83                   // buffer 1 to main memory page program with built-in erase
#define B2_TO_PAGE_WITH_ERASE 0x86                   // buffer 2 to main memory page program with built-in erase
#define B1_TO_PAGE_WITHOUT_ERASE 0x88          // buffer 1 to main memory page program without built-in erase
#define B2_TO_PAGE_WITHOUT_ERASE 0x89          // buffer 2 to main memory page program without built-in erase
#define PAGE_PROG_THROUGH_B1 0x82                  // main memory page program through buffer 1
#define PAGE_PROG_THROUGH_B2 0x85                  // main memory page program through buffer 2
#define AUTO_PAGE_REWRITE_THROUGH_B1 0x58   // auto page rewrite through buffer 1
#define AUTO_PAGE_REWRITE_THROUGH_B2 0x59   // auto page rewrite through buffer 2
#define PAGE_TO_B1_COMP 0x60                     // main memory page compare to buffer 1
#define PAGE_TO_B2_COMP 0x61                     // main memory page compare to buffer 2
#define PAGE_TO_B1_XFER 0x53             // main memory page to buffer 1 transfer
#define PAGE_TO_B2_XFER 0x55             // main memory page to buffer 2 transfer
#define STATUS_REGISTER 0x57               
#define MAIN_MEMORY_PAGE_READ 0x52          // main memory page read (change to 0xD2 for SPI mode 0,3)
#define PAGE_ERASE 0x81                     // erase a 264 byte page
#define BULK_ERASE 0x50                     // erase 8 pages
#define WIP_Flag   0x80                    
#define Dummy_Byte 0xA5
AT45DB系列的读写函数
void AT45xxReadx(uint32_t Num,uint32_t PageAddr, uint32_t ByteAddr, uint8_t *
Data, uint32_t ByteNum)
{

    SPIx_FLASH_PageToBuffer2(Num,PageAddr);

    SPIx_FLASH_Buffer2Read(Num,Data, ByteAddr, ByteNum);

}
写函数
void AT45xxWritex(uint32_t Num,uint32_t PageAddr, uint32_t ByteAddr, u8 *Data
, uint32_t ByteNum)
{
    uint32_t i; 
         u8 aa[100];     

    if((ByteNum <= (528 - ByteAddr))&&(ByteNum > 0))
    {
        SPIx_FLASH_WaitForWriteEnd(Num);
         //  while(!(Rat45_status()& 0x80 )); //判断是否忙

        SPIx_FLASH_CS_LOW(Num);

        SPIx_FLASH_SendByte(Num,0x82);
         //      SPIx_ReadWriteByte(0x82);

         //      SPIx_ReadWriteByte((uint8_t)(PageAddr>>6));
         //      SPIx_ReadWriteByte((uint8_t)((PageAddr<<2)|(ByteAddr>>8)));
         //      SPIx_ReadWriteByte((uint8_t)ByteAddr);
        SPIx_FLASH_SendByte(Num,(uint8_t)(PageAddr>>6));
        SPIx_FLASH_SendByte(Num,(uint8_t)((PageAddr<<2)|(ByteAddr>>8)));
        SPIx_FLASH_SendByte(Num,(uint8_t)ByteAddr);

        for(i = 0; i < ByteNum; i++)
        {
            SPIx_FLASH_SendByte(Num,Data[i]);
                   //      SPIx_ReadWriteByte(Data[i]);
         //      SPIx_FLASH_SendByte(Num,Data[i]);
        }

        SPIx_FLASH_CS_HIGH(Num);                    
    }
}

void SPIx_FLASH_WaitForWriteEnd(uint32_t Num)
{
  unsigned char FLASH_Status = 0;

  SPIx_FLASH_CS_LOW(Num);

  SPIx_FLASH_SendByte(Num,STATUS_REGISTER);

  do
  {

    FLASH_Status = SPIx_FLASH_SendByte(Num,Dummy_Byte);

  }
  while ((FLASH_Status & WIP_Flag) == RESET);

  SPIx_FLASH_CS_HIGH(Num);
}

void SPIx_FLASH_Buffer2Read(uint32_t Num,u8* pBuffer, u32 ReadAddr, u16 
NumByteToRead)
{

  SPIx_FLASH_WaitForWriteEnd(Num);
 // while(!(Rat45_status()& 0x80 )); //判断是否忙

  SPIx_FLASH_CS_LOW(Num);

  SPIx_FLASH_SendByte(Num,BUFFER_2_READ);

  SPIx_FLASH_SendByte(Num,Dummy_Byte);

  SPIx_FLASH_SendByte(Num,(ReadAddr& 0xFF00) >> 8);

  SPIx_FLASH_SendByte(Num,ReadAddr & 0xFF);

  SPIx_FLASH_SendByte(Num,Dummy_Byte);//

  while (NumByteToRead--)
  {

    *pBuffer = SPIx_FLASH_SendByte(Num,Dummy_Byte);

    pBuffer++;
  }

  SPIx_FLASH_CS_HIGH(Num);
}   

void SPIx_FLASH_CS_LOW(uint32_t Num)
{
   switch(Num)
   {
     case 0:  GPIO_ResetBits(GPIOB, GPIO_Pin_12); break;
     case 1: GPIO_ResetBits(GPIOA, GPIO_Pin_8); break;  //U6
          case 2: GPIO_ResetBits(GPIOA, GPIO_Pin_7);     break;   //U7
      case 3: GPIO_ResetBits(GPIOA, GPIO_Pin_3);     break;       //U8
      case 4: GPIO_ResetBits(GPIOC, GPIO_Pin_3); break;          //U9
          default:break;
   }

}

void SPIx_FLASH_CS_HIGH(uint32_t Num)
{
   switch(Num)
   {
     case 0:  GPIO_SetBits(GPIOB, GPIO_Pin_12);  break;
     case 1: GPIO_SetBits(GPIOA, GPIO_Pin_8); break;       //U6
          case 2: GPIO_SetBits(GPIOA, GPIO_Pin_7); break;   //U7
      case 3: GPIO_SetBits(GPIOA, GPIO_Pin_3); break;       //U8
      case 4: GPIO_SetBits(GPIOC, GPIO_Pin_3); break;     //U9
          default:break;
   }
}

最新评论

  1. 发布于:2015-12-09 13:18 回复
    关注本网站更多资源开放!开发工具软件会逐步在右侧分类中的【开发工具】栏中更新!
  2. 发布于:2015-08-21 15:49 回复
    该部分内容已经更新过

sitemap