ADS1115可以測量ADC,能夠測量單端對地電壓和差分對輸入的電壓,測量范圍是0-6V。
上代碼:
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 V\r\n",t1);//打印 if(result == 0x7fff || result == 0x8000) { printf("已超量程!\r\n\r\n"); } else { printf("讀取正常!\r\n\r\n"); } } 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 V\r\n",t1); //打印 if(result == 0x7fff || result == 0x8000) //超過最大值或者低於最小值 { printf("已超量程!\r\n\r\n"); } else { printf("讀取正常!\r\n\r\n"); } } 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 V\r\n",t1);//打印 if(result == 0x7fff || result == 0x8000) { printf("已超量程!\r\n\r\n"); } else { printf("讀取正常!\r\n\r\n"); } } i++; delay_ms(10); if(i==20) { LED0=!LED0;//提示系統正在運行 i=0; } } }
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 SDA////PA9 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("已超量程!\r\n\r\n"); } else { printf("讀取正常!\r\n\r\n"); }
實際電路接法: