查看: 1385|回复: 0

STM32两轮平衡小车——传感器IIC协议

[复制链接]
  • TA的每日心情
    开心
    2015-7-7 09:19
  • 签到天数: 13 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2015-7-2 13:11:29 | 显示全部楼层 |阅读模式
    分享到:
    上一篇主要讲述了如何对电机进行控制,接下来就该进行传感器相关的讲解了,而对于传感器部分,我是使用的MPU6050+HMC5883结合。而MPU6050呢又可以将HMC5883作为他的从机(我是这么理解的,也不知对不对)。传感器的数据通信是使用的IIC通信协议,IIC通信协议的最大好处呢就是只需要使用两个引脚就可以进行数据的交换和控制;还有就是它可以一对多,也就是说一个主机对应多个从机,每次主机需要通信时需要先发送从机地址。但是他也有他的缺点就是传输数度最大400K,而且仅适用于板上数据通信,因为其传输的距离比较有限。
      IIC的连接方式和数据通信协议图如下所示(借用于百度):


      对于IIC的通信和串口一样STM32也有其通信的相关接口,但是由于前段时间STM32的IIC通信让人不是很满意(偶尔无故进入死循环),所以现在大部分人员都还是使用的模拟IIC,而且网上相关代码很多都是大同小异。接下来我就将相关主要代码贴上。
      IIC引脚初始化:
    GPIO_InitTypeDef GPIO_InitStructure;         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                                      //配置PB6 PB7 为开漏输出  刷新频率为10Mhz         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;                  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;          //应用配置到GPIOB           GPIO_Init(GPIOB, &GPIO_InitStructure);  IIC数据引脚输入输出改变:
    #define IIC_SCL    PBout(6) //SCL#define IIC_SDA    PBout(7) //SDA         #define READ_SDA   PBin(7)  //输入SDA 接下来就是各种函数:void IIC_Start(void){        SDA_OUT();     //sda线输出        IIC_SDA=1;                            IIC_SCL=1;        delay_us(4);         IIC_SDA=0;//START:when CLK is high,DATA change form high to low         delay_us(4);        IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 }          void IIC_Stop(void){        SDA_OUT();//sda线输出        IIC_SCL=0;        IIC_SDA=0;//STOP:when CLK is high DATA change form low to high         delay_us(4);        IIC_SCL=1;         IIC_SDA=1;//发送I2C总线结束信号        delay_us(4);                                                                   }u8 IIC_Wait_Ack(void){        u8 ucErrTime=0;        SDA_IN();      //SDA设置为输入          IIC_SDA=1;delay_us(1);                   IIC_SCL=1;delay_us(1);                 while(READ_SDA)        {                ucErrTime++;                if(ucErrTime>50)                {                        IIC_Stop();                        return 1;                }          delay_us(1);        }        IIC_SCL=0;//时钟输出0                    return 0;  } void IIC_Ack(void){        IIC_SCL=0;        SDA_OUT();        IIC_SDA=0;        delay_us(2);        IIC_SCL=1;        delay_us(2);        IIC_SCL=0;}                    void IIC_NAck(void){        IIC_SCL=0;        SDA_OUT();        IIC_SDA=1;        delay_us(2);        IIC_SCL=1;        delay_us(2);        IIC_SCL=0;}                                                                                        void IIC_Send_Byte(u8 txd){                            u8 t;           SDA_OUT();                 IIC_SCL=0;//拉低时钟开始数据传输    for(t=0;t<8;t++)    {                      IIC_SDA=(txd&0x80)>>7;        txd<<=1;                           delay_us(2);                   IIC_SCL=1;                delay_us(2);                 IIC_SCL=0;                        delay_us(2);    }         }             u8 IIC_Read_Byte(unsigned char ack){        unsigned char i,receive=0;        SDA_IN();//SDA设置为输入    for(i=0;i<8;i++ )        {        IIC_SCL=0;         delay_us(2);                IIC_SCL=1;        receive<<=1;        if(READ_SDA)receive++;                   delay_us(2);     }                                             if (ack)        IIC_Ack(); //发送ACK     else        IIC_NAck();//发送nACK      return receive;}unsigned char I2C_ReadOneByte(unsigned char I2C_Addr,unsigned char addr){        unsigned char res=0;                IIC_Start();                IIC_Send_Byte(I2C_Addr);           //发送写命令        res++;        IIC_Wait_Ack();        IIC_Send_Byte(addr); res++;  //发送地址        IIC_Wait_Ack();                  //IIC_Stop();//产生一个停止条件                IIC_Start();        IIC_Send_Byte(I2C_Addr+1); res++;          //进入接收模式                                   IIC_Wait_Ack();        res=IIC_Read_Byte(0);               IIC_Stop();//产生一个停止条件        return res;}u8 IICreadBytes(u8 dev, u8 reg, u8 length, u8 *data){    u8 count = 0;                IIC_Start();        IIC_Send_Byte(dev);           //发送写命令        IIC_Wait_Ack();        IIC_Send_Byte(reg);   //发送地址    IIC_Wait_Ack();                  IIC_Start();        IIC_Send_Byte(dev+1);  //进入接收模式                IIC_Wait_Ack();            for(count=0;count<length;count++){                                  if(count!=length-1)data[count]=IIC_Read_Byte(1);  //带ACK的读数据                         else  data[count]=IIC_Read_Byte(0);         //最后一个字节NACK        }    IIC_Stop();//产生一个停止条件    return count;}u8 IICwriteBytes(u8 dev, u8 reg, u8 length, u8* data){           u8 count = 0;        IIC_Start();        IIC_Send_Byte(dev);           //发送写命令        IIC_Wait_Ack();        IIC_Send_Byte(reg);   //发送地址    IIC_Wait_Ack();                  for(count=0;count<length;count++){                IIC_Send_Byte(data[count]);                 IIC_Wait_Ack();          }        IIC_Stop();//产生一个停止条件    return 1; //status == 0;}u8 IICreadByte(u8 dev, u8 reg, u8 *data){        *data=I2C_ReadOneByte(dev, reg);    return 1;}unsigned char IICwriteByte(unsigned char dev, unsigned char reg, unsigned char data){    return IICwriteBytes(dev, reg, 1, &data);}u8 IICwriteBits(u8 dev,u8 reg,u8 bitStart,u8 length,u8 data){    u8 b;    if (IICreadByte(dev, reg, &b) != 0) {        u8 mask = (0xFF << (bitStart + 1)) | 0xFF >> ((8 - bitStart) + length - 1);        data <<= (8 - length);        data >>= (7 - bitStart);        b &= mask;        b |= data;        return IICwriteByte(dev, reg, b);    } else {        return 0;    }}u8 IICwriteBit(u8 dev, u8 reg, u8 bitNum, u8 data){    u8 b;    IICreadByte(dev, reg, &b);    b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));    return IICwriteByte(dev, reg, b);}
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-4-27 02:02 , Processed in 0.112164 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.