打印
[STM8]

STM8 ADS1115 硬件I2C 读数据有点问题

[复制链接]
5634|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 shuishuo615 于 2013-10-15 10:23 编辑

东拼西凑了下代码,
读ADS1115 的转换数据16位,MSB+LSB
调试现象:debug串口用watch功能 第一次while(1)的数据有问题,第二次以后进while读出正常。
比如接了3v 在ain端口,第一次while出来的数据ConversionResult是0x3eff,第二进while次才是0x3e80为正确值。我是在最后一句程序处设置断点查看的。估计是不是在读完MSB后的操作不正确?反正第一次读LSB总是0xff,第二次就对了。。。。。附上程序,只有一个main.c


附上ADS的读数据时序


/**
  ******************************************************************************
  *  
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"

/* Private defines -----------------------------------------------------------*/
#define ADS1115_ADDR        0x90  
#define ADS1115_POINT_CONFIG_REG 0x01
#define ADS1115_POINT_CONVERSION_REG 0x00

/* Private function prototypes -----------------------------------------------*/
u8  AD_MSB,AD_LSB;
u16 ConversionResult;

/* Private functions ---------------------------------------------------------*/

void main(void)
{
  
  //void bsp_InitI2C(void)
{
        I2C->CR1 = 0x00;  //禁用I2C模块 以初始化I2C模块
        I2C->CR2 = 0x04;  //应答使能
        I2C->FREQR = 10;  //输入时钟频率 10M
        I2C->OARH  = 0x40; //设置地址模式配置 为1
        I2C->OARL  = 0x00; //做为从机时的7位地址
        I2C->ITR  =  0x00;  //禁止所有的I2C中断
        I2C->CCRH = 0x80; //快速模式I2C  快速模式 tlow/thigh = 2;
        I2C->CCRL = 12;  //400Khz 时钟速率
        I2C->CR1 = 0x01;  //启用I2C模块
}
  
// void ADS1115_Init(void)
{
        
        unsigned char Temp;
        I2C->CR2 |= 0x01;  //产生始起信号
        while((I2C->SR1&0x01)==0); //等待始起信号已发送
        I2C->DR = ADS1115_ADDR;
        while((I2C->SR1&0x02)==0); //等待接收到从ADS1115返回的ACK
        Temp = I2C->SR1;
        Temp = I2C->SR3; //读SR3寄存器,以清除标志位ADDR

        
        while((I2C->SR1&0x80)==0); //等待数据寄存器空
        I2C->DR = ADS1115_POINT_CONFIG_REG;
        while((I2C->SR1&0x80)==0); //等待数据寄存器空
        I2C->DR = 0x52; //MSB
        while((I2C->SR1&0x80)==0); //等待数据寄存器空
        I2C->DR = 0x83; //LSB
        while((I2C->SR1&0x80)==0); //等待数据寄存器空
        I2C->CR2 |= 0x02;  //产生停止信号
        
}
        


  /* Infinite loop */
  while (1)
  {
                //u16 ADS1115_Read_Conversion(void)
{
        unsigned char Temp;
        
        
        /*********************************************
        
              将寄存器指向读取转换结果寄存器0x00
        
        **********************************************/
        while(I2C->SR3 & 0x02); //等待总线空闲
        I2C->CR2 |= 0x01;  //产生始起信号
        while((I2C->SR1&0x01)==0); //等待始起信号已发送
        I2C->DR = ADS1115_ADDR;
        while((I2C->SR1&0x02)==0); //等待接收到从ADS1115返回的ACK
        Temp = I2C->SR1;
        Temp = I2C->SR3; //读SR3寄存器,以清除标志位ADDR

        
        while((I2C->SR1&0x80)==0); //等待数据寄存器空
        I2C->DR = ADS1115_POINT_CONVERSION_REG;
        
        while((I2C->SR1&0x80)==0); //等待数据寄存器空
        I2C->CR2 |= 0x02;  //产生停止信号
        
        
        
        /*************************************************
        
           开始分别读取高8位和低8位
        
        **************************************************/
        
        
        //1.产生I2C始起信号
        while(I2C->SR3 & 0x02); //等待总线空闲
        I2C->CR2 |= 0x01;  //产生始起信号
        while((I2C->SR1&0x01)==0); //等待始起信号已发送

        //发送ADS1115器件地址+读操作
        I2C->DR = ADS1115_ADDR+0x01;
        while((I2C->SR1&0x02)==0); //等待接收到从ADS1115返回的ACK
        Temp = I2C->SR1; //读SR3寄存器,以清除标志位ADDR
        Temp = I2C->SR3; //读SR3寄存器,以清除标志位ADDR
        /*1115返回数据*/
        
        /*读高8位数据*/
        while((I2C->SR1&0x40)==0); //等待数据寄存器不为空BTF
        Temp = I2C->SR1; //读SR1寄存器,以清除标志位ADDR
        AD_MSB=0x00;
        AD_MSB=I2C->DR ;
        Temp = I2C->SR3; //读SR3寄存器,以清除标志位ADDR
        
        I2C->CR2 &= ~0x04;
        I2C->CR2 |= 0x02;
        
        /*读低8位数据*/
        while((I2C->SR1&0x40)==0); //等待数据寄存器不为空
        Temp = I2C->SR1;
        AD_LSB=0x00;
        AD_LSB=I2C->DR ;
        Temp = I2C->SR3; //读SR3寄存器,以清除标志位ADDR
        
        

        I2C->CR2 |= 0x04;
        I2C->CR2 &= ~0x08;
        
        /*计算转换结果*/
        ConversionResult = 0x0000;
        ConversionResult += AD_MSB;
        ConversionResult = ConversionResult<<8;
        ConversionResult += AD_LSB;
        
        
//        return ConversionResult;

}
  }
  
}

#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */
void assert_failed(u8* file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
  
沙发
shuishuo615|  楼主 | 2013-10-18 11:25 | 只看该作者
已解决,发现第一次接受第一个byte的时候发送的是NAK,而第二次发送的是ACK,在接受第一个数据的时候加入ACK使能就可以了
加入I2C->CR2 |= 0x04; 就OK了

使用特权

评论回复
板凳
shuishuo615|  楼主 | 2013-10-18 11:26 | 只看该作者
搞定

screenshot.jpg (59.86 KB )

screenshot.jpg

使用特权

评论回复
地板
moxue10| | 2014-7-19 20:32 | 只看该作者
楼主  可以把你ADS1115的接线图发给我们吗  我想知道AIN0~AIN3是怎么接线的   谢谢  

使用特权

评论回复
5
shuishuo615|  楼主 | 2014-11-20 15:29 | 只看该作者
moxue10 发表于 2014-7-19 20:32
楼主  可以把你ADS1115的接线图发给我们吗  我想知道AIN0~AIN3是怎么接线的   谢谢   ...

输入端的话要看你前一级是什么电路了,你的问题是啥

使用特权

评论回复
6
luoyelinyu| | 2015-9-10 15:36 | 只看该作者
  I2C->CCRH = 0x80; //快速模式I2C  快速模式 tlow/thigh = 2;
        I2C->CCRL = 12;  //400Khz 时钟速率

这里怎么算到400k的,tlow=2*CCR*tck;thigh=CCR*tck。tck=1/10M,CCR=12;反正我是算不到

使用特权

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

本版积分规则

8

主题

66

帖子

0

粉丝