加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

【CW32模塊使用】ADS1115多路模數(shù)轉(zhuǎn)換器

09/17 09:55
1295
閱讀需 31 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

ADS1115 器件是兼容 IIC 的 16 位高精度低功耗模數(shù)轉(zhuǎn)換器 (ADC),采用超小型無引線 X2QFN-10 封裝和 VSSOP-10 封裝。ADS111x 器件采用了低漂移電壓基準和振蕩器。ADS1114 和 ADS1115 還采用可編程增益放大器(PGA)和數(shù)字比較器。這些特性加以較寬的工作電源電壓范圍使得 ADS1115 非常適合功率與空間受限的傳感器測量。

ADS111x 可在數(shù)據(jù)速率高達每秒 860 個樣本 (SPS) 的情況下執(zhí)行轉(zhuǎn)換。PGA 可提供從 ±256mV 到±6.144V 的輸入范圍,從而實現(xiàn)精準的大小信號測量。ADS1115 具有 一個輸入多路復(fù)用器 (MUX),可實現(xiàn)兩次差動輸入測量或四次單端輸入測量。在ADS1115 中可使用數(shù)字比較器進行欠壓和過壓檢測。ADS1115既可在連續(xù)轉(zhuǎn)換模式下工作,也可在單沖模式下工作。在單沖模式下,這些器件可在一次轉(zhuǎn)換后自動斷電;因此顯著降低了空閑期間的功耗。

02?規(guī)格參數(shù)

工作電壓:2.0-5.5V

工作電流:150uA

采集精度:16位

采集通道:4通道

控制方式:IIC

管腳數(shù)量:10 Pin(2.54mm間距排針

以上信息見廠家資料文件

03移植過程

我們的目標是將例程移植至CW32F030C8T6開發(fā)板上【實現(xiàn)4路ADC采集電壓功能】。首先要獲取資料,查看數(shù)據(jù)手冊應(yīng)如何實現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。

3.1查看資料

ADS1115是采用的IIC通信,所以首先要了解IIC的地址與時序,再確定根據(jù)寄存器的設(shè)置。

器件地址

器件地址的設(shè)置見下表:

說明:當模塊上的ADDR引腳接入GND時,其器件地址為1001000,最后一位數(shù)據(jù)是讀寫位。

時序

下圖是讀時序,步驟是:

IIC起始信號?->?發(fā)送器件地址+0(寫)?->?等待模塊應(yīng)答?->?應(yīng)答后發(fā)送寄存器地址?->?等待模塊應(yīng)答?->?重新發(fā)送起始信號?->?發(fā)送器件地址+1(讀)?->?等待模塊應(yīng)答?->?應(yīng)答后讀取高8位數(shù)據(jù)?->?讀取完畢主機發(fā)送應(yīng)答信號?->?讀取低8位數(shù)據(jù)?->?讀取完畢主機發(fā)送應(yīng)答信號?->?發(fā)送IIC停止信號

下圖是寫時序,步驟是:

IIC起始信號?->?發(fā)送器件地址+0(寫)?->?等待模塊應(yīng)答?->?應(yīng)答后發(fā)送寄存器地址?->?等待模塊應(yīng)答?->?應(yīng)答后寫入高8位數(shù)據(jù)?->?等待模塊應(yīng)答?->?寫入低8位數(shù)據(jù)?->?等待模塊應(yīng)答?->?發(fā)送IIC停止信號

寄存器說明

ADS1115有四個寄存器,可通過IIC接口使用地址指針進入。

地址0X00為轉(zhuǎn)換寄存器,它包含最后一次轉(zhuǎn)換的結(jié)果。

地址0X01為配置寄存器,用于更改ADS1115的工作模式和查詢設(shè)備狀態(tài)。

另外兩個寄存器,Lo_thresh和Hi_thresh,設(shè)置用于比較器函數(shù)的閾值,我們用不到。

配置寄存器有16位,用于控制工作模式、輸入選擇、數(shù)據(jù)速率、滿量程范圍和比較器模式。

第15位:OS,讀操作時可以知道當前設(shè)備的工作狀態(tài);寫操作時可以設(shè)置單次轉(zhuǎn)換。本文配置為1(必須為斷電模式下,當對OS寫1時,設(shè)備會進入上電模式并完成一次數(shù)據(jù)轉(zhuǎn)換,然后會自動將OS置0)

第14-12位:MUX為輸入多路復(fù)用器,對輸入模式進行選擇,如下圖有八種輸入模式,分別是四種差分與四種單端輸入,本文配置為A0單端輸入(0x04)。(單端輸入就是測量的數(shù)據(jù)有兩個引腳,一個輸出一個地。將測量的輸出接入A0引腳,測量的地與ADS1115共地)

第11-9位:PGA為可編程增益放大器,設(shè)置FSR(滿刻度的范圍),本文配置為±4.096V(0x01)后面電壓計算公式與這個有關(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位:對比較器的配置,我們不使用,默認為0即可(0x00) 第1-0位:本位配置為關(guān)閉比較器并將ALERT/RDY引腳設(shè)置為高阻抗模式(0x03)

最終得到的配置結(jié)果為1100_0010_1000_0011(0xC283)。

當前配置的是A0的引腳,我們后續(xù)獲取數(shù)據(jù)也是從A0引腳讀取。

16位轉(zhuǎn)換寄存器以二進制的補碼格式保存最后一次轉(zhuǎn)換的結(jié)果。需要注意的是,在上電之后,轉(zhuǎn)換寄存器被清除為0,并保持為0,直到第一次轉(zhuǎn)換完成。

實現(xiàn)代碼說明

讀取到的ADC值如何換算為電壓?

以PGA設(shè)置為4.96V為例。

電壓 = 采集到的ADC值 * 分辨率

分辨率 = 測量電壓范圍 / (2^AD位數(shù)-1) = 4.096 / 2的15次方 = 0.000125V

分辨率也可以在數(shù)據(jù)手冊中查看,見右圖。其中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();//起始信號    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();//停止信號    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();//起始信號    IIC_Write(0x90);//器件地址+寫    if( IIC_Wait_Ack() == 1 )        return -1;    IIC_Write(add);//寄存器地址    if( IIC_Wait_Ack() == 1 )        return -1;    do{      //超時判斷      i++;      if( i > 20 ) return -1;      delay_1ms(1);      IIC_Start();//重新發(fā)送起始信號      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ā)送停止信號    //數(shù)據(jù)整合    num =  ((dat[0]<<8) | (dat[1]));    //分辨率計算:測量電壓范圍/(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移植至工程

工程模板參考入門手冊的工程模板

移植步驟中的導(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ù) 說 明:對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時鐘
    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起始信號 * 函 數(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停止信號 * 函 數(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ù) 說 明:主機發(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ù) 說 明:等待從機應(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寫一個字節(jié) * 函 數(shù) 形 參:dat寫入的數(shù)據(jù) * 函 數(shù) 返 回:無 * 作       者:LC * 備       注:無******************************************************************/void IIC_Write(unsigned char dat){        int i = 0;        SDA_OUT();        SCL(0);//拉低時鐘開始數(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個字節(jié) * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:讀出的1個字節(jié)數(shù)據(jù) * 作       者:LC * 備       注:無******************************************************************/unsigned char IIC_Read(void){        unsigned char i,receive=0;    SDA_IN();//SDA設(shè)置為輸入    for(i=0;i<8;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();//起始信號  IIC_Write(0x90);//器件地址+寫  if( IIC_Wait_Ack() == 1 )      return -1;  IIC_Write(add);//寄存器地址  if( IIC_Wait_Ack() == 1 )      return -1;  do{    //超時判斷    i++;    if( i > 20 ) return -1;    delay_ms(1);    IIC_Start();//重新發(fā)送起始信號    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ā)送停止信號  //數(shù)據(jù)整合  num =  ((dat[0]<<8) | (dat[1]));
        //數(shù)值計算取決于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;
  //分辨率計算:測量電壓范圍/(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移植驗證

在自己工程中的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)    {        //當前設(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)推薦

電子產(chǎn)業(yè)圖譜

以開放、共享、互助為理念,致力于構(gòu)建武漢芯源半導(dǎo)體CW32系列MCU生態(tài)社區(qū)。無論是嵌入式MCU小自還是想要攻破技術(shù)難題的工程師,亦或是需求解決方案的產(chǎn)品經(jīng)理都可在CW32生態(tài)社區(qū)汲取營養(yǎng)、共同成長。

B站