ADS1115的使用教程(IIC)
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"); }
实际电路接法: