- IIC
- 简介
- 该总线半双工,速度慢,多用于芯片之间通信。由数据线SDA和时钟SCL构成,可发送和接收数据。
- 有三种类型信号:开始信号、结束信号和应答信号。
- 开始信号:SCL为高电平时,SDA由高电平跳变为低电平,开始传送数据;
- 结束信号:SCL为高电平时,SDA由低电平跳变为高电平,结束传送数据;
- 应答信号:接收方收到8位数据后,向发送端发出低电平,表示数据收到。
- 时序
- 软件模拟IIC与24C02之间的通信
- 写过程
- 起始地址》》要写入的设备在吗》》要写入的数据地址在吗》》写入》》停止信号
- 读过程
- 起始信号》》要读的设备在吗》》要读的地址在吗》》要读的设备在吗》》读取数据》》停止信号
- 注:这里要写两个设备地址,此两个地址只有前7bit真正表示地址,最后一位0表示写,1表示读,故设备地址不一样。
- 起始信号》》要读的设备在吗》》要读的地址在吗》》要读的设备在吗》》读取数据》》停止信号
- 写过程
- 简介
- SPI
- 简介
- 高速、全双工同步总线,占用四根引脚
- 若主机需读取数据,需要向从机发送空字节(0xff),与从机移位寄存器的数据进行交换。
- 时序
- 主从的时钟相位和极性应一致:CPOL=1,则空闲为高电平,CPPL=0,则空闲为低;CPHA=0,第一个边沿采集,CPHA=1,第二个边沿采集。
- 简介
- 软件模拟
- IIC
-
void 24C02_WriteOneByte(u16 WriteAddr,u8 DataToWrite) { IIC_Start(); IIC_Send_Byte(0XA0); //0XA0包括设备地址和写命令 IIC_Wait_Ack(); IIC_Send_Byte(WriteAddr); //WriteAddr为写入数据的目的地址 IIC_Wait_Ack(); // IIC_Send_Byte(DataToWrite); // DataToWrite写入的数据 IIC_Wait_Ack(); IIC_Stop(); delay_ms(10); } u8 24C02_ReadOneByte(u16 ReadAddr) { u8 temp=0; IIC_Start(); IIC_Send_Byte(0XA0); //写入要读的设备地址 IIC_Wait_Ack(); // IIC_Send_Byte(ReadAddr); // IIC_Wait_Ack(); // IIC_Start(); IIC_Send_Byte(0XA1); //真正的读 IIC_Wait_Ack(); temp=IIC_Read_Byte(0); IIC_Stop(); return temp; }
void IIC_Send_Byte(u8 txd)//txd为待发送的数据 { u8 t; SDA_OUT(); IIC_SCL=0;//等待发送 for(t=0;t<8;t++) { IIC_SDA=(txd&0x80)>>7;//取最高位开始发送 txd<<=1; //将已发送的移走,次高位变成最高位 delay_us(2); // IIC_SCL=1; delay_us(2); IIC_SCL=0; delay_us(2); } }
-
- SPI
-
u8 SPI1_ReadWriteByte(u8 TxData)//TxData为要写入的命令或数据,写入命令,则一般返回值不采用,写入空字节,则为读取字节 { u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //RESET为0,表示发送缓冲区非空,待发送数据无法写入 { retry++; if(retry>200)return 0; } SPI_I2S_SendData(SPI1, TxData); //向SPI1写入命令或数据,在写之前要要保证发送缓冲区为空; retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//RESET表示接收缓冲区无有效数据 { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI1); // 通过SPI1接收最近的数据,在接收之前要保证接收缓冲去包含有效数据 } //读取SPI FLASH void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) { u16 i; SPI_FLASH_CS=0; //片选 SPI1_ReadWriteByte(W25X_ReadData); //发送读取命令 SPI1_ReadWriteByte((u8)((ReadAddr)>>16)); //· SPI1_ReadWriteByte((u8)((ReadAddr)>>8)); SPI1_ReadWriteByte((u8)ReadAddr); for(i=0;i<NumByteToRead;i++) { pBuffer[i]=SPI1_ReadWriteByte(0XFF); //循环读数 } SPI_FLASH_CS=1; // 取消片选 }
void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) { u32 secpos; u16 secoff; u16 secremain; u16 i; secpos=WriteAddr/4096;//一个扇区4096个地址,表示扇区地址 secoff=WriteAddr%4096;//在扇区内偏移 secremain=4096-secoff;//扇区剩余空间大小 if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//如果无跨区 while(1) { SPI_Flash_Read(SPI_FLASH_BUF,secpos*4096,4096);//读出整个扇区的内容 for(i=0;i<secremain;i++)//校验数据 { if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除 } if(i<secremain)// { SPI_Flash_Erase_Sector(secpos);//擦除整个扇区 for(i=0;i<secremain;i++) // { SPI_FLASH_BUF[i+secoff]=pBuffer[i];// } SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096);//更新扇区 }else SPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain);// if(NumByteToWrite==secremain)break;// secpos++;// secoff=0;// pBuffer+=secremain; // WriteAddr+=secremain;// NumByteToWrite-=secremain; // if(NumByteToWrite>4096)secremain=4096; // else secremain=NumByteToWrite; // } }; }
-
- IIC
时间: 2024-10-29 19:07:28