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");
}
实际电路接法: