stm32模拟IIC操作

话不多说,直接上代码,不懂的看注解

//本程序使用的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值
	}	
}

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑟寒凌风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值