/* ********************************************************************************************************* * 函 数 名: SI4730_GetRevision * 功能说明: 读取器件、固件信息。 返回8字节数据 * 形 参:_ReadBuf 返回结果存放在此缓冲区,请保证缓冲区大小大于等于8 * 返 回 值: 0 失败, 1 成功 ********************************************************************************************************* */ uint8_t SI4730_GetRevision(uint8_t *_ReadBuf) { uint8_t ucCmdBuf[2]; uint32_t uiTimeOut; uint8_t i; /* AN223 page = 67 */ /* 发送 0x10 命令 */ ucCmdBuf[0] = 0x10; SI4730_SendCmd(ucCmdBuf, 1); /* 第1个形参表示最大轮询次数; 如果成功,返回值uiTimeOut > 0 表示实际轮询次数 第2个形参0表示结束后不发送STOP, 因为还需要读取器件返回数据 */ uiTimeOut = SI4730_WaitStatus80(10, 0); if (uiTimeOut == 0) { return 0; } /* 连续读取8个字节的器件返回信息 */ for (i = 0; i < 8; i++) { i2c_Ack(); _ReadBuf[i] = i2c_ReadByte(); } i2c_NAck(); i2c_Stop(); return 1; }
//带自动回复的读一字节 uint8_t i2c_ReadByteA(void) { u8 tmp; //第一个字节假 i2c_ReadByte(); i2c_Ack(); //真正读 tmp=i2c_ReadByte(); i2c_NAck(); return tmp; }
/* ********************************************************************************************************* * 函 数 名: SI4730_GetRevision * 功能说明: 读取器件、固件信息。 返回8字节数据 * 形 参:_ReadBuf 返回结果存放在此缓冲区,请保证缓冲区大小大于等于8 * 返 回 值: 0 失败, 1 成功 ********************************************************************************************************* */ uint8_t SI4730_GetRevision(uint8_t *_ReadBuf) { uint8_t ack; uint8_t status; uint32_t i; /* AN223 page = 67 */ /* 发送 0x10 命令 */ i2c_Start(); i2c_SendByte(I2C_ADDR_SI4730_W); ack = i2c_WaitAck(); i2c_SendByte(0x10); ack = i2c_WaitAck(); i2c_Stop(); /* 等待器件状态为 0x80 */ for (i = 0; i < 50; i++) { i2c_Start(); i2c_SendByte(I2C_ADDR_SI4730_R); /* 读 */ ack = i2c_WaitAck(); status = i2c_ReadByte(); if (status == 0x80) { break; } } /* 实测 2 次循环应该正常退出 */ if (i == 50) { i2c_NAck(); i2c_Stop(); return 0; } /* 连续读取8个字节的器件返回信息 */ for (i = 0; i < 8; i++) { i2c_Ack(); _ReadBuf[i] = i2c_ReadByte(); } i2c_NAck(); i2c_Stop(); return 1; }
/* ********************************************************************************************************* * 函 数 名: SI4730_GetFMSignalQuality * 功能说明: 读取FM接收信号质量 * 形 参: _ReadBuf 返回结果存放在此缓冲区,请保证缓冲区大小大于等于7 * 返 回 值: 0 失败, 1 成功 ********************************************************************************************************* */ uint8_t SI4730_GetFMSignalQuality(uint8_t *_ReadBuf) { /* FM_RSQ_STATUS Queries the status of the Received Signal Quality (RSQ) for the current channel. CMD 0x23 FM_RSQ_STATUS ARG1 0x01 Clear RSQINT STATUS ?0x80 Reply Status. Clear-to-send high. RESP1 ?0x00 No blend, SNR high, low, RSSI high or low interrupts. RESP2 ?0x01 Soft mute is not engaged, no AFC rail, valid frequency. RESP3 ?0xD9 Pilot presence, 89% blend RESP4 ?0x2D RSSI = 45 dBμV RESP5 ?0x33 SNR = 51 dB RESP6 ?0x00 RESP7 ?0x00 Freq offset = 0 kHz */ uint8_t ucCmdBuf[32]; uint32_t uiTimeOut; uint32_t i; ucCmdBuf[0] = 0x23; ucCmdBuf[1] = 0x01; SI4730_SendCmd(ucCmdBuf, 2); uiTimeOut = SI4730_WaitStatus80(1000, 0); if (uiTimeOut == 0) { return 0; } /* 连续读取7个字节的器件返回信息 */ for (i = 0; i < 7; i++) { i2c_Ack(); _ReadBuf[i] = i2c_ReadByte(); } i2c_NAck(); i2c_Stop(); return 1; }
/* ********************************************************************************************************* * 函 数 名: SI4730_GetAMTuneStatus * 功能说明: 读取AM调谐状态 * 形 参: 返回结果存放在此缓冲区,请保证缓冲区大小大于等于7 * 返 回 值: 0 失败, 1 成功 ********************************************************************************************************* */ uint8_t SI4730_GetAMTuneStatus(uint8_t *_ReadBuf) { /* CMD 0x42 AM_TUNE_STATUS ARG1 0x01 Clear STC interrupt. STATUS ?0x80 Reply Status. Clear-to-send high. RESP1 ?0x01 Channel is valid, AFC is not railed, and seek did not wrap at AM band boundary RESP2 ?0x03 RESP3 ?0xE8 Frequency = 0x03E8 = 1000 kHz RESP4 ?0x2A RSSI = 0x2A = 42d = 42 dBμV RESP5 ?0x1A SNR = 0x1A = 26d = 26 dB RESP6 ?0x0D Value the antenna tuning capacitor is set to. RESP7 ?0x95 0x0D95 = 3477 dec. 电容计算 The tuning capacitance is 95 fF x READANTCAP + 7 pF */ uint8_t ucCmdBuf[32]; uint32_t uiTimeOut; uint32_t i; ucCmdBuf[0] = 0x42; ucCmdBuf[1] = 0x01; SI4730_SendCmd(ucCmdBuf, 2); uiTimeOut = SI4730_WaitStatus80(100, 0); if (uiTimeOut == 0) { return 0; } /* 连续读取7个字节的器件返回信息 */ for (i = 0; i < 7; i++) { i2c_Ack(); _ReadBuf[i] = i2c_ReadByte(); } i2c_NAck(); i2c_Stop(); return 1; }
/* ********************************************************************************************************* * 函 数 名: SI4730_GetAMSignalQuality * 功能说明: 读取AM接收信号质量 * 形 参: _ReadBuf 返回结果存放在此缓冲区,请保证缓冲区大小大于等于5 * 返 回 值: 0 失败, 1 成功 ********************************************************************************************************* */ uint8_t SI4730_GetAMSignalQuality(uint8_t *_ReadBuf) { /* AM_RSQ_STATUS Queries the status of the Received Signal Quality (RSQ) for the current channel. CMD 0x43 AM_RSQ_STATUS ARG1 0x01 Clear STC interrupt. STATUS ?0x80 Reply Status. Clear-to-send high. RESP1 ?0x00 No SNR high, low, RSSI high, or low interrupts. RESP2 ?0x01 Channel is valid, soft mute is not activated, and AFC is not railed RESP3 ?0x00 RESP4 ?0x2A RSSI = 0x2A = 42d = 42 dBμV RESP5 ?0x1A SNR = 0x1A = 26d = 26 dB */ uint8_t ucCmdBuf[32]; uint32_t uiTimeOut; uint32_t i; ucCmdBuf[0] = 0x43; ucCmdBuf[1] = 0x01; SI4730_SendCmd(ucCmdBuf, 2); uiTimeOut = SI4730_WaitStatus80(100, 0); if (uiTimeOut == 0) { return 0; } /* 连续读取5个字节的器件返回信息 */ for (i = 0; i < 5; i++) { i2c_Ack(); _ReadBuf[i] = i2c_ReadByte(); } i2c_NAck(); i2c_Stop(); return 1; }
/* ********************************************************************************************************* * 函 数 名: SI4730_GetFMTuneStatus * 功能说明: 读取FM调谐状态 * 形 参: 返回结果存放在此缓冲区,请保证缓冲区大小大于等于7 * 返 回 值: 0 失败, 1 成功 ********************************************************************************************************* */ uint8_t SI4730_GetFMTuneStatus(uint8_t *_ReadBuf) { /* CMD 0x22 FM_TUNE_STATUS ARG1 0x01 Clear STC interrupt. STATUS ?0x80 Reply Status. Clear-to-send high. RESP1 ?0x01 Valid Frequency. RESP2 ?0x27 Frequency = 0x27F6 = 102.3 MHz RESP3 ?0xF6 RESP4 ?0x2D RSSI = 45 dBμV RESP5 ?0x33 SNR = 51 dB RESP6 ?0x00 MULT[7:0] RESP7 ?0x00 Antenna tuning capacitor = 0 (range = 0–191) READANTCAP[7:0] (Si4704/05/06/2x only) */ uint8_t ucCmdBuf[32]; uint32_t uiTimeOut; uint32_t i; ucCmdBuf[0] = 0x22; ucCmdBuf[1] = 0x01; SI4730_SendCmd(ucCmdBuf, 2); uiTimeOut = SI4730_WaitStatus80(100, 0); if (uiTimeOut == 0) { return 0; } /* 连续读取7个字节的器件返回信息 */ for (i = 0; i < 7; i++) { i2c_Ack(); _ReadBuf[i] = i2c_ReadByte(); } i2c_NAck(); i2c_Stop(); return 1; }
uint8_t i2c_ReceiveByte_WithACK(void) { uint8_t i,i2c_data; // I2C_SDA_1(); I2C_SCL_0(); i2c_data=0; // for(i=0;i<8;i++) { I2C_SCL_1(); i2c_Delay(); i2c_data<<=1; // if(I2C_SDA_READ()) i2c_data|=0x01; I2C_SCL_0(); i2c_Delay(); } i2c_Ack(); return i2c_data; }
unsigned int mem_Read(unsigned int addr,unsigned char *data, unsigned int data_len) { unsigned int i=0; unsigned char b; i2c_Start(); i2c_Write(MEM_ADDRESS); if (i2c_Timeout()) goto Timeout; b = addr>>8; i2c_Write(b); if (i2c_Timeout()) goto Timeout; b = addr&0xFF; i2c_Write(b); if (i2c_Timeout()) goto Timeout; //i2c_Stop(); i2c_Start(); i2c_Write(MEM_ADDRESS | 1); if (i2c_Timeout()) goto Timeout; for (i=0; i<data_len; i++) { data[i] = i2c_Read(); clear_CPU_operation_detection(); if (i<data_len-1) i2c_Ack(); else i2c_Nack(); } i2c_Stop(); return i; Timeout: return i; }
/* ********************************************************************************************************* * 函 数 名: i2c_ReadByte * 功能说明: CPU从I2C总线设备读取8bit数据 * 形 参: 无 * 返 回 值: 读到的数据 ********************************************************************************************************* */ uint8_t i2c_ReadByte(uint8_t ack) { uint8_t i; uint8_t receive=0; SDA_IN(); for (i = 0; i < 8; i++) { I2C_SCL_0(); i2c_Delay(); I2C_SCL_1(); receive <<= 1; if (I2C_SDA_READ()){ receive++; } i2c_Delay(); } if(ack) { i2c_Ack(); } else { i2c_NAck(); } return receive; }
/* ********************************************************************************************************* * 函 数 名: MPU6050_ReadData * 功能说明: 读取 MPU-6050 数据寄存器, 结果保存在全局变量 g_tMPU6050. 主程序可以定时调用该程序刷新数据 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void MPU6050_ReadData(void) { uint8_t ucReadBuf[14]; uint8_t i; uint8_t ack; #if 1 /* 连续读 */ i2c_Start(); /* 总线开始信号 */ i2c_SendByte(MPU6050_SLAVE_ADDRESS); /* 发送设备地址+写信号 */ ack = i2c_WaitAck(); if (ack != 0) { i2c_Stop(); return; } i2c_SendByte(ACCEL_XOUT_H); /* 发送存储单元地址 */ ack = i2c_WaitAck(); if (ack != 0) { i2c_Stop(); return; } i2c_Start(); /* 总线开始信号 */ i2c_SendByte(MPU6050_SLAVE_ADDRESS + 1); /* 发送设备地址+读信号 */ ack = i2c_WaitAck(); if (ack != 0) { i2c_Stop(); return; } for (i = 0; i < 13; i++) { ucReadBuf[i] = i2c_ReadByte(); /* 读出寄存器数据 */ i2c_Ack(); } /* 读最后一个字节,时给 NAck */ ucReadBuf[13] = i2c_ReadByte(); i2c_NAck(); i2c_Stop(); /* 总线停止信号 */ #else /* 单字节读 */ for (i = 0 ; i < 14; i++) { ucReadBuf[i] = MPU6050_ReadByte(ACCEL_XOUT_H + i); } #endif /* 将读出的数据保存到全局结构体变量 */ g_tMPU6050.Accel_X = (ucReadBuf[0] << 8) + ucReadBuf[1]; g_tMPU6050.Accel_Y = (ucReadBuf[2] << 8) + ucReadBuf[3]; g_tMPU6050.Accel_Z = (ucReadBuf[4] << 8) + ucReadBuf[5]; g_tMPU6050.Temp = (int16_t)((ucReadBuf[6] << 8) + ucReadBuf[7]); g_tMPU6050.GYRO_X = (ucReadBuf[8] << 8) + ucReadBuf[9]; g_tMPU6050.GYRO_Y = (ucReadBuf[10] << 8) + ucReadBuf[11]; g_tMPU6050.GYRO_Z = (ucReadBuf[12] << 8) + ucReadBuf[13]; }
/* ********************************************************************************************************* * 函 数 名: ee_ReadBytes * 功能说明: 从串行EEPROM指定地址处开始读取若干数据 * 形 参:_usAddress : 起始地址 * _usSize : 数据长度,单位为字节 * _pReadBuf : 存放读到的数据的缓冲区指针 * 返 回 值: 0 表示失败,1表示成功 ********************************************************************************************************* */ uint8_t ee_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize) { uint16_t i; /* 采用串行EEPROM随即读取指令序列,连续读取若干字节 */ /* 第1步:发起I2C总线启动信号 */ i2c_Start(); /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ i2c_SendByte(EE_DEV_ADDR | I2C_WR); /* 此处是写指令 */ /* 第3步:发送ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } /* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那么此处需要连发多个地址 */ i2c_SendByte((uint8_t)_usAddress); /* 第5步:发送ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } /* 第6步:重新启动I2C总线。前面的代码的目的向EEPROM传送地址,下面开始读取数据 */ i2c_Start(); /* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ i2c_SendByte(EE_DEV_ADDR | I2C_RD); /* 此处是读指令 */ /* 第8步:发送ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } /* 第9步:循环读取数据 */ for (i = 0; i < _usSize; i++) { _pReadBuf[i] = i2c_ReadByte(); /* 读1个字节 */ /* 每读完1个字节后,需要发送Ack, 最后一个字节不需要Ack,发Nack */ if (i != _usSize - 1) { i2c_Ack(); /* 中间字节读完后,CPU产生ACK信号(驱动SDA = 0) */ } else { i2c_NAck(); /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */ } } /* 发送I2C总线停止信号 */ i2c_Stop(); return 1; /* 执行成功 */ cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */ /* 发送I2C总线停止信号 */ i2c_Stop(); return 0; }