OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5747|回复: 1

MMA7660模块,读到的数值一直都是0。不知道是不是IIC的问题,IIC部分我是用的原子哥的代码,只加了几个函数,求救一下大家

[复制链接]

1

主题

3

帖子

0

精华

新手入门

积分
27
金钱
27
注册时间
2014-8-29
在线时间
0 小时
发表于 2015-7-8 17:39:42 | 显示全部楼层 |阅读模式
5金钱

主函数部分

#define MMA7660ADRW   0x98   // write address
#define MMA7660ADRR   0x99  // read address
#define  True  1
#define  False 0
#define CHSBIT6  0x0040

#define  True  1
#define  False 0
#define  ZERO       0
#define  ONE          1
#define  TWO          2
#define  THREE        3
#define  FOUR         4
#define  FIVE         5
#define  SIX          6
#define  SEVEN        7
#define  EIGHT        8
#define  NINE         9
#define  TEN          10
#define  HUNDRED      100
#define  THOUSAND     1000
#define  HALFBYTEMAX  15
#define  ONEBYTEMAX   255

//输出方向值
enum{
  DIRT0,    //正向
  DIRT1,      //左向
  DIRT2,      //右向
  DIRT3       //反向
};
//重力传感器Pola状态(过去.现在)
u8 Pre_PoLaStatus, Cur_PoLaStatus; 
//方向输出控制
u8 DirtOutputFlag = False;
//系统方向值
u8 Dirt_Vaule = DIRT0;
//内部寄存器地址 Xout/TILT
const u8 AddressXout[] = {0x00}, AddressTILT[] = {0x03};

//方向检测控制
u8 Dirt_CheckFlag = True;

//开启模块并执行初始化
void DirtModeOn(void)
{
  /* 0x07模式寄存器,待机模式, 自动睡眠计数器分频系数为 1 */
  u8 Data1[]= {0x07,0x00};
  /*0x05--Sleep Count Register ,0xff--32秒后进入睡眠状态,0x03--前后左右上下方向改变,产生中断*/ 
  u8 Data2[]= {0x05,0xff,0x03};
  /*0x08--Sample Rate Register,在活跃状态下 8 samples/second ,
  在睡眠状态下,1 sample/second,2个测量样本相匹配,则更新TILT寄存器 */ 
  u8 Data3[]= {0x08,0x3c,0xe0,0x00};
  /* 0x07模式寄存器,活跃模式,自动睡眠使能,自动唤醒使能, 自动睡眠计数器分频系数为 1 */  
  /*中断推挽输出,低电平有效(下降沿)*/
  u8 Data4[]={0x07,0x59};
  //I2C_ON();
  I2C_Send(MMA7660ADRW,Data1,TWO);  //在对其他寄存器进行操作前,应该先让mma7660处于待命模式
  I2C_Send(MMA7660ADRW,Data2,THREE); //初始化自动 睡眠寄存器(0x05)和中断 配置寄存器(0x06)
  I2C_Send(MMA7660ADRW,Data3,FOUR);   //设置采样率,不使能tap检测,
  I2C_Send(MMA7660ADRW,Data4,TWO);   //进入active模式
  //Driver_I2COFF(); 
}

//x/y/z-out加速度对应值
//0 +:1-22  -:63-42
const u16 G_Num[] = {0, 47, 94, 141, 188, 234, 281, 328, 375, 422, 469, 516, 563, 609, 656, 703, 750, 797, 844, 891, 938, 984, 1000};

//当前加速度值0-2000
u16 XOut = 0;
u16 YOut = 0;
int main(void)
{
 Stm32_Clock_Init(9); //系统时钟设置
 uart_init(72,9600);   //串口初始化为9600
 delay_init(72);       //延时初始化
 IIC_Init();
 LED_Init();      //初始化与LED连接的硬件接口
 usmart_dev.init(72); //初始化USMART
  //方向传感器
    DirtModeOn();
  while(1)
  {
    u8 Buff[4];
    u32 DelayTimer;
    //读一次重力传感器的Xout.Yout.Zout.TILT
    I2C_Send(MMA7660ADRW, (u8*)AddressXout, 1);    
    I2C_Recv(MMA7660ADRR, Buff, 4);  
    if(Buff[3]&CHSBIT6)
    { 
      //若设备正在更新状态,再读一次TILT
      I2C_Send(MMA7660ADRW, (u8*)AddressTILT, 1);  
      I2C_Recv(MMA7660ADRR, &Buff[3], 1);
    }
    //获取POLA状态位 可用于简单判断方向值
    Cur_PoLaStatus  = ((Buff[3])>>2)&0x07; 
    //这里我们获取x/y/z-out值,存于Buff[0],Buff[1],Buff[2]中
    //本实验只需用到x-out与y-out值
    printf("%d\r\n",Buff[0]);
    printf("%d\r\n",Buff[1]);
    printf("%d\r\n",Buff[2]);
if(!(Buff[0]&CHSBIT6))
    {
      //bit6为零 x-out为有效值
      static u8 Num = 0;
      static s16 Temp[10];
      //采集加速度值并转换(-1000~1000)
      if(Buff[0] == 0 || (Buff[0] >=1 && Buff[0] <= 22))
       Temp[Num++] = G_Num[Buff[0]];
      else if(Buff[0] >=42 && Buff[0] <= 63)
      {
        Buff[0] -= 41;
        Buff[0] = 23 - Buff[0];
        Temp[Num++] = -G_Num[Buff[0]];
      }
      //消抖求平均值
      if(Num == 10)
      {
        u8 i;
        s16 BuffTemp;
        //找出最小值
        for(i=0; i<9; i++)
         if(Temp < Temp[i+1])
         {
           BuffTemp = Temp[i+1];
           Temp[i+1] = Temp;
           Temp = BuffTemp;
         }
        //找出最大值
        for(i=0; i<8; i++)
         if(Temp > Temp[i+1])
         {
           BuffTemp = Temp[i+1];
           Temp[i+1] = Temp;
           Temp = BuffTemp;
         }
        //计算平均值
        XOut = (Temp[0] + Temp[1]  + Temp[2] + Temp[3] + Temp[4] + Temp[5] + Temp[6] + Temp[7])/8 + 1000;
        //led显示
        if(XOut <= 1000)
        {
         // printf("%d",(1000-XOut));
        }
        else
        {
          printf("%d",(XOut-1000));
        }
        Num = 0;
      }    
    }

/*IIC部分*******************************************************************************************/
//初始化IIC
void IIC_Init(void)
{         
  RCC->APB2ENR|=1<<3;//先使能外设IO PORTB时钟        
 GPIOB->CRL&=0X00FFFFFF;//PB1/11 推挽输出
 GPIOB->CRL|=0X33000000;   
// GPIOB->ODR|=3<<6;     //PB10,11 输出高
}
//产生IIC起始信号
void I2C_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总线,准备发送或接收数据
}  
//产生IIC停止信号
void I2C_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);           
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
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>250)
  {
   I2C_Stop();
   return 1;
  }
 }
 IIC_SCL=0;//时钟输出0    
 return 0; 
}
//产生ACK应答
void I2C_ACK(void)
{
 IIC_SCL=0;
 SDA_OUT();
 IIC_SDA=0;
 delay_us(2);
 IIC_SCL=1;
 delay_us(2);
 IIC_SCL=0;
}
//不产生ACK应答     
void I2C_NACK(void)
{
 IIC_SCL=0;
 SDA_OUT();
 IIC_SDA=1;
 delay_us(2);
 IIC_SCL=1;
 delay_us(2);
 IIC_SCL=0;
}              
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答    
void I2C_SendAByter(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);   //对TEA5767这三个延时都是必须的
  IIC_SCL=1;
  delay_us(2);
  IIC_SCL=0; 
  delay_us(2);
    } 
}     
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK  
u8 I2C_ReadAByter(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(1);
    }     
    if (!ack)
        I2C_NACK();//发送nACK
    else
        I2C_ACK(); //发送ACK  
    return receive;
}


void I2C_Send(u8 Address, u8 *DataBuff, u16 DataLen)
{
  //发启始条件
  I2C_Start();
  //发从地址
  I2C_SendAByter(Address);
  //等待ACK应答
  IIC_Wait_Ack();
  //发送数据
  for(; DataLen>0; DataLen--, DataBuff++)
  {
    //发数据
    I2C_SendAByter(*DataBuff);
    //等待ACK应答
    IIC_Wait_Ack();
  }
  //发停止
  I2C_Stop();
}

void I2C_Recv(u8 Address, u8 *DataBuff, u16 DataLen)
{
  //发启始条件
  I2C_Start();
  //发从地址
  I2C_SendAByter(Address);
  //等待ACK应答
  IIC_Wait_Ack();
  
  //接收数据,读DataLen-1个数
  for(;DataLen>1;DataLen--,DataBuff++)
  {
    //等待寄存器为满
    *DataBuff = I2C_ReadAByter(1);
    //发应答
  }
  *DataBuff = I2C_ReadAByter(0);
  //发停止
  I2C_Stop(); 
}

/*IIC头文件***************************************************************/

#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=8<<7;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=3<<7;}

//IO操作函数 
#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA 
#define READ_SDA   PBin(7)  //输入SDA

//IIC所有操作函数
void IIC_Init(void);
void I2C_Send(u8 Address,u8 *DataBuff,u16 DataLen);
void I2C_Recv(u8 Address,u8 *DataBuff,u16 DataLen); 
#endif


主函数部分我是从库函数程序那边复制过来的。

 

最佳答案

查看完整内容[请看2#楼]

#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=8<<7;} #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=3<<7;} 改为: #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=8<<7*4;} #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=3<<7*4;}
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2015-7-8 17:39:43 | 显示全部楼层
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=8<<7;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=3<<7;}
改为:
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=8<<7*4;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=3<<7*4;}
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-24 21:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表