话不多说,直接上代码,不懂的看注解
//本程序使用的IIC器件是一个三轴加速度,型号MMA845x
#define IIC_WRITE 0x1C
#define IIC_READ 0x1C
#define clk_hight (HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET)) //本程序IIC的时钟线接在PB6,置高
#define clk_low (HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET)) //本程序IIC的时钟线接在PB6,置低
#define sda_hight (HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET)) //本程序IIC的数据线接在PB7,置高
#define sda_low (HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET)) //本程序IIC的数据线接在PB7,置低
#define sda_rd HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)
#define sda_setin iic_in()//设置数据线为输入模式
#define sda_setout iic_out()//设置数据线为输出模式
void usleep(uint16_t t)//自定义一个延时函数
{
for(uint16_t i=0;i<16*t;i++)
{
__NOP();
}
}
void iic_IO_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_3; //本程序的IIC器件电源引脚PB3
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);//开启IIC传感器电源
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
usleep(10);
}
void iic_in()//数据线的输入模式设置
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
usleep(10);
}
void iic_out()//数据线的输出模式设置
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
usleep(10);
}
void iic_start()//开始信号
{
sda_setout;
clk_hight;
sda_hight;
usleep(4);
sda_low;
usleep(4);
clk_low;
}
void iic_stop()//结束信号
{
sda_setout;
sda_low;
clk_low;
usleep(4);
clk_hight;
sda_hight;
usleep(4);
}
void iic_nack()//非应答信号
{
clk_low;
sda_setout;
sda_hight;
usleep(2);
clk_hight;
usleep(2);
clk_low;
}
void iic_ack()//应答信号
{
clk_low;
sda_setout;
sda_low;
usleep(2);
clk_hight;
usleep(2);
clk_low;
}
uint8_t iic_wait_ack()//等待应答
{
uint8_t ucErrTime=0;
sda_setin;
clk_hight;
usleep(1);
sda_hight;
usleep(1);
while(sda_rd)
{
ucErrTime++;
if(ucErrTime>250)
{
iic_stop();
return 1;
}
}
clk_low;
return 0;
}
void iic_write_byte(uint8_t wr)//写字节
{
unsigned char i;
sda_setout;
clk_low;//拉低时钟开始数据传输
for(i=0;i<8;i++)
{
if((wr & 0x80)>>7)
sda_hight;
else
sda_low;
wr <<= 1;
usleep(2);
clk_hight;
usleep(2);
clk_low;
usleep(2);
}
}
uint8_t iic_read_byte(unsigned char ack)//读字节
{
unsigned char i,receive=0;
sda_setin;//SDA设置为输入
for(i=0;i<8;i++ )
{
clk_low;
usleep(2);
clk_hight;
receive<<=1;
if(sda_rd) receive++;
usleep(1);
}
if (!ack)
iic_nack();//发送nACK
else
iic_ack(); //发送ACK
return receive;
}
uint8_t iic_write(uint8_t uint8_add,uint8_t rdata)//写地址+命令
{
iic_start();
iic_write_byte((IIC_WRITE<<1));//发送器件地址+写命令
if(iic_wait_ack())//等待应答
{
iic_stop();
return 1;
}
iic_write_byte(uint8_add);//写寄存器地址
iic_wait_ack();//等待应答
iic_write_byte(rdata);//发送数据
if(iic_wait_ack())//等待ACK
{
iic_stop();
return 1;
}
iic_stop();
return 0;
}
//IIC连续读
//addr:器件地址
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
//其他,错误代码
uint8_t MPU_Read_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
{
iic_start();
iic_write_byte((IIC_READ<<1)); //发送器件地址+写命令
if(iic_wait_ack()) //等待应答
{
iic_stop();
return 1;
}
iic_write_byte(reg); //写寄存器地址
iic_wait_ack(); //等待应答
iic_start();
iic_write_byte((addr<<1)|1); //发送器件地址+读命令
iic_wait_ack(); //等待应答
while(len)
{
if(len==1)
*buf=iic_read_byte(0); //读数据,发送nACK
else
*buf=iic_read_byte(1); //读数据,发送ACK
len--;
buf++;
}
iic_stop(); //产生一个停止条件
return 0;
}
void I2cinit(void)//这是初始化一个三轴加速度的,型号MMA845
{
iic_IO_init();
usleep(100);
iic_write(0x0a,0x01);
iic_write(0x0b,0x02);
iic_write(0x2a,0x18);
iic_write(0x1d,0x16);
iic_write(0x1f,0x08);
usleep(1);
iic_write(0x20,0x05);
usleep(1);
iic_write(0x2d,0x20);
usleep(1);
iic_write(0x0e,0x12);
usleep(1);
iic_write(0x0f,0x03);
usleep(1);
iic_write(0x2e,0x20);
usleep(1);
iic_write(0x2a,0x18 | 0x01);
usleep(1);
}
void mma845x_value(void)
{
uint8_t res,buf[6];
float K_Q = 0.1,K_P = 2;
short X,Y,Z;
for(uint8_t i=0;i<6;i++)
{
res=MPU_Read_Len(0x1C,i+1,1,&buf[i]);
}
if(res==0)
{
X=(buf[0]<<8)|buf[1];//获取三轴加速度的X值
Y=(buf[2]<<8)|buf[3];//获取三轴加速度的Y值
Z=(buf[4]<<8)|buf[5];//获取三轴加速度的Z值
}
}