//写W25QXX状态寄存器 //只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!! void W25QXX_Write_SR(u8 sr) { W25QXX_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_WriteStatusReg);//发送写取状态寄存器命令 SPI2_ReadWriteByte(sr); //写入一个字节 W25QXX_CS=1; //取消片选 }
//写SPI_FLASH状态寄存器 //只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!! void SPI_FLASH_Write_SR(u8 sr) { SPI_FLASH_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_WriteStatusReg); //发送写取状态寄存器命令 SPI2_ReadWriteByte(sr); //写入一个字节 SPI_FLASH_CS=1; //取消片选 }
//在指定位置写指定长度的数据 //reg:寄存器(位置) //*pBuf:数据指针 //len:数据长度 //返回值,此次读到的状态寄存器值 u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len) { u8 status,u8_ctr; NRF24L01_CSN = 0; //使能SPI传输 status = SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值 for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI2_ReadWriteByte(*pBuf++); //写入数据 NRF24L01_CSN = 1; //关闭SPI传输 return status; //返回读到的状态值 }
//在指定位置读出指定长度的数据 //reg:寄存器(位置) //*pBuf:数据指针 //len:数据长度 //返回值,此次读到的状态寄存器值 u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len) { u8 status,u8_ctr; NRF24L01_CSN_LOW //使能SPI传输 status=SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值 for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI2_ReadWriteByte(0XFF);//读出数据 NRF24L01_CSN_HIGH //关闭SPI传输 return status; //返回读到的状态值 }
//SPI写寄存器 //reg:指定寄存器地址 //value:写入的值 u8 NRF24L01_Write_Reg(u8 reg,u8 value) { u8 status; NRF24L01_CSN=0; //使能SPI传输 status =SPI2_ReadWriteByte(reg);//发送寄存器号 SPI2_ReadWriteByte(value); //写入寄存器的值 NRF24L01_CSN=1; //禁止SPI传输 return(status); //返回状态值 }
//Write ENC28J60 register //op: command //addr: register address //data: parameter to write void ENC28J60_Write_Op(u8 op,u8 addr,u8 data) { u8 dat = 0; ENC28J60_SELECT(); dat=op|(addr&ADDR_MASK); SPI2_ReadWriteByte(dat); SPI2_ReadWriteByte(data); ENC28J60_NO_SELECT(); }
//读取SPI寄存器值 //reg:要读的寄存器 u8 NRF24L01_Read_Reg(u8 reg) { u8 reg_val; NRF24L01_CSN = 0; //使能SPI传输 SPI2_ReadWriteByte(reg); //发送寄存器号 reg_val=SPI2_ReadWriteByte(0XFF);//读取寄存器内容 NRF24L01_CSN = 1; //禁止SPI传输 return(reg_val); //返回状态值 }
//读取SPI_FLASH的状态寄存器 //BIT7 6 5 4 3 2 1 0 //SPR RV TB BP2 BP1 BP0 WEL BUSY //SPR:默认0,状态寄存器保护位,配合WP使用 //TB,BP2,BP1,BP0:FLASH区域写保护设置 //WEL:写使能锁定 //BUSY:忙标记位(1,忙;0,空闲) //默认:0x00 u8 SPI_Flash_ReadSR(void) { u8 byte=0; SPI_FLASH_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令 byte=SPI2_ReadWriteByte(0Xff); //读取一个字节 SPI_FLASH_CS=1; //取消片选 return byte; }
//读取W25QXX的状态寄存器 //BIT7 6 5 4 3 2 1 0 //SPR RV TB BP2 BP1 BP0 WEL BUSY //SPR:默认0,状态寄存器保护位,配合WP使用 //TB,BP2,BP1,BP0:FLASH区域写保护设置 //WEL:写使能锁定 //BUSY:忙标记位(1,忙;0,空闲) //默认:0x00 u8 W25QXX_ReadSR(void) { u8 byte=0; W25QXX_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令 byte=SPI2_ReadWriteByte(0Xff); //读取一个字节 W25QXX_CS=1; //取消片选 return byte; }
//Write data to send via ENC28J60 //len: data length to send //data: data pointer void ENC28J60_Write_Buf(u32 len,u8* data) { ENC28J60_SELECT(); SPI2_ReadWriteByte(ENC28J60_WRITE_BUF_MEM); while(len) { len--; SPI2_ReadWriteByte(*data); data++; } ENC28J60_NO_SELECT(); }
//SPI在一页(0~65535)内写入少于256个字节的数据 //在指定地址开始写入最大256字节的数据 //pBuffer:数据存储区 //WriteAddr:开始写入的地址(24bit) //NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!! void W25QXX_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) { u16 i; W25QXX_Write_Enable(); //SET WEL W25QXX_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_PageProgram); //发送写页命令 SPI2_ReadWriteByte((u8)((WriteAddr)>>16)); //发送24bit地址 SPI2_ReadWriteByte((u8)((WriteAddr)>>8)); SPI2_ReadWriteByte((u8)WriteAddr); for(i=0;i<NumByteToWrite;i++)SPI2_ReadWriteByte(pBuffer[i]);//循环写数 W25QXX_CS=1; //取消片选 W25QXX_Wait_Busy(); //等待写入结束 }
//Read ENC28J60 register //op: command //addr: register address //return: read out data u8 ENC28J60_Read_Op(u8 op,u8 addr) { u8 dat=0; ENC28J60_SELECT(); dat=op|(addr&ADDR_MASK); SPI2_ReadWriteByte(dat); dat=SPI2_ReadWriteByte(0xFF); //datasheet p.29, read two times to get MAC/MII register value if(addr&0x80)dat=SPI2_ReadWriteByte(0xFF); ENC28J60_NO_SELECT(); return dat; }
//Read Rx buffer data from ENC28J60 //len: data length to read //data: pointer to store data void ENC28J60_Read_Buf(u32 len,u8* data) { ENC28J60_SELECT(); SPI2_ReadWriteByte(ENC28J60_READ_BUF_MEM); while(len) { len--; *data=(u8)SPI2_ReadWriteByte(0); data++; } *data='\0'; //add end char ENC28J60_NO_SELECT(); }
void initial_HMC5983() { GPIO_ResetBits(GPIOB,GPIO_Pin_12); DELAY_mS(1); SPI2_ReadWriteByte(0x00); SPI2_ReadWriteByte(0xfc); GPIO_SetBits(GPIOB,GPIO_Pin_12); GPIO_ResetBits(GPIOB,GPIO_Pin_12); DELAY_mS(1); SPI2_ReadWriteByte(0x02); SPI2_ReadWriteByte(0x00); GPIO_SetBits(GPIOB,GPIO_Pin_12); }
//读取SPI FLASH //在指定地址开始读取指定长度的数据 //pBuffer:数据存储区 //ReadAddr:开始读取的地址(24bit) //NumByteToRead:要读取的字节数(最大65535) void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) { u16 i; W25QXX_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_ReadData); //发送读取命令 SPI2_ReadWriteByte((u8)((ReadAddr)>>16)); //发送24bit地址 SPI2_ReadWriteByte((u8)((ReadAddr)>>8)); SPI2_ReadWriteByte((u8)ReadAddr); for(i=0;i<NumByteToRead;i++) { pBuffer[i]=SPI2_ReadWriteByte(0XFF); //循环读数 } W25QXX_CS=1; }
//擦除一个扇区 //Dst_Addr:扇区地址 根据实际容量设置 //擦除一个山区的最少时间:150ms void W25QXX_Erase_Sector(u32 Dst_Addr) { //监视falsh擦除情况,测试用 printf("fe:%x\r\n",Dst_Addr); Dst_Addr*=4096; W25QXX_Write_Enable(); //SET WEL W25QXX_Wait_Busy(); W25QXX_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_SectorErase); //发送扇区擦除指令 SPI2_ReadWriteByte((u8)((Dst_Addr)>>16)); //发送24bit地址 SPI2_ReadWriteByte((u8)((Dst_Addr)>>8)); SPI2_ReadWriteByte((u8)Dst_Addr); W25QXX_CS=1; //取消片选 W25QXX_Wait_Busy(); //等待擦除完成 }
//唤醒 void W25QXX_WAKEUP(void) { W25QXX_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB W25QXX_CS=1; //取消片选 delay_us(3); //等待TRES1 }
//唤醒 void SPI_Flash_WAKEUP(void) { SPI_FLASH_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB SPI_FLASH_CS=1; //取消片选 delay_us(3); //等待TRES1 }
void SPI2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB1Periph_SPI2, ENABLE );//GPIOA 时钟使能//SPI1 时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //GPIOA 5 6 7复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA GPIO_SetBits(GPIOA,GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7); //GPIOA 5 6 7上拉 // LOW 2 有反应 测试多次 注意接口按紧 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为 低电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第1个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 SPI_Cmd(SPI2, ENABLE); //使能SPI外设 SPI2_ReadWriteByte(0xff);//启动传输 }
//进入掉电模式 void W25QXX_PowerDown(void) { W25QXX_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_PowerDown); //发送掉电命令 W25QXX_CS=1; //取消片选 delay_us(3); //等待TPD }
//进入掉电模式 void SPI_Flash_PowerDown(void) { SPI_FLASH_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_PowerDown); //发送掉电命令 SPI_FLASH_CS=1; //取消片选 delay_us(3); //等待TPD }
void SPI2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 SPI_Cmd(SPI2, ENABLE); //使能SPI外设 SPI2_ReadWriteByte(0xff);//启动传输 }
/******************************************************************************* ** 函数名称: SPI2_Init ** 功能描述: SPI口初始化代码 ** 输 入: 无 ** 返 回: 无 ** 注 意: 配置成主机模式 ,对SPI2属于APB1的外设.时钟频率最大为36M. *******************************************************************************/ void SPI2_Init(void) { RCC->APB1RSTR |= 1<<14; RCC->APB1RSTR &= ~(1<<14); RCC->APB2ENR |= 1<<3; //PORTB时钟使能 RCC->APB1ENR |= 1<<14; //SPI2时钟使能 GPIOB->CRH &= 0X000FFFFF; GPIOB->CRH |= 0XBBB00000; //PB13/14/15复用 GPIOB->ODR |= 0X7<<13; //PB13/14/15上拉 SPI2->CR1 |= 0<<10; //全双工模式 SPI2->CR1 |= 1<<9; //软件nss管理 SPI2->CR1 |= 1<<8; SPI2->CR1 |= 1<<2; //SPI主机 SPI2->CR1 |= 0<<11; //8bit数据格式 //SPI2->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1 //SPI2->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1 //对SPI2属于APB1的外设.时钟频率最大为36M. SPI2->CR1 |= 3<<3; //Fsck=Fpclk1/256 SPI2->CR1 |= 0<<7; //MSBfirst SPI2->CR1 |= 1<<6; //SPI设备使能 SPI2_ReadWriteByte(0xff); //启动传输 }
void read_HMC5983(s16* MAG) { u8 tmpBuffer_5983[6]; GPIO_ResetBits(GPIOB,GPIO_Pin_12); DELAY_mS(1); SPI2_ReadWriteByte(0xC3); tmpBuffer_5983[0] = SPI2_ReadWriteByte(0x00); tmpBuffer_5983[1] = SPI2_ReadWriteByte(0x00); tmpBuffer_5983[2] = SPI2_ReadWriteByte(0x00); tmpBuffer_5983[3] = SPI2_ReadWriteByte(0x00); tmpBuffer_5983[4] = SPI2_ReadWriteByte(0x00); tmpBuffer_5983[5] = SPI2_ReadWriteByte(0x00); DELAY_mS(1); GPIO_SetBits(GPIOB,GPIO_Pin_12); /* Get magne rate */ for(int i=0; i<3; i++) MAG[i]=((s16)((u16)tmpBuffer_5983[2*i] << 8) + tmpBuffer_5983[2*i+1]); }
//擦除整个芯片 //等待时间超长... void SPI_Flash_Erase_Chip(void) { SPI_FLASH_Write_Enable(); //SET WEL SPI_Flash_Wait_Busy(); SPI_FLASH_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_ChipErase); //发送片擦除命令 SPI_FLASH_CS=1; //取消片选 SPI_Flash_Wait_Busy(); //等待芯片擦除结束 }
//擦除整个芯片 //等待时间超长... void W25QXX_Erase_Chip(void) { W25QXX_Write_Enable(); //SET WEL W25QXX_Wait_Busy(); W25QXX_CS=0; //使能器件 SPI2_ReadWriteByte(W25X_ChipErase); //发送片擦除命令 W25QXX_CS=1; //取消片选 W25QXX_Wait_Busy(); //等待芯片擦除结束 }
//初始化24L01的IO口 void NRF24L01_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能PB,D,G端口时钟 RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //PG6 7 推挽 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化指定IO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PG8 输入 GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_ResetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);//PG6,7,8上拉 GPIO_SetBits(GPIOB,GPIO_Pin_8); // SPI2_Init(); //初始化SPI GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15); //PB13/14/15上拉 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //定义波特率预分频的值:波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 SPI_Cmd(SPI2, ENABLE); //使能SPI外设 SPI2_ReadWriteByte(0xff);//启动传输 NRF24L01_CE=0; //使能24L01 NRF24L01_CSN=1; //SPI片选取消 }
/** * @brief Write a byte to OLED @params dat: 8-bit data being transferred cmd: Command or data select @retval None */ static void OLED_WR_Byte(unsigned char dat, unsigned char cmd) { if (cmd) OLED_RS_Set(); else OLED_RS_Clr(); OLED_CS_Clr(); SPI2_ReadWriteByte(dat); OLED_CS_Set(); OLED_RS_Set(); }
//读取芯片ID //返回值如下: //0XEF13,表示芯片型号为W25Q80 //0XEF14,表示芯片型号为W25Q16 //0XEF15,表示芯片型号为W25Q32 //0XEF16,表示芯片型号为W25Q64 u16 SPI_Flash_ReadID(void) { u16 Temp = 0; SPI_FLASH_CS=0; SPI2_ReadWriteByte(0x90);//发送读取ID命令 SPI2_ReadWriteByte(0x00); SPI2_ReadWriteByte(0x00); SPI2_ReadWriteByte(0x00); Temp|=SPI2_ReadWriteByte(0xFF)<<8; Temp|=SPI2_ReadWriteByte(0xFF); SPI_FLASH_CS=1; return Temp; }
//读取芯片ID //返回值如下: //0XEF13,表示芯片型号为W25Q80 //0XEF14,表示芯片型号为W25Q16 //0XEF15,表示芯片型号为W25Q32 //0XEF16,表示芯片型号为W25Q64 //0XEF17,表示芯片型号为W25Q128 u16 W25QXX_ReadID(void) { u16 Temp = 0; W25QXX_CS=0; SPI2_ReadWriteByte(0x90);//发送读取ID命令 SPI2_ReadWriteByte(0x00); SPI2_ReadWriteByte(0x00); SPI2_ReadWriteByte(0x00); Temp|=SPI2_ReadWriteByte(0xFF)<<8; Temp|=SPI2_ReadWriteByte(0xFF); W25QXX_CS=1; return Temp; }