Stm32的io口模拟spi例程分析
微信ID:niceli123
以下是硬件电路图,主芯片为stm32rbt6.
贴上代码
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; } }
最新评论