forked from logzhan/RobotHardware-UESTC
227 lines
3.8 KiB
C
227 lines
3.8 KiB
C
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
#include "i2c.h"
|
||
|
#include "nvic.h"
|
||
|
|
||
|
static void I2C_delay()
|
||
|
{
|
||
|
volatile int i = 7;
|
||
|
while (i)
|
||
|
i--;
|
||
|
}
|
||
|
|
||
|
static int I2C_Start()
|
||
|
{
|
||
|
SDA_H;
|
||
|
SCL_H;
|
||
|
I2C_delay();
|
||
|
if (!SDA_read)
|
||
|
return 0;
|
||
|
SDA_L;
|
||
|
I2C_delay();
|
||
|
if (SDA_read)
|
||
|
return 0;
|
||
|
SDA_L;
|
||
|
I2C_delay();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void I2C_Stop()
|
||
|
{
|
||
|
SCL_L;
|
||
|
I2C_delay();
|
||
|
SDA_L;
|
||
|
I2C_delay();
|
||
|
SCL_H;
|
||
|
I2C_delay();
|
||
|
SDA_H;
|
||
|
I2C_delay();
|
||
|
}
|
||
|
|
||
|
static void I2C_Ack()
|
||
|
{
|
||
|
SCL_L;
|
||
|
I2C_delay();
|
||
|
SDA_L;
|
||
|
I2C_delay();
|
||
|
SCL_H;
|
||
|
I2C_delay();
|
||
|
SCL_L;
|
||
|
I2C_delay();
|
||
|
}
|
||
|
|
||
|
static void I2C_NoAck()
|
||
|
{
|
||
|
SCL_L;
|
||
|
I2C_delay();
|
||
|
SDA_H;
|
||
|
I2C_delay();
|
||
|
SCL_H;
|
||
|
I2C_delay();
|
||
|
SCL_L;
|
||
|
I2C_delay();
|
||
|
}
|
||
|
|
||
|
static int I2C_WaitAck()
|
||
|
{
|
||
|
SCL_L;
|
||
|
I2C_delay();
|
||
|
SDA_H;
|
||
|
I2C_delay();
|
||
|
SCL_H;
|
||
|
I2C_delay();
|
||
|
if (SDA_read) {
|
||
|
SCL_L;
|
||
|
return 0;
|
||
|
}
|
||
|
SCL_L;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void I2C_SendByte(uint8_t b)
|
||
|
{
|
||
|
uint8_t i = 8;
|
||
|
while (i--) {
|
||
|
SCL_L;
|
||
|
I2C_delay();
|
||
|
if (b & 0x80)
|
||
|
SDA_H;
|
||
|
else
|
||
|
SDA_L;
|
||
|
b <<= 1;
|
||
|
I2C_delay();
|
||
|
SCL_H;
|
||
|
I2C_delay();
|
||
|
}
|
||
|
SCL_L;
|
||
|
}
|
||
|
|
||
|
static uint8_t I2C_ReadByte()
|
||
|
{
|
||
|
uint8_t i = 8;
|
||
|
uint8_t byte = 0;
|
||
|
|
||
|
SDA_H;
|
||
|
while (i--) {
|
||
|
byte <<= 1;
|
||
|
SCL_L;
|
||
|
I2C_delay();
|
||
|
SCL_H;
|
||
|
I2C_delay();
|
||
|
if (SDA_read) {
|
||
|
byte |= 0x01;
|
||
|
}
|
||
|
}
|
||
|
SCL_L;
|
||
|
return byte;
|
||
|
}
|
||
|
|
||
|
void PB_I2C_Init(void)
|
||
|
{
|
||
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||
|
//已更改
|
||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
|
||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
|
||
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
|
||
|
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||
|
}
|
||
|
|
||
|
int PB_I2C_Write_Byte(uint8_t addr, uint8_t reg, uint8_t data)
|
||
|
{
|
||
|
if (!I2C_Start())
|
||
|
return 0;
|
||
|
I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
|
||
|
if (!I2C_WaitAck()) {
|
||
|
I2C_Stop();
|
||
|
return 0;
|
||
|
}
|
||
|
I2C_SendByte(reg);
|
||
|
I2C_WaitAck();
|
||
|
I2C_SendByte(data);
|
||
|
if (!I2C_WaitAck()) {
|
||
|
I2C_Stop();
|
||
|
return 0;
|
||
|
}
|
||
|
I2C_Stop();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int PB_I2C_Write_Buf(uint8_t addr, uint8_t reg, uint8_t *data , uint8_t size)
|
||
|
{
|
||
|
int i;
|
||
|
if (!I2C_Start())
|
||
|
return 0;
|
||
|
I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
|
||
|
if (!I2C_WaitAck()) {
|
||
|
I2C_Stop();
|
||
|
return 0;
|
||
|
}
|
||
|
I2C_SendByte(reg);
|
||
|
I2C_WaitAck();
|
||
|
for (i = 0; i < size; i++) {
|
||
|
I2C_SendByte(data[i]);
|
||
|
if (!I2C_WaitAck()) {
|
||
|
I2C_Stop();
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
I2C_Stop();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int PB_I2C_Read_Byte(uint8_t addr, uint8_t reg, uint8_t* data)
|
||
|
{
|
||
|
if (!I2C_Start())
|
||
|
return 0;
|
||
|
I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
|
||
|
if (!I2C_WaitAck()) {
|
||
|
I2C_Stop();
|
||
|
return 0;
|
||
|
}
|
||
|
I2C_SendByte(reg);
|
||
|
I2C_WaitAck();
|
||
|
I2C_Start();
|
||
|
I2C_SendByte(addr << 1 | I2C_Direction_Receiver);
|
||
|
I2C_WaitAck();
|
||
|
*data = I2C_ReadByte();
|
||
|
I2C_NoAck();
|
||
|
I2C_Stop();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int PB_I2C_Read_Buf(uint8_t addr,uint8_t reg, uint8_t* data , uint8_t size)
|
||
|
{
|
||
|
if (!I2C_Start())
|
||
|
return 0;
|
||
|
I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
|
||
|
if (!I2C_WaitAck()) {
|
||
|
I2C_Stop();
|
||
|
return 0;
|
||
|
}
|
||
|
I2C_SendByte(reg);
|
||
|
I2C_WaitAck();
|
||
|
I2C_Start();
|
||
|
I2C_SendByte(addr << 1 | I2C_Direction_Receiver);
|
||
|
I2C_WaitAck();
|
||
|
while (size) {
|
||
|
*data = I2C_ReadByte();
|
||
|
if (size == 1)
|
||
|
I2C_NoAck();
|
||
|
else
|
||
|
I2C_Ack();
|
||
|
data++;
|
||
|
size--;
|
||
|
}
|
||
|
I2C_Stop();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|
||
|
|