打印
[STM32F1]

求救啊,51移植成32的时候iic部分出错啊,求大神指点

[复制链接]
644|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gonghao199471|  楼主 | 2016-3-24 08:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我51的代码成功,可移植成32的时候iic部分可能有问题,lcd不显示,以下是我32的iic部分代码,求大神指点哪里有问题啊
/**************************************
起始信号
**************************************/
void ADXL345_Start()
{
    SDA(1);                    //拉高数据线
    SCL (1);                    //拉高时钟线
    Delay_us(5);                 //延时
    SDA (0);                    //产生下降沿
    Delay_us(5);                 //延时
    SCL (0);                    //拉低时钟线
}
/**************************************
起始信号
**************************************/
void ADXL345_Stop()
{
  SDA(0);  //SDA=0;   //发送结束条件的数据信号
  Delay_us(1);      //发送结束条件的时钟信号
  SCL(1)        ; //SCL=1; 结束条件建立时间大于4μs
  Delay_us(5);
  SDA(1);  //SDA=1; 发送I2C总线结束信号
  Delay_us(4);
}

/********************************************************************
                     应答子函数
函数原型:  void Ack_I2c(bit a);
功能:      主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
********************************************************************/
void Ack_I2c(u8 a)
{

  if(a==0)
   
   SDA(0);  //SDA=0;在此发出应答或非应答信号
  else
   SDA(1);  //SDA=1;
  Delay_us(3);   

  SCL(1);   //SCL=1;         
  Delay_us(4);        //时钟低电平周期大于4μs

  SCL(0)        ;   //SCL=0; 清时钟线,钳住I2C总线以便继续接收
  Delay_us(2);

}

/**************************************
向IIC总线发送一个字节数据
**************************************/
void  ADXL345_SendByte(unsigned char  c)
{
unsigned char  BitCnt;

for(BitCnt=0;BitCnt<8;BitCnt++)  //要传送的数据长度为8位
    {
     if((c<<BitCnt)&0x80) SDA(1);  //SDA=1; 判断发送位
     else SDA(0); // SDA=0               
     Delay_us(1);
     SCL(1);      //SCL=1 置时钟线为高,通知被控器开始接收数据位
         Delay_us(5);  //保证时钟高电平周期大于4μs
     SCL(0);             //SCL = 0
    }
   
    Delay_us(2);
    SDA(1);   //SDA=1 位发送完后释放数据线,准备接收应答位
        Delay_us(2);   
           SCL(1);   //SCL=1
    Delay_us(3);
    if(GPIO_ReadInputDataBit(GPIOB ,SData)==1)ack=0;     
    else ack=1;     //判断是否接收到应答信号
          SCL(0);   //SCL=0;
    Delay_us(3);
}

/**************************************
从IIC总线接收一个字节数据
**************************************/
unsigned char   ADXL345_RecvByte()
{
  unsigned char  retc;
  unsigned char  BitCnt;
  
  retc=0;
  SDA(1); //SDA=1 置数据线为输入方式
  for(BitCnt=0;BitCnt<8;BitCnt++)
      {
        Delay_us(1);           
        SCL(0);    //SCL=0 置时钟线为低,准备接收数据位
                Delay_us(5); //时钟低电平周期大于4.7μs
            
                SCL(1);         //SCL=1 置时钟线为高使数据线上数据有效
        Delay_us(2);
        retc=retc<<1;
        if(GPIO_ReadInputDataBit(GPIOB , SData)== 1)retc=retc+1; // SDA == 1读数据位,接收的数据位放入retc中
        Delay_us(2);
      }
  SCL(0); // SCL=0;
  Delay_us(2);
  return(retc);
}

//******单字节写入*******************************************

u8 Single_Write_ADXL345(unsigned char REG_Address,unsigned char REG_data)
{

   ADXL345_Start();              /*启动总线*/
   ADXL345_SendByte(SlaveAddress);            /*发送器件地址*/
   ADXL345_SendByte(REG_Address);            //发送存储单元地址,从0开始
   ADXL345_SendByte(REG_data);
   ADXL345_Stop();                /*结束总线*/

   return(1);
}

//********单字节读取*****************************************
u8 Single_Read_ADXL345(unsigned char  REG_Address)
{
   unsigned char REG_data;

   ADXL345_Start();
   ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号                  /*启动总线*/
  ADXL345_SendByte(REG_Address);

   ADXL345_Start();                 /*重新启动总线*/
   ADXL345_SendByte(SlaveAddress+1);
   REG_data=ADXL345_RecvByte();
   Ack_I2c(1);                   /*发送非应位*/
   ADXL345_Stop();                   /*结束总线*/
   return  REG_data        ;
}
//*********************************************************
//
//连续读出ADXL345内部加速度数据,地址范围0x32~0x37
//
//*********************************************************
void Multiple_read_ADXL345(void)
{   
    uchar i;
    ADXL345_Start();                          //起始信号
    ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
    ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始       
    ADXL345_Start();                          //起始信号
    ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
         for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
    {
        BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
        if (i == 5)
        {
           Ack_I2c(1);                //最后一个数据需要回NOACK
        }
        else
        {
          Ack_I2c(0);                //回应ACK
       }
   }
    ADXL345_Stop();                          //停止信号
    Delay_ms(5);
}
沙发
airwill| | 2016-3-24 10:00 | 只看该作者
这基本是时序问题导致的, 由于 stm32 的执行速度快. 原来指令间不需要的延时也需要补全.
比如:
void ADXL345_Start()
{
    SDA(1);                    //拉高数据线
    SCL (1);                    //拉高时钟线
    ...

这两条是有先后顺序, 但由于指令速度快, 拉高是通过上拉电阻完成, 总线上的反应时间不太确定, 最终的结果未必 SDA 先置高了.
不见得问题就在这里, 你可以相关地方一一分析, 或者用示波器捕捉波形来分析.

使用特权

评论回复
板凳
gonghao199471|  楼主 | 2016-3-24 10:22 | 只看该作者
现在的问题是读不到数据,小白很无奈啊,要疯了

使用特权

评论回复
地板
mmuuss586| | 2016-3-24 12:44 | 只看该作者
那示波器对比下,时序的脉冲宽度不一样吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

55

帖子

0

粉丝