IIC相对而言硬件设计较为简单,两线总线可以直接挂载很多芯片,但通信受干扰,容易进入“死锁”状态,需要软件处理。SPI相对而言需要的硬线更多,但不存在出现“死锁”的问题,另外通信速率也更高。
死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
那么为什么会产生死锁呢?
1.因为系统资源不足。
2.进程运行推进的顺序不合适。
3.资源分配不当。
产生死锁的四个必要条件:
互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。
#ifndef __USER_IIC_
#define __USER_IIC_
#include "pca10040.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
//ERROR
#define ERROR_CODE_TRUE 0
#define ERROR_CODE_FALSE 1
#define ERROR_CODE_WRITE_ADDR 10
#define ERROR_CODE_WRITE_DATA 20
#define ERROR_CODE_READ_ADDR 30
#define ERROR_CODE_READ_DATA 40
#define ERROR_CODE_START_BIT 50
#define ERROR_CODE_APROCESS 60
#define ERROR_CODE_DENY 70
#define I2C_DELAY nrf_delay_us(13) // 5uS delay setting
#define I2C_DELAY_LONG nrf_delay_us(130) // 10uS delay setting
#define SCL1 6
#define SDA1 7
//设置IO方向
#define SDA_OUT1() nrf_gpio_cfg_output(SDA1)
#define SDA_IN1() nrf_gpio_cfg_input(SDA1,NRF_GPIO_PIN_PULLUP)
//设置IO电平
#define I2C_SCL_HIGH1 nrf_gpio_pin_set(SCL1) //SCL = 1
#define I2C_SCL_LOW1 nrf_gpio_pin_clear(SCL1) //SCL = 0
#define I2C_SDA1 1 //SDA
#define READ_SDA1 nrf_gpio_pin_read(SDA1) //read SDA
#define I2C_SDA_HIGH1 nrf_gpio_pin_set(SDA1) //SDA
#define I2C_SDA_LOW1 nrf_gpio_pin_clear(SDA1) //SDA
void IIC_IO_Init1(void);
void _i2c_start1(void);
void _i2c_stop1(void);
unsigned char _i2c_write_byte1(unsigned char data);
unsigned char _i2c_read_byte1(unsigned char ack);
void _i2c_ack_send1(void);
void _i2c_nack_send1(void);
unsigned char _i2c_ack_detect1(void);
#endif
void IIC_IO_Init1(void)
{
nrf_gpio_cfg_output(SDA1);
nrf_gpio_cfg_output(SCL1);
I2C_SDA_HIGH1;
I2C_SCL_HIGH1;
}
void _i2c_start1(void)
{
SDA_OUT1();
I2C_SDA_HIGH1;
I2C_SCL_HIGH1;
I2C_DELAY;
I2C_SDA_LOW1;
I2C_DELAY;
I2C_SCL_LOW1;
I2C_DELAY;
}
void _i2c_stop1(void)
{
SDA_OUT1();
I2C_SCL_LOW1;
I2C_SDA_LOW1;
I2C_DELAY;
I2C_SCL_HIGH1;
I2C_DELAY;
I2C_SDA_HIGH1;
I2C_DELAY_LONG;
}
void _i2c_ack_send1(void)//??ACK??
{
SDA_OUT1();
I2C_SCL_LOW1;
I2C_SDA_LOW1;
I2C_DELAY;
I2C_SCL_HIGH1;
I2C_DELAY;
I2C_SCL_LOW1;
I2C_DELAY;
}
void _i2c_nack_send1(void)
{
SDA_OUT1();
I2C_SCL_LOW1;
I2C_SDA_HIGH1;
I2C_DELAY;
I2C_SCL_HIGH1;
I2C_SCL_LOW1;
I2C_DELAY;
}
unsigned char _i2c_ack_detect1(void)
{
unsigned char ucErrTime=0;
SDA_IN1(); // SDA Input Mode
I2C_SDA_HIGH1;
I2C_SCL_HIGH1;
I2C_DELAY;
while(READ_SDA1==I2C_SDA1)
{
ucErrTime++;
if(ucErrTime>250)
{
SDA_OUT1();
return ERROR_CODE_FALSE; // false
}
}
I2C_SCL_LOW1;
I2C_DELAY;
return ERROR_CODE_TRUE;
}
unsigned char _i2c_write_byte1(unsigned char data)
{
unsigned char i ;
SDA_OUT1();
I2C_SCL_LOW1;
for(i = 0; i< 8; i++)
{
if( (data & 0x80) == 0x80) I2C_SDA_HIGH1;
else I2C_SDA_LOW1;
data <<=1;
I2C_DELAY;
I2C_SCL_HIGH1;
I2C_DELAY;
I2C_SCL_LOW1;
I2C_DELAY;
}
if(_i2c_ack_detect1())
{
return ERROR_CODE_FALSE;
}
return ERROR_CODE_TRUE;
}
unsigned char _i2c_read_byte1(unsigned char ack)//ack=1 send ACK,ack=0 send NACK
{
unsigned char i=0, data=0;
SDA_IN1();
I2C_SDA_HIGH1;
for(i = 0; i< 8; i++)
{
data <<= 1;
I2C_SCL_LOW1;
I2C_DELAY;
I2C_SCL_HIGH1;
I2C_DELAY;
if (READ_SDA1==I2C_SDA1) data |= 0x01;
I2C_DELAY;
}
if (!ack) _i2c_nack_send1();
else _i2c_ack_send1();
return data;
}
//MPU6050
struct MPU6050_ACCEL1 MPU6050_ACCEL_OUT1;
unsigned char MPU_X050_Write_Byte1(unsigned char SlaveAddress,unsigned char REG_Address,unsigned char REG_data)
{
_i2c_start1();
if(_i2c_write_byte1(SlaveAddress))
{
_i2c_stop1();
return ERROR_CODE_WRITE_ADDR;
}
if(_i2c_write_byte1(REG_Address))
{
_i2c_stop1();
return ERROR_CODE_WRITE_ADDR;
}
if(_i2c_write_byte1(REG_data))
{
_i2c_stop1();
return ERROR_CODE_WRITE_ADDR;
}
_i2c_stop1();
I2C_DELAY_LONG;
return ERROR_CODE_TRUE;
}
unsigned char MPU_X050_Read_Byte1(unsigned char SlaveAddress,unsigned char REG_Address)
{
unsigned char REG_data;
_i2c_start1();
if(_i2c_write_byte1(SlaveAddress))
{
_i2c_stop1();
return 0;
}
if(_i2c_write_byte1(REG_Address))
{
_i2c_stop1();
return 0;
}
_i2c_start1();
if(_i2c_write_byte1(SlaveAddress+1))
{
_i2c_stop1();
return 0;
}
REG_data = _i2c_read_byte1(0);
_i2c_stop1();
I2C_DELAY_LONG;
return REG_data;
}
unsigned char MPU_Write_Len1(unsigned char SlaveAddress,unsigned char REG_Address,unsigned char len,unsigned char *buf)
{
unsigned char i;
_i2c_start1();
if(_i2c_write_byte1(SlaveAddress))
{
_i2c_stop1();
return ERROR_CODE_WRITE_ADDR;
}
if(_i2c_write_byte1(REG_Address))
{
_i2c_stop1();
return ERROR_CODE_WRITE_ADDR;
}
for(i=0;i
if(_i2c_write_byte1(buf[i]))
{
_i2c_stop1();
return ERROR_CODE_WRITE_ADDR;
}
}
_i2c_stop1();
return 0;
}
unsigned char MPU_Read_Len1(unsigned char SlaveAddress,unsigned char REG_Address,unsigned char len,unsigned char *buf)
{
_i2c_start1();
if(_i2c_write_byte1(SlaveAddress))
{
_i2c_stop1();
return ERROR_CODE_READ_ADDR;
}
if(_i2c_write_byte1(REG_Address))
{
_i2c_stop1();
return ERROR_CODE_READ_ADDR;
}
_i2c_start1();
if(_i2c_write_byte1(SlaveAddress+1))
{
_i2c_stop1();
return ERROR_CODE_READ_ADDR;
}
while(len)
{
if(len==1)*buf=_i2c_read_byte1(0);
else *buf=_i2c_read_byte1(1);
len--;
buf++;
}
_i2c_stop1();
return 0;
}
unsigned char MPU0605_Init1(void)
{
unsigned char res;
nrf_delay_ms(100);
IIC_IO_Init1();
nrf_delay_ms(100);
MPU_X050_Write_Byte1(MPU6050_Addr,PWR_MGMT_1,0X80);
nrf_delay_ms(100);
MPU_X050_Write_Byte1(MPU6050_Addr,PWR_MGMT_1, 0x00);
MPU_X050_Write_Byte1(MPU6050_Addr,SMPLRT_DIV, 7);
MPU_X050_Write_Byte1(MPU6050_Addr,CONFIG, 0x06);
MPU_X050_Write_Byte1(MPU6050_Addr,GYRO_CONFIG, 0x18);
MPU_X050_Write_Byte1(MPU6050_Addr,ACCEL_CONFIG, 0x00);
MPU_X050_Write_Byte1(MPU6050_Addr,MPU_INT_EN_REG,0X00);
MPU_X050_Write_Byte1(MPU6050_Addr,MPU_USER_CTRL_REG,0X00);
MPU_X050_Write_Byte1(MPU6050_Addr,MPU_FIFO_EN_REG,0X00);
nrf_delay_ms(50);
res=MPU_X050_Read_Byte1(MPU6050_Addr,WHO_AM_I);
printf("\r\nWHO = %x", res);
if(res==0x68)
{
MPU_X050_Write_Byte1(MPU6050_Addr,PWR_MGMT_1, 0x03);
MPU_X050_Write_Byte1(MPU6050_Addr,PWR_MGMT_2, 0x00);
}
else
return 1;
return 0;
}
unsigned char MPU_Get_Accelerometer1(void)
{
unsigned char buf[6],res;
res=MPU_Read_Len1(MPU6050_Addr,ACCEL_XOUT_H,6,buf);
if(res==0)
{
MPU6050_ACCEL_OUT1.ACCEL_xOUT=((int)buf[0]<<8)|buf[1];
MPU6050_ACCEL_OUT1.ACCEL_yOUT=((int)buf[2]<<8)|buf[3];
MPU6050_ACCEL_OUT1.ACCEL_zOUT=((int)buf[4]<<8)|buf[5];
}
return res;
}
void test_MPU60501(void)
{
#if(user_printf==jiaodu)
float Accel_x;
float Accel_y;
float Accel_z;
MPU_Get_Accelerometer1();
Accel_x = MPU6050_ACCEL_OUT1.ACCEL_xOUT;
Accel_y = MPU6050_ACCEL_OUT1.ACCEL_yOUT;
Accel_z = MPU6050_ACCEL_OUT1.ACCEL_zOUT;
if(Accel_x>=0x8000)
{
Accel_x = -(65536-Accel_x);
}
if(Accel_y>=0x8000)
{
Accel_y = -(65536-Accel_y);
}
if(Accel_z>=0x8000)
{
Accel_z = -(65536 - Accel_z);
}
Accel_x=(int)((Accel_x/16384.0f)*1000);
Accel_y=(int)((Accel_y/16384.0f)*1000);
Accel_z=(int)((Accel_z/16384.0f)*1000);
printf("X1 %d ",(int)Accel_x);
printf("Y1 %d ",(int)Accel_y);
printf("Z1 %d ",(int)Accel_z);
#else
MPU_Get_Accelerometer1();
// printf("X1 %d ",MPU6050_ACCEL_OUT1.ACCEL_xOUT);
// printf("Y1 %d ",MPU6050_ACCEL_OUT1.ACCEL_yOUT);
// printf("Z1 %d ",MPU6050_ACCEL_OUT1.ACCEL_zOUT);
#endif
}