模数转换芯片ADS1115/1015的使用教程(IIC)

ADS1115是一块模数转换芯片(ADC),能够测量单端对地电压(4路)和差分对输入的电压(2路),测量范围是0-6V。

1、main.c:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "key.h"  
#include "ads1115.h"
 
float aa;    
 
 int main(void)
 { 
     float t1; 
   u16 t,result;
     u8 key;
     u16 i=0;
 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
    delay_init();             
    uart_init(9600);         //串口初始化为9600
    LED_Init();                  
     //LCD_Init();    
    KEY_Init();                 
        //IIC初始化 
    ADS1115_Init();
  
    while(1)
    {
        key=KEY_Scan(0);
        if(key==WKUP_PRES)
        {                
          result=lvbo(0xeb,0x82);    //A0 A1为差分输入测试端  低八位 高八位1111 1011,1000 0010
            
            if(result >= 0x8000 && result <= 0xffff)
                result = 0xffff - result;   //差值为负取绝对值,使得A0 A1正反接都行
             else if(result >= 0xffff)
                result = 0;
            
          t1=4.096*2*result/65535;     //转换成电压
    
            printf("量程为4.096V,A0-A1之间电压 = %f Vrn",t1);//打印
            
                if(result == 0x7fff || result == 0x8000)
            {
                printf("已超量程!rnrn");
            }
            else
            {
                printf("读取正常!rnrn");
            }    
        }
        
        if(key==KEY0_PRES)
        {                 
          result=lvbo(0xe3,0xb2); //A2 A3为差分输入测试端  低八位 高八位 1111 0011,1011 0010
            
            
            if(result >= 0x8000)
                result = 0xffff - result; //差值为负取绝对值,使得A2 A3正反接都行
            
            
          t1=4.096*2*result/65535;     //转换成电压
            
            printf("量程为4.096V,A2-A3之间电压 = %f Vrn",t1); //打印
            
                if(result == 0x7fff || result == 0x8000) //超过最大值或者低于最小值
            {
                printf("已超量程!rnrn");
            }
            else
            {
                printf("读取正常!rnrn");
            }    
        }    
        
        if(key == KEY1_PRES)
        {
                  result=lvbo(0xe3,0xb4);    //A2 A3为差分输入测试端 低八位 高八位 1111 0011,1011 0100
            
            if((result >= 0x8000) && (result <= 0xffff))
                result = 0xffff - result;   //差值为负取绝对值,使得A0 A1正反接都行
             else if(result >= 0xffff)
                result = 0;
          t1=2.048*2*result/65535;     //转换成电压
            
            printf("量程为2.048V,A0-A1之间电压 = %f Vrn",t1);//打印
            if(result == 0x7fff || result == 0x8000)
            {
                printf("已超量程!rnrn");
            }
            else
            {
                printf("读取正常!rnrn");
            }
        }
        
        i  ;
        delay_ms(10);
        if(i==20)
        {
            LED0=!LED0;//提示系统正在运行    
            i=0;
            }           
    }
}

2、ADS1115.c

#include "sys.h"
#include "stm32f10x_i2c.h"
#include "ads1115.h"
 
static void ADS1115_delay(u16 D)
{
    while(--D);
}
 
void delay_nms(u16 ms)
{
    u16 i;
    u32 M = 0;//720W
    for(i = 0;i < ms; i  )
    for(M=12000;M > 0;M--);
}
 
void delay_nus(u16 us)
{
    u16 i;
    u16 M = 0;//720W
    for(i = 0;i < us; i  )
    for(M=72;M > 0;M--);
}
 
 
 
/PA8 SDAPA9 SCL///
void ADS1115_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC ,ENABLE);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;//A SCL SDA
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
 
    SDA_A1;
    SCL_A1;
    delay_nms(5);
 
}
 
//I2C总线启动
void I2CStart_A(void)
{
   SDA_A1;
   ADS1115_delay(5);
   SCL_A1;
   ADS1115_delay(5);
   SDA_A0;
   ADS1115_delay(5);//MIN 160ns
   SCL_A0;
   ADS1115_delay(5);
}
 
//I2C停止总线
void I2CStop_A(void)
{
   SDA_A0;
   ADS1115_delay(5);
   SCL_A1;
   ADS1115_delay(5);
   SDA_A1;
   ADS1115_delay(5);//MIN 160ns
}
 
//I2C 写一字节
void I2CWriteByte_A(u8 DATA)
{
      u8 i;
      SCL_A0;
      for(i = 0;i < 8; i  )
      {
         if(DATA&0x80)
         {
              SDA_A1;
         }
         else
         {
              SDA_A0;
         }
         SCL_A1;//按照手册不需延时
         ADS1115_delay(5);
         SCL_A0;
         ADS1115_delay(5);
         DATA    = DATA << 1;  
      }
      SDA_A1;
      SCL_A1;
      ADS1115_delay(5);
      SCL_A0;
}
 
 
//I2C 读一字节
u8 I2CReadByte_A(void)
{
    u8 TData=0,i;
    for(i=0;i<8;i  )
    {
        SCL_A1;
        ADS1115_delay(5);
        TData=TData<<1;
        if(SDA_AI)
        {
            TData|=0x01;
        }
        SCL_A0;
        ADS1115_delay(5);
    }
    SCL_A0;
    ADS1115_delay(5);
    SDA_A0;
    ADS1115_delay(5);
    SCL_A1;
    ADS1115_delay(5);
    SCL_A0;
    ADS1115_delay(5);
    SDA_A1;
    return TData;
}
 
 
 
/*********************************************************************
*函数名称:  ADS1115Config
*描       述: 设置ADS1115包括通道配置,采样时间等等
*参       数: HCMD :命令字高8位(通道,量程,转换模式)
            LCMD : 命令字低8位(采样率设置 比较模式 有效电平 信号输出锁存)
*返       回; 无
********************************************************************/
void ADS1115Config_A(u8 LCMD,u8 HCMD)
{
    u8 i=0;
    u8 Initdata[4];
 
    Initdata[0] = 0x90;  // 地址0x90  器件ADR接地 写寄存器
    Initdata[1] = 0x01;// 配置寄存器
    Initdata[2] = HCMD;    // 配置字高字节
    Initdata[3] = LCMD;    // 配置字低字节
    SCL_A1;
    I2CStart_A();        //开启
    for(i=0;i<4;i  )
    {
        I2CWriteByte_A(Initdata[i]);
        ADS1115_delay(10);
    }
    I2CStop_A();         //关闭
}
 
void SetThresHold_A(u16 L_TH,u16 H_TH)        //高低阀门设置
{
   SCL_A1;
   I2CStart_A();      // 开启
   I2CWriteByte_A(0x90);
   I2CWriteByte_A(0x02);//最低阀值寄存器
   I2CWriteByte_A((L_TH>>8));
   I2CWriteByte_A(L_TH);
   I2CStop_A();       //关闭
 
   I2CStart_A();     //开启
   I2CWriteByte_A(0x90);
   I2CWriteByte_A(0x03);//最高阀值寄存器
   I2CWriteByte_A((H_TH>>8));
   I2CWriteByte_A(H_TH);
   I2CStop_A();      //关闭
}
 
 
/*******************************************************************
*函数名称:  ReadAD_A
*描       述: 获取AD转换的值
*参       数: 获取的值为在前面设置的那个通道
*返       回; 无
********************************************************************/
u16 ReadAD_A(void)
{
   u16 Data[2]={0,0};
//转换指向寄存器
   SCL_A1;
   I2CStart_A();
   I2CWriteByte_A(0x90);
   I2CWriteByte_A(0x00);
   I2CStop_A();                        
   
   I2CStart_A();
   I2CWriteByte_A(0x91);
   Data[0] = I2CReadByte_A();
   Data[1] = I2CReadByte_A();
   I2CStop_A();
   
   Data[0] = Data[0]<<8 | Data[1];
   return  (Data[0]);//&0x7fff
}
 
u16 getad(u8 LCMD,u8 HCMD)
{
   u16 value=0;
    ADS1115Config_A(LCMD,HCMD);          //配置通道
        
    delay_nms(5); // 延时一定时间,防止通道切换互相影响        
    value=ReadAD_A();
    return value;
}
 
u16 lvbo(u8 LCMD,u8 HCMD)        //求30个值的平均值
{
    u8 k;
    u32 U=0, temp;   //u32 给够叠加空间 或者float、double亦可 
    for(k=0;k<30;k  )
    {
        U =getad(LCMD,HCMD);    
    }
    temp=U;
        U=0;
    return ((float)temp/30);    //带上小数点
}

ADS1115.h

#ifndef  __ADS115_H_
#define  __ADS115_H_
#include "sys.h"
 
 
/***************************************************************************************
*说明:当端输入时候正输入为输入信号,负输入为地但是输入信号不能为负电压(不能比地电位低)
*       双端输入时候正输入为输入信号,负输入为负输入输入信号的差值可以为负电压
****************************************************************************************/
#define     SDA_A1     PCout(11)=1   //SDA输出
#define     SDA_A0     PCout(11)=0
#define     SCL_A1        PCout(12)=1    //SCL
#define     SCL_A0        PCout(12)=0
#define     SDA_AI        PCin(11)   //SDA读入
 
//#define     SDA_A21     PAout(10)=1   //SDA输出
//#define     SDA_A20     PAout(10)=0
//#define     SCL_A21       PAout(11)=1    //SCL
//#define     SCL_A20       PAout(11)=0
//#define     SDA_A2I       PAin(10)   //SDA读入
 
//#define     SDA_A31     PBout(10)=1   //SDA输出
//#define     SDA_A30     PBout(10)=0
//#define     SCL_A31       PBout(11)=1    //SCL
//#define     SCL_A30       PBout(11)=0
//#define     SDA_A3I       PBin(10)   //SDA读入
 
//#define     SDA_A41     PBout(12)=1   //SDA输出
//#define     SDA_A40     PBout(12)=0
//#define     SCL_A41       PBout(13)=1    //SCL
//#define     SCL_A40       PBout(13)=0
//#define     SDA_A4I       PBin(12)   //SDA读入
 
//I2C地址以及读写设置
#define  WR_REG 0x90       //写寄存器
#define  RE_REG 0x91       //读寄存器
 
/***********************************寄存器控制字**********************************************/
#define  DATA_REG  0x00        //转换数据寄存器
#define  CONF_REG  0x01     //控制字设置寄存器
#define  LOTH_REG  0x02        //最低阀值寄存器
#define  HITH_REG  0x03        //最高阀值寄存器
 
#define  ch0  0xc0       //通道0
#define  ch1  0xd0       //通道1
#define  ch2  0xe0       //通道2
#define  ch3  0xf0       //通道3
 
/***********************控制字申明*************************************************************
*|  OS | MUX2 | MUX1 | MUX0 | PGA2 | PGA1 | PGA0 | MODE  |------HCMD
*|  DR2| DR1  | DR0  | COMP_MODE | COMP_POL | COMP_LAT |  COMP_QUE1 | COMP_QUE0 |-----LCMD
***********************************************************************************************/
#define  HCMD1    0x64   //AIN0单端输入  -4.096量程  连续模式  01000100b
#define  LCMD1      0xf0     //860sps 窗口比较器模式 输出低有效  不锁存信号至读 每周期检测阀值 11110000b
 
/************************函数申明****************************/
static void ADS1115_delay(u16 D);
void delay_nms(u16 ms);
void delay_nus(u16 us);
void ADS1115_Init(void);
void I2CStart_A(void);
void I2CStop_A(void);
void I2CWriteByte_A(u8 DATA);
u8 I2CReadByte_A(void);
void ADS1115Config_A(u8 LCMD,u8 HCMD);
void SetThresHold_A(u16 L_TH,u16 H_TH);        //高低阀门设置
u16 ReadAD_A(void);
u16 getad(u8 LCMD,u8 HCMD);
u16 lvbo(u8 LCMD,u8 HCMD);
 
 
#endif

判断量程高低由数据手册寄存器决定。

程序实现:

if(result == 0x7fff || result == 0x8000)
            {
                printf("已超量程!rnrn");
            }
            else
            {
                printf("读取正常!rnrn");
            }

实际电路接法:

发表评论