总括

SHT20可能代表主要需要读的设备,EEPROM可能代表需要读写的设备

EEPROM

一页的字节数

01为8个字节,02/04/08/16为16个字节,128/256为64字节

在操作AT24C256时发现EEPROM连续写入时不能跨页写(比如,第一页0~63,我先向63写入一个数据再向64写入一个数据,64没有得到想要的数据,该数据覆盖了第一页第一个地址的数据)

 1     Myiic_Start();        
 2     Myiic_SendByte(EEPROM_WRITEADDRESS);    
 3     Myiic_SlaveAck();    
 4 
 5     Myiic_SendByte(63>>8);            
 6     Myiic_SlaveAck();                    
 7     
 8     Myiic_SendByte(63);            
 9     Myiic_SlaveAck();                    
10 
11     Myiic_SendByte (63);
12     Myiic_SlaveAck();
13     Myiic_SendByte(64);
14     Myiic_SlaveAck();            
15     Myiic_Stop();
16     Delay_ms(15);
17     OLED_Printf(0, 0, OLED_8X16, "%d",EEPROM_ReadByte(63));
18     OLED_Printf(0, 16, OLED_8X16, "%d",EEPROM_ReadByte(64));
19     OLED_Printf(0, 32, OLED_8X16, "%d",EEPROM_ReadByte(0));

清一下EEPROM做下个实验

当我将数据写入地址63后重新开启一次IIC时序将数据写入地址64,发现写成功了

1 EEPROM_WriteByte(63,63);
2 EEPROM_WriteByte(64,64);
3 OLED_Printf(0, 0, OLED_8X16, "%d",EEPROM_ReadByte(63));
4 OLED_Printf(0, 32, OLED_8X16, "%d",EEPROM_ReadByte(64));
 1 void EEPROM_WriteByte(uint16_t RegAddress, uint8_t Data)
 2 {
 3     Myiic_Start();                        //iic起始
 4     Myiic_SendByte(EEPROM_WRITEADDRESS);    //发送从机地址,读写位为0,表示即将写入
 5     Myiic_SlaveAck();                    //接收应答
 6     
 7     Myiic_SendByte(RegAddress>>8);            //发送寄存器地址
 8     Myiic_SlaveAck();                    //接收应答
 9     
10     Myiic_SendByte(RegAddress);            //发送寄存器地址
11     Myiic_SlaveAck();                    //接收应答
12     
13     Myiic_SendByte(Data);                //发送要写入寄存器的数据
14     Myiic_SlaveAck();                    //接收应答
15     
16     Myiic_Stop();                        //iic终止
17     Delay_ms(15);
18 }

总结一下EEPROM不能跨页写,多出本页的数据会从本页前面的地址开始覆盖,如果想要跨页必须重新开启IIC时序

不同型号的芯片可存储的字节数

(20)01--128个字节(20+7)

02--256个字节

04--512个字节

08--1024个字节

16--2048个字节

128--16384个字节

256--32768个字节(215)

寄存器地址

以256为例0~0x7FFF(正好是15位),这里和MPU6050比较一下

MPU6050也是写入寄存器(SHT20是写入指令),但是每个寄存器有它自己单独的地址

读写时序

01~16都是8位寄存器地址,而04~16地址(9~11位)显然超过了8位,超出的位写在从机地址里面(PX),也就是说仅可以通过AX来更改从机地址,因此01~02可以挂载8个从机,04可以挂载4个从机,08可以挂载2个从机,16可以挂载1个从机

 1   FunctionalState I2C_WriteByte(uint8_t SendByte, uint16_t WriteAddress)
 2  {        
 3     if(!I2C_Start())return DISABLE;                          /* 判断是否有起始信号*/
 4     
 5     I2C_SendByte((((WriteAddress&0x0700)>>7)|0xA0)&0xFFFE);  /*从机地址加写入寄存器地址的高8位(16是0x0700,08是0x0300,04是0x0100)*/
 6     
 7     if(!I2C_WaitAck()){I2C_Stop(); return DISABLE;}          /* 等待应答信号*/
 8     
 9     I2C_SendByte((uint8_t)(WriteAddress & 0x00FF));          /* 发送字地址(低8位数据) */  
10     
11     I2C_WaitAck();                                             /* 等待应答   */ 
12     
13     I2C_SendByte(SendByte);                                  /* 发送数据   */  
14     
15     I2C_WaitAck();                                           /* 等待应答   */  
16     
17     I2C_Stop();                                              /* 等待停止   */ 
18     
19     return ENABLE;
20   }                            

而128和256都是16位地址,因此IIC时序时先写入高位地址,应答,再写入低位地址,应答

 1 uint8_t EEPROM_ReadByte(uint16_t RegAddress)
 2 {
 3     uint8_t Data;
 4     
 5     Myiic_Start();                        //iic起始
 6     Myiic_SendByte(EEPROM_WRITEADDRESS);    //发送从机地址,读写位为0,表示即将写入
 7     Myiic_SlaveAck();                    //接收应答
 8     
 9     Myiic_SendByte(RegAddress>>8);            //发送寄存器地址
10     Myiic_SlaveAck();                    //接收应答
11     
12     Myiic_SendByte(RegAddress);            //发送寄存器地址
13     Myiic_SlaveAck();                    //接收应答
14     
15     Myiic_Start();                        //iic重复起始
16     Myiic_SendByte(EEPROM_READADDRESS);    //发送从机地址,读写位为1,表示即将读取
17     Myiic_SlaveAck();                    //接收应答
18     
19     Data = Myiic_ReceiveByte();            //接收指定寄存器的数据
20     Myiic_HostAck(1);                    //发送应答,给从机非应答,终止从机的数据输出
21     Myiic_Stop();                        //iic终止
22     
23     return Data;
24 }

写等待

当EEPROM接收到停止信号后有10ms的写等待将数据写入数据区,这期间不响应主机,不能对EEPROM做任何操作,如果想要写入数据后马上读数据需要注意这个问题

当然上次写完成后好久才操作EEPROM就不用加延时函数了

SHT20

(项目心得跳过来的看这里)这里仅说一个最重要的地方,当主机发送从机地址+读标志位时,由于从机测量时间的问题,主机要一直等待从机响应,其他地方正常响应就好了

 1 float SHT20_Read(uint8_t cmd)
 2 {
 3     float Humidity,Temperature;
 4     uint16_t data;//高位一个字节,低位一个字节
 5     Myiic_Start();
 6     Myiic_SendByte(SHT20_WriteAddress);
 7     if(Myiic_SlaveAck()==0)//正常响应
 8     {
 9         Myiic_SendByte(cmd);
10         if(Myiic_SlaveAck()==0)//正常响应
11         {
12             do
13             {
14               Delay_us(8);
15               Myiic_Start();
16               Myiic_SendByte(SHT20_ReadAddress);
17               Myiic_W_SDA(1);                            
18               Myiic_W_SCL(1);
19             }
20             while(Myiic_R_SDA());        
21             Myiic_W_SCL(0);
22             data=Myiic_ReceiveByte();
23             data<<=8;//iic通信是高位先行,因此数据是高位先进来
24             data|=Myiic_ReceiveByte();
25             Myiic_HostAck(1);
26             Myiic_Stop();
27             if(cmd==RH_Measurement_NoHold)
28             {
29                 Humidity =(data*125)/65536-6;
30                 return Humidity;
31             }
32             else if(cmd==T_Measurement_NoHold)
33             {
34                 Temperature = (data*175.72)/65536-46.85;
35                 return Temperature;
36             }
37         }
38     }
39     return Slave_Error;
40 }
1 uint8_t Myiic_SlaveAck(void)
2 {
3     uint8_t AckBit;                            
4     Myiic_W_SDA(1);                            
5     Myiic_W_SCL(1);                            
6     AckBit = Myiic_R_SDA();
7     Myiic_W_SCL(0);                            
8     return AckBit;                            
9 }

 

posted on 2023-12-24 19:07  小凉拖  阅读(25)  评论(0编辑  收藏  举报