OpenEdv-开源电子网

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

STM8模拟IIC的问题,和加速度计模块MMA8452Q通信异常

[复制链接]

1

主题

6

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-4-19
在线时间
4 小时
发表于 2017-4-19 15:04:13 | 显示全部楼层 |阅读模式
2金钱
最近想用STM8S103F3驱动MMA8452Q这个加速度计,可是我模拟的IIC读到的一直是FF,下面是我写的程序,希望可以收到大家的指点,小弟谢谢了!





[mw_shl_code=c,true].C文件


#include "soft_i2c.h"
#include "math.h"
#include "gpio.h"
u8     BUF[8];
int    dis_data;
float  x,y,z;
//===============================================================================
//功能:初始化IIC
//输入:无
//输出:无
//返回:无
//===============================================================================
void Soft_I2C_Int(void)
{
  Set_I2C_SCL_Out1;
  Set_I2C_SDA_Out1;  
//  Set_I2C_SCL_HIGHT;
//  Set_I2C_SDA_HIGHT;
}
//===============================================================================
//功能:模拟I2C的起始条件
//名称: Soft_I2C_Start
//输入:无
//返回:无
//说明: 标准的I2C协议I2C起始条件:SCL为高时,SDA由高变低
//===============================================================================
void Soft_I2C_Start(void)
{
  Set_I2C_SDA_Out1;
  Set_I2C_SCL_HIGHT;
  delay_us(5);
  Set_I2C_SDA_LOW;
  //标准的I2C协议I2C起始条件:SCL为高时,SDA由高变低
  delay_us(5);
  Set_I2C_SCL_LOW;//钳住I2C总线,准备发送或接收数据
}
//===============================================================================
//名称: Soft_I2C_Stop
//功能: 模拟I2C的停止条件
//返回: 无
//说明: 标准的I2C协议I2C停止条件:SCL为高时,SDA由低变高      
//===============================================================================
void Soft_I2C_Stop(void)
{
  Set_I2C_SDA_Out0;
  Set_I2C_SCL_HIGHT;
  delay_us(5);
  Set_I2C_SDA_HIGHT;
  //标准的I2C协议I2C停止条件:SCL为高时,SDA由低变高
  delay_us(5);
}
//===============================================================================
//名称: Soft_I2C_Ack
//功能: 模拟I2C的应答  
//返回:无
//===============================================================================
void Soft_I2C_Ack(void)
{
  Set_I2C_SDA_Out0;
  Set_I2C_SCL_HIGHT;
  delay_us(5);
  Set_I2C_SCL_LOW;
  delay_us(5);
}
//===============================================================================
//名称: Soft_I2C_NAck
//功能: 模拟I2C的不应答
//===============================================================================
void Soft_I2C_NAck(void)
{
  Set_I2C_SDA_Out1;  
  Set_I2C_SCL_HIGHT;
  delay_us(5);
  Set_I2C_SCL_LOW;
  delay_us(5);
}
//===============================================================================
//名称: Soft_I2C_recvACK
//功能: 接收应答信号
//===============================================================================
BitAction Soft_I2C_RecvAck(void)
{
  BitAction CY;
  Set_I2C_SDA_In;
  Set_I2C_SCL_HIGHT;
  delay_us(5);
  CY =(BitAction) Get_I2C_SDA;
  Set_I2C_SCL_LOW;
  delay_us(5);
  
  return CY;
}
//===============================================================================
//名称: Soft_I2C_Send_Byte
//功能: 模拟I2C主器件向从器件发送一个字节
//形参: Byte     
//返回: 无
//===============================================================================
void Soft_I2C_Send_Byte(u8 Byte)
{
  u8 bit,temp;
  for(bit=0;bit<8;bit++)
  {
    temp = Byte & 0x80;
    if(temp == 0)
    {
      Set_I2C_SDA_Out0;
    }
    else if(temp > 0)
    {
       Set_I2C_SDA_Out1;
    }
    Set_I2C_SCL_HIGHT;
    delay_us(5);      
    Set_I2C_SCL_LOW;
    delay_us(5);
    Byte<<= 1;
  }
  Soft_I2C_RecvAck();
}
//===============================================================================
//名称: Soft_I2C_Read_Byte
//功能: 模拟I2C主器件向从器件读取一个字节
//形参: 无
//返回: 一个字节
//明: 主器件从从器件里读一个字节  
//===============================================================================
u8 Soft_I2C_Recv_Byte(void)
{
  u8 bit,dat=0;
  Set_I2C_SDA_In;
  for(bit=0;bit<8;bit++)
  {
    dat<<=1;   //把上一时刻的值左移一位
    Set_I2C_SCL_HIGHT;   
    delay_us(5);   
    dat |= Get_I2C_SDA;
    Set_I2C_SCL_LOW;
    delay_us(5);
  }
  return dat;
}
//============================================================
//功能:单字节写入
//输入:无
//输出:无
//返回:无
//===============================================================================
void Single_Write_MMA8452(unsigned char REG_Address,unsigned char REG_data)
{
    Soft_I2C_Start();                    //起始信号
    Soft_I2C_Send_Byte(SlaveAddress);    //发送设备地址+写信号
    Soft_I2C_Send_Byte(REG_Address);     //内部寄存器地址
    Soft_I2C_Send_Byte(REG_data);        //内部寄存器数据
    Soft_I2C_Stop();                     //停止信号
}
//===============================================================================
//功能:连续读出MMA8452内部加速度数据,地址范围0x01~0x06
//输入:无
//输出:无
//返回:无
//===============================================================================
void Multiple_Read_MMA8452(void)
{   
    unsigned char i;
    Soft_I2C_Start();                          //起始信号
    Soft_I2C_Send_Byte(SlaveAddress);          //发送设备地址

    Soft_I2C_Send_Byte(0x01);                  //发送存储单元地址,从0x01开始
    Soft_I2C_Start();                          //起始信号
    Soft_I2C_Send_Byte(SlaveAddress+1);        //发送设备地址+读信号
       
    for (i=0; i<6; i++)                       //连续读取6个地址数据
    {
      BUF = Soft_I2C_Recv_Byte();          //BUF[0]存储0x32地址中的数据
      if (i == 5)
      {
        Soft_I2C_NAck();                      //最后一个数据需要回NACK         
      }
      else
      {
        Soft_I2C_Ack();                       //回应ACK
      }
   }
    Soft_I2C_Stop();                           //停止信号
    delay_us(5);
}
//===============================================================================
//功能:初始化IIC
//输入:无
//输出:无
//返回:无
//===============================================================================
void Init_MMA8452(void)
{
   Soft_I2C_Int();                  //
   Single_Write_MMA8452(0x2A,0x01); //
   Single_Write_MMA8452(0x2B,0x02); //
}
//====================X轴数据====================================================
float Get_x(void)
{   
    dis_data = (BUF[0]<<8)|BUF[1];//
        dis_data >>= 4;                  //
        x = (float)dis_data;
        return x;
}

//====================Y轴数据====================================================
float Get_y(void)
{   
    dis_data=(BUF[2]<<8)|BUF[3]; //
        dis_data>>=4;                 //
        y=(float)dis_data;
        return y;
}
//====================Z轴数据====================================================
float Get_z(void)
{  
    dis_data=(BUF[4]<<8)|BUF[5];//
    dis_data>>=4;                //
        z=(float)dis_data;
        return z;
}
//===============================================================================
//功能:us级别延时,必须大于0
//输入:无
//输出:无
//返回:无
//===============================================================================
void delay_us(volatile unsigned short time)
{
  do{
      asm("nop");
      asm("nop");
      asm("nop");
      asm("nop");
      asm("nop");
      asm("nop");
    }while(--time);
}


.h文件

#ifndef SOFT_I2C_H
#define SOFT_I2C_H
#include "stm8s.h"
#define I2C_PIN  GPIOB
#define I2C_SCL  GPIO_PIN_4
#define I2C_SDA  GPIO_PIN_5
#define Set_I2C_SCL_HIGHT    GPIO_WriteHigh(I2C_PIN, I2C_SCL)
#define Set_I2C_SCL_LOW      GPIO_WriteLow(I2C_PIN, I2C_SCL)
#define Set_I2C_SDA_HIGHT    GPIO_WriteHigh(I2C_PIN, I2C_SDA)
#define Set_I2C_SDA_LOW      GPIO_WriteLow(I2C_PIN, I2C_SDA)
#define Get_I2C_SDA          GPIO_ReadInputPin(I2C_PIN, I2C_SDA)
#define Set_I2C_SCL_Out1      GPIO_Init(I2C_PIN, I2C_SCL, GPIO_MODE_OUT_PP_HIGH_FAST)
#define Set_I2C_SDA_Out1      GPIO_Init(I2C_PIN, I2C_SDA, GPIO_MODE_OUT_PP_HIGH_FAST)
#define Set_I2C_SCL_Out0      GPIO_Init(I2C_PIN, I2C_SCL, GPIO_MODE_OUT_PP_LOW_FAST)
#define Set_I2C_SDA_Out0      GPIO_Init(I2C_PIN, I2C_SDA, GPIO_MODE_OUT_PP_LOW_FAST)

#define Set_I2C_SDA_In       GPIO_Init(I2C_PIN, I2C_SDA, GPIO_MODE_IN_FL_NO_IT)//PU换成FL

#define        SlaveAddress         0x38

void Soft_I2C_Int(void);
void Soft_I2C_Start(void);
void Soft_I2C_Stop(void);
void Soft_I2C_Ack(void);
void Soft_I2C_NAck(void);
void Soft_I2C_Send_Byte(u8 Byte);
u8 Soft_I2C_Recv_Byte(void);
void Single_Write_MMA8452(unsigned char REG_Address,unsigned char REG_data);
void delay_us(volatile unsigned short time);
BitStatus Soft_I2C_RecvAck(void);
void delay_init(unsigned char clk);
void Init_MMA8452(void);
void Multiple_Read_MMA8452(void);




float Get_x(void);
float Get_y(void);
float Get_z(void);


//void Multiple_Read_MMA8452(void)

//void I2C_MMA8452_ReadByte(void)
#endif[/mw_shl_code]

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-4-19
在线时间
4 小时
 楼主| 发表于 2017-4-19 15:09:43 | 显示全部楼层
我的编译环境是IAR FOR STM8
回复

使用道具 举报

6

主题

93

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
317
金钱
317
注册时间
2016-11-1
在线时间
64 小时
发表于 2017-4-19 16:28:48 | 显示全部楼层
你这里
Set_I2C_SCL_Out1;
Set_I2C_SDA_Out1;

Set_I2C_SCL_Out0;
Set_I2C_SDA_Out0;
0和1有啥区别啊
回复

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
发表于 2017-4-19 20:11:03 | 显示全部楼层
I2C玩的是开漏模式输出,其它的做法都不是正解.不推荐,不赞成.
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-4-19
在线时间
4 小时
 楼主| 发表于 2017-4-19 22:59:53 | 显示全部楼层
fankai 发表于 2017-4-19 16:28
你这里
Set_I2C_SCL_Out1;
Set_I2C_SDA_Out1;

输出,1是高,0是低。不对吗?
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-4-19
在线时间
4 小时
 楼主| 发表于 2017-4-19 23:00:40 | 显示全部楼层
操作系统 发表于 2017-4-19 20:11
I2C玩的是开漏模式输出,其它的做法都不是正解.不推荐,不赞成.

谢谢,您的意思是我的引脚输出模式错误?
回复

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
发表于 2017-4-20 09:18:08 | 显示全部楼层
木子又 发表于 2017-4-19 23:00
谢谢,您的意思是我的引脚输出模式错误?

错倒是说不上.用推挽输出方式+上拉输入方式,两个方式切换也是可以完成I2C程序的.但这是不正确的解决办法.使用开漏输出的方式才是正确的.STM8的I2C引脚本身就强制了开漏功能.无推挽输出功能可设置.由此可见.I2C应该设置为开漏输出模式.个人意见..
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-4-19
在线时间
4 小时
 楼主| 发表于 2017-4-21 15:18:10 | 显示全部楼层
操作系统 发表于 2017-4-20 09:18
错倒是说不上.用推挽输出方式+上拉输入方式,两个方式切换也是可以完成I2C程序的.但这是不正确的解决办法. ...

谢谢提醒
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-4-19
在线时间
4 小时
 楼主| 发表于 2017-4-21 15:19:24 | 显示全部楼层
依然没有解决,在对加速度计进行写操作的时候没有接收到应答
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-26 09:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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