ADS1115 器件是兼容 IIC 的 16 位高精度低功耗模數(shù)轉(zhuǎn)換器 (ADC),采用超小型無引線 X2QFN-10 封裝和 VSSOP-10 封裝。ADS111x 器件采用了低漂移電壓基準(zhǔn)和振蕩器。ADS1114 和 ADS1115 還采用可編程增益放大器(PGA)和數(shù)字比較器。這些特性加以較寬的工作電源電壓范圍使得 ADS1115 非常適合功率與空間受限的傳感器測(cè)量。
ADS111x 可在數(shù)據(jù)速率高達(dá)每秒 860 個(gè)樣本 (SPS) 的情況下執(zhí)行轉(zhuǎn)換。PGA 可提供從 ±256mV 到±6.144V 的輸入范圍,從而實(shí)現(xiàn)精準(zhǔn)的大小信號(hào)測(cè)量。ADS1115 具有 一個(gè)輸入多路復(fù)用器 (MUX),可實(shí)現(xiàn)兩次差動(dòng)輸入測(cè)量或四次單端輸入測(cè)量。在ADS1115 中可使用數(shù)字比較器進(jìn)行欠壓和過壓檢測(cè)。ADS1115既可在連續(xù)轉(zhuǎn)換模式下工作,也可在單沖模式下工作。在單沖模式下,這些器件可在一次轉(zhuǎn)換后自動(dòng)斷電;因此顯著降低了空閑期間的功耗。
01模塊來源
	模塊實(shí)物展示:
	
	
	
	
02 規(guī)格參數(shù)
工作電壓:2.0-5.5V
工作電流:150uA
采集精度:16位
采集通道:4通道
控制方式:IIC
以上信息見廠家資料文件
03移植過程
我們的目標(biāo)是將例程移植至CW32F030C8T6開發(fā)板上【實(shí)現(xiàn)4路ADC采集電壓功能】。首先要獲取資料,查看數(shù)據(jù)手冊(cè)應(yīng)如何實(shí)現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。
3.1查看資料
ADS1115是采用的IIC通信,所以首先要了解IIC的地址與時(shí)序,再確定根據(jù)寄存器的設(shè)置。
器件地址
器件地址的設(shè)置見下表:
	
說明:當(dāng)模塊上的ADDR引腳接入GND時(shí),其器件地址為1001000,最后一位數(shù)據(jù)是讀寫位。
	
時(shí)序
下圖是讀時(shí)序,步驟是:
IIC起始信號(hào) -> 發(fā)送器件地址+0(寫) -> 等待模塊應(yīng)答 -> 應(yīng)答后發(fā)送寄存器地址 -> 等待模塊應(yīng)答 -> 重新發(fā)送起始信號(hào) -> 發(fā)送器件地址+1(讀) -> 等待模塊應(yīng)答 -> 應(yīng)答后讀取高8位數(shù)據(jù) -> 讀取完畢主機(jī)發(fā)送應(yīng)答信號(hào) -> 讀取低8位數(shù)據(jù) -> 讀取完畢主機(jī)發(fā)送應(yīng)答信號(hào) -> 發(fā)送IIC停止信號(hào)
	
下圖是寫時(shí)序,步驟是:
IIC起始信號(hào) -> 發(fā)送器件地址+0(寫) -> 等待模塊應(yīng)答 -> 應(yīng)答后發(fā)送寄存器地址 -> 等待模塊應(yīng)答 -> 應(yīng)答后寫入高8位數(shù)據(jù) -> 等待模塊應(yīng)答 -> 寫入低8位數(shù)據(jù) -> 等待模塊應(yīng)答 -> 發(fā)送IIC停止信號(hào)
寄存器說明
ADS1115有四個(gè)寄存器,可通過IIC接口使用地址指針進(jìn)入。
地址0X00為轉(zhuǎn)換寄存器,它包含最后一次轉(zhuǎn)換的結(jié)果。
地址0X01為配置寄存器,用于更改ADS1115的工作模式和查詢?cè)O(shè)備狀態(tài)。
另外兩個(gè)寄存器,Lo_thresh和Hi_thresh,設(shè)置用于比較器函數(shù)的閾值,我們用不到。
	
配置寄存器有16位,用于控制工作模式、輸入選擇、數(shù)據(jù)速率、滿量程范圍和比較器模式。
	
第15位:OS,讀操作時(shí)可以知道當(dāng)前設(shè)備的工作狀態(tài);寫操作時(shí)可以設(shè)置單次轉(zhuǎn)換。本文配置為1(必須為斷電模式下,當(dāng)對(duì)OS寫1時(shí),設(shè)備會(huì)進(jìn)入上電模式并完成一次數(shù)據(jù)轉(zhuǎn)換,然后會(huì)自動(dòng)將OS置0)
第14-12位:MUX為輸入多路復(fù)用器,對(duì)輸入模式進(jìn)行選擇,如下圖有八種輸入模式,分別是四種差分與四種單端輸入,本文配置為A0單端輸入(0x04)。(單端輸入就是測(cè)量的數(shù)據(jù)有兩個(gè)引腳,一個(gè)輸出一個(gè)地。將測(cè)量的輸出接入A0引腳,測(cè)量的地與ADS1115共地)
	
第11-9位:PGA為可編程增益放大器,設(shè)置FSR(滿刻度的范圍),本文配置為±4.096V(0x01)后面電壓計(jì)算公式與這個(gè)有關(guān)。
	
第8位:MODE選擇持續(xù)轉(zhuǎn)換模式與單次轉(zhuǎn)換模式(單次轉(zhuǎn)換模式需要OS位觸發(fā)),本文配置為連續(xù)轉(zhuǎn)換模式(0x00)
	
第7-5位:DR配置data rate數(shù)據(jù)傳輸速率,本文配置為128SPS(0x04)
	
第4-2位:對(duì)比較器的配置,我們不使用,默認(rèn)為0即可(0x00) 第1-0位:本位配置為關(guān)閉比較器并將ALERT/RDY引腳設(shè)置為高阻抗模式(0x03)
	
最終得到的配置結(jié)果為1100_0010_1000_0011(0xC283)。
當(dāng)前配置的是A0的引腳,我們后續(xù)獲取數(shù)據(jù)也是從A0引腳讀取。
16位轉(zhuǎn)換寄存器以二進(jìn)制的補(bǔ)碼格式保存最后一次轉(zhuǎn)換的結(jié)果。需要注意的是,在上電之后,轉(zhuǎn)換寄存器被清除為0,并保持為0,直到第一次轉(zhuǎn)換完成。
	
實(shí)現(xiàn)代碼說明
讀取到的ADC值如何換算為電壓?
以PGA設(shè)置為4.96V為例。
電壓 = 采集到的ADC值 * 分辨率
分辨率 = 測(cè)量電壓范圍 / (2^AD位數(shù)-1) = 4.096 / 2的15次方 = 0.000125V
分辨率也可以在數(shù)據(jù)手冊(cè)中查看,見右圖。其中125uV = 0.125mV = 0.000125V。
	
/******************************************************************
 * 函 數(shù) 名 稱:WriteADS1115
 * 函 數(shù) 說 明:向ADS1115的add地址寫入dat數(shù)據(jù)
 * 函 數(shù) 形 參: add寫入寄存器地址
 *             dat_H寫入的高8位數(shù)據(jù)
 *             dat_L寫入的低8位數(shù)據(jù)
 * 函 數(shù) 返 回:0寫入成功
 *             1寫入器件地址無應(yīng)答
 *             2寫入寄存器地址無應(yīng)答
 * 作       者:LC
 * 備       注:器件地址=0X90
******************************************************************/
uint8_t WriteADS1115(uint8_t add, uint8_t dat_H, uint8_t dat_L)
{
    IIC_Start();//起始信號(hào)
    IIC_Write(0x90);//器件地址
    if( IIC_Wait_Ack() == 1 )
        return 1;
    IIC_Write(add);//寄存器地址
    if( IIC_Wait_Ack() == 1 )
        return 2;
    IIC_Write(dat_H);//寫入高8位
    IIC_Wait_Ack();//等待應(yīng)答
    IIC_Write(dat_L);//寫入低8位
    IIC_Wait_Ack();//等待應(yīng)答
    IIC_Stop();//停止信號(hào)
    return (0);
}
/******************************************************************
 * 函 數(shù) 名 稱:ReadADS1115
 * 函 數(shù) 說 明:讀取ADS1115的數(shù)據(jù)
 * 函 數(shù) 形 參:add讀取的寄存器地址
 * 函 數(shù) 返 回:-1-讀取失敗  其他-讀取成功
 * 作       者:LC
 * 備       注:無
******************************************************************/
float ReadADS1115(unsigned char add)
{
    int i =0;
    unsigned char dat[2]={0};
    unsigned int num = 0;
    float ret=0;
    IIC_Start();//起始信號(hào)
    IIC_Write(0x90);//器件地址+寫
    if( IIC_Wait_Ack() == 1 )
        return -1;
    IIC_Write(add);//寄存器地址
    if( IIC_Wait_Ack() == 1 )
        return -1;
    do{
      //超時(shí)判斷
      i++;
      if( i > 20 ) return -1;
      delay_1ms(1);
      IIC_Start();//重新發(fā)送起始信號(hào)
      IIC_Write(0x91);//器件地址+讀
    }while(IIC_Wait_Ack() == 1);
    dat[0]=IIC_Read();//讀高8位數(shù)據(jù)
    IIC_Send_Ack(0);//應(yīng)答
    dat[1]=IIC_Read();//讀低8位數(shù)據(jù)
    IIC_Send_Ack(1);//非應(yīng)答
    IIC_Stop();//發(fā)送停止信號(hào)
    //數(shù)據(jù)整合
    num =  ((dat[0]<8) | (dat[1]));
    //分辨率計(jì)算:測(cè)量電壓范圍/(2^AD位數(shù)-1)
    //    分辨率= 4.096/2^15=0.000125
    //      電壓= 采集到的ADC值 * 分辨率
    if(num?>32768)
        ret=(65535-num)*0.000125;
    else
        ret=num*0.000125;
    return ret;
}
3.2引腳選擇
	
接線表
3.3移植至工程
工程模板參考入門手冊(cè)的工程模板
移植步驟中的導(dǎo)入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,只是將.c和.h文件更改為bsp_ads1115.c與bsp_ads1115.h。這里不再過多講述,移植完成后面修改相關(guān)代碼。
在文件bsp_ads1115.c中,編寫如下代碼。
/* * Change Logs: * Date Author Notes * 2024-06-20 LCKFB-LP first version */ #include "bsp_ads1115.h" #include "stdio.h" /****************************************************************** * 函 數(shù) 名 稱:ADS1115_GPIO_Init * 函 數(shù) 說 明:對(duì)IIC引腳初始化 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:1100_0010_1000_0011 WriteADS1115(0x01,0xc2,0x83); ******************************************************************/ void ADS1115_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化結(jié)構(gòu)體 RCC_ADS1115_ENABLE(); // 使能GPIO時(shí)鐘 GPIO_InitStruct.Pins = GPIO_SCL|GPIO_SDA; // GPIO引腳 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 開漏輸出 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 輸出速度高 GPIO_Init(PORT_ADS1115, &GPIO_InitStruct); // 初始化 //寫入配置參數(shù) WriteADS1115(0x01,0xC2,0x83); } /****************************************************************** * 函 數(shù) 名 稱:IIC_Start * 函 數(shù) 說 明:IIC起始信號(hào) * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void IIC_Start(void) { SDA_OUT(); SDA(1); delay_us(5); SCL(1); delay_us(5); SDA(0); delay_us(5); SCL(0); delay_us(5); } /****************************************************************** * 函 數(shù) 名 稱:IIC_Stop * 函 數(shù) 說 明:IIC停止信號(hào) * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void IIC_Stop(void) { SDA_OUT(); SCL(0); SDA(0); SCL(1); delay_us(5); SDA(1); delay_us(5); } /****************************************************************** * 函 數(shù) 名 稱:IIC_Send_Ack * 函 數(shù) 說 明:主機(jī)發(fā)送應(yīng)答 * 函 數(shù) 形 參:0應(yīng)答 1非應(yīng)答 * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void IIC_Send_Ack(unsigned char ack) { SDA_OUT(); SCL(0); SDA(0); delay_us(5); if(!ack) SDA(0); else SDA(1); SCL(1); delay_us(5); SCL(0); SDA(1); } /****************************************************************** * 函 數(shù) 名 稱:IIC_Wait_Ack * 函 數(shù) 說 明:等待從機(jī)應(yīng)答 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:1=無應(yīng)答 0=有應(yīng)答 * 作 者:LC * 備 注:無 ******************************************************************/ unsigned char IIC_Wait_Ack(void) { char ack = 0; unsigned char ack_flag = 10; SDA_IN(); SDA(1); delay_us(5); SCL(1); delay_us(5); while( (GETSDA()==1) && ( ack_flag ) ) { ack_flag--; delay_us(5); } if( ack_flag <= 0 ) { IIC_Stop(); return 1; } else { SCL(0); SDA_OUT(); } return ack; } /****************************************************************** * 函 數(shù) 名 稱:IIC_Write * 函 數(shù) 說 明:IIC寫一個(gè)字節(jié) * 函 數(shù) 形 參:dat寫入的數(shù)據(jù) * 函 數(shù) 返 回:無 * 作 者:LC * 備 注:無 ******************************************************************/ void IIC_Write(unsigned char dat) { int i = 0; SDA_OUT(); SCL(0);//拉低時(shí)鐘開始數(shù)據(jù)傳輸 for( i = 0; i < 8; i++ ) { SDA( (dat & 0x80) >> 7 ); delay_us(2); dat<=1; delay_us(6); SCL(1); delay_us(4); SCL(0); delay_us(4); } } /****************************************************************** * 函 數(shù) 名 稱:IIC_Read * 函 數(shù) 說 明:IIC讀1個(gè)字節(jié) * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:讀出的1個(gè)字節(jié)數(shù)據(jù) * 作 者:LC * 備 注:無 ******************************************************************/ unsigned char IIC_Read(void) { unsigned char i,receive=0; SDA_IN();//SDA設(shè)置為輸入 for(i=0;i8;i++ ) { SCL(0); delay_us(5); SCL(1); delay_us(5); receive<=1; if( GETSDA() ) { receive|=1; } delay_us(5); } return receive; } /****************************************************************** * 函 數(shù) 名 稱:WriteADS1115 * 函 數(shù) 說 明:向ADS1115的add地址寫入dat數(shù)據(jù) * 函 數(shù) 形 參:add寫入寄存器地址 dat_H寫入的高8位數(shù)據(jù) dat_L寫入的低8位數(shù)據(jù) * 函 數(shù) 返 回:0寫入成功 1寫入器件地址無應(yīng)答 2寫入寄存器地址無應(yīng)答 * 3寫入高8位數(shù)據(jù)無應(yīng)答 4寫入低8位數(shù)據(jù)無應(yīng)答 * 作 者:LC * 備 注:器件地址=0X90 ******************************************************************/ uint8_t WriteADS1115(uint8_t add,uint8_t dat_H,uint8_t dat_L) { IIC_Start(); IIC_Write(0x90); if( IIC_Wait_Ack() == 1 ) { printf("error 1rn"); return 1; } IIC_Write(add); if( IIC_Wait_Ack() == 1 ) { printf("error 2rn"); return 2; } IIC_Write(dat_H); IIC_Wait_Ack(); IIC_Write(dat_L); IIC_Wait_Ack(); IIC_Stop(); return (0); } /****************************************************************** * 函 數(shù) 名 稱:ReadADS1115 * 函 數(shù) 說 明:讀取ADS1115的數(shù)據(jù) * 函 數(shù) 形 參:add讀取的寄存器地址 * 函 數(shù) 返 回:-1-讀取失敗 其他-讀取成功 * 作 者:LC * 備 注:無 ******************************************************************/ float ReadADS1115(unsigned char add) { int i =0; unsigned char dat[2]={0}; unsigned int num = 0; float ret=0; IIC_Start();//起始信號(hào) IIC_Write(0x90);//器件地址+寫 if( IIC_Wait_Ack() == 1 ) return -1; IIC_Write(add);//寄存器地址 if( IIC_Wait_Ack() == 1 ) return -1; do{ //超時(shí)判斷 i++; if( i > 20 ) return -1; delay_ms(1); IIC_Start();//重新發(fā)送起始信號(hào) IIC_Write(0x91);//器件地址+讀 }while(IIC_Wait_Ack() == 1); dat[0]=IIC_Read();//讀高8位數(shù)據(jù) IIC_Send_Ack(0);//應(yīng)答 dat[1]=IIC_Read();//讀低8位數(shù)據(jù) IIC_Send_Ack(1);//非應(yīng)答 IIC_Stop();//發(fā)送停止信號(hào) //數(shù)據(jù)整合 num = ((dat[0]<8) | (dat[1])); //數(shù)值計(jì)算取決于PGA配置 //2的15次方=32768 //設(shè)置的最大量程4.096 // if(num?>32768) // ret=((float)(65535-num)/32768.0)*4.096; // else // ret=((float)num/32768.0)*4.096; //分辨率計(jì)算:測(cè)量電壓范圍/(2^AD位數(shù)-1) // 分辨率= 4.096/2^15=0.000125 // 電壓= 采集到的ADC值 * 分辨率 if(num>32768) ret=(65535-num)*0.000125; else ret=num*0.000125; return ret; }
在文件bsp_ads1115.h中,編寫如下代碼。
/*
 * Change Logs:
 * Date           Author       Notes
 * 2024-06-20     LCKFB-LP    first version
 */
#ifndef _BSP_ADS1115_H_
#define _BSP_ADS1115_H_
#include "board.h"
#define RCC_ADS1115_ENABLE()      __RCC_GPIOB_CLK_ENABLE()
#define PORT_ADS1115              CW_GPIOB
#define GPIO_SCL                  GPIO_PIN_8
#define GPIO_SDA                  GPIO_PIN_9
//SDA輸入模式
#define SDA_IN()   {                                                     
                        GPIO_InitTypeDef GPIO_InitStruct;                
                        GPIO_InitStruct.Pins = GPIO_SDA;                 
                        GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP;   
                        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;         
                        GPIO_Init(PORT_ADS1115, &GPIO_InitStruct);       
                   }
//SDA輸出模式
#define SDA_OUT()  {                                                                                                         
                        GPIO_InitTypeDef GPIO_InitStruct;                
                        GPIO_InitStruct.Pins = GPIO_SDA;                 
                        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;      
                        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;         
                        GPIO_Init(PORT_ADS1115, &GPIO_InitStruct);       
                    }
#define SCL(BIT)  GPIO_WritePin( PORT_ADS1115, GPIO_SCL, BIT?GPIO_Pin_SET:GPIO_Pin_RESET )
#define SDA(BIT)  GPIO_WritePin( PORT_ADS1115, GPIO_SDA, BIT?GPIO_Pin_SET:GPIO_Pin_RESET )
#define GETSDA()  GPIO_ReadPin( PORT_ADS1115, GPIO_SDA )
void ADS1115_GPIO_Init(void);
unsigned char WriteADS1115(unsigned char add,unsigned char dat_H,unsigned char dat_L);
float ReadADS1115(unsigned char add);
#endif
04移植驗(yàn)證
在自己工程中的main主函數(shù)中,編寫如下。
/* * Change Logs: * Date Author Notes * 2024-06-20 LCKFB-LP first version */ #include "board.h" #include "stdio.h" #include "bsp_uart.h" #include "bsp_ads1115.h" int32_t main(void) { board_init(); // 開發(fā)板初始化 uart1_init(115200); // 串口1波特率115200 ADS1115_GPIO_Init(); printf("demo startrn"); while(1) { //當(dāng)前設(shè)置最大量程為4.096V printf("A0 = %.4frn", ReadADS1115(0x00) );//讀取A0的值 delay_ms(1000); } }
移植現(xiàn)象:將A0接入GND、3.3V和5V。
	
模塊移植成功案例代碼:
鏈接:https://pan.baidu.com/s/1A6SRdtHRT5N7uUNE6Y08YQ?pwd=LCKF
	提取碼:LCKF
	審核編輯 黃宇
- 
                                傳感器
                                +關(guān)注
關(guān)注
2573文章
54039瀏覽量
782885 - 
                                ads1115
                                +關(guān)注
關(guān)注
0文章
17瀏覽量
13274 - 
                                多模數(shù)轉(zhuǎn)換器
                                +關(guān)注
關(guān)注
0文章
4瀏覽量
1591 - 
                                CW32
                                +關(guān)注
關(guān)注
1文章
278瀏覽量
1625 
發(fā)布評(píng)論請(qǐng)先 登錄
求助,關(guān)于模數(shù)轉(zhuǎn)換器ADS1115連續(xù)轉(zhuǎn)換的問題求解
使用ADS1115模數(shù)轉(zhuǎn)換器時(shí),它的PGA的增益是如何設(shè)置的?
ADS1115模數(shù)轉(zhuǎn)換用作單端信號(hào)轉(zhuǎn)換時(shí),vin-端連接數(shù)字地還是模擬地?
ADS1115是什么意思呢
TI公司IIC接口16位AD模塊ADS1115
ADS1115用戶手冊(cè)
ads1115電壓測(cè)量范圍
基于51的ads1115詳細(xì)程序介紹
ads1115應(yīng)用電路圖
ads1115使用方法
模數(shù)轉(zhuǎn)換器16位ADC芯片ADS1115
用于多路信號(hào)采集的國產(chǎn)模數(shù)轉(zhuǎn)換器,軟硬件兼容ADS1220
    
基于CW32模塊的ADS1115多路模數(shù)轉(zhuǎn)換器設(shè)計(jì)
    
          
        
        
CW32模塊使用 ADS1115多路模數(shù)轉(zhuǎn)換器
                
 
    
    
           
            
            
                
            
評(píng)論