ADS1115的配置
请问一下大家:
1、ADS1115的Config Register 在什么时候配置比较好,因为我需要采集双通道AD
2、写入的时候是不是要先写ADDR,然后Pointer Reg指向Config Reg,然后配置Config Reg,再ADDR,再Conversion Reg
读取的时候是不是只要先写ADDR,然后Pointer Reg指向Conversion Reg,再ADDR,然后输出的是Data
不知道我这样的理解对不对,还请大家帮忙指正,谢谢!
可以参考数据手册 QUICKSTART GUIDE
数据手册第11页介绍的很详细的,可以看看。另外Config Register在初始化配置,然后需要切换通道的时候需要重新配置
您好!我现在遇到了另外一个问题,单个通道采集没有问题,但是两个通道交替采集时,出来的数据是一样的,请问一下怎么解决,谢谢!
有可能是你没有切换到另外一个通道上去吧?
我用单个通道都能正常工作,就是两个通道一起交替进行,就出问题了
您好!请问一下对于切换通道,是不是只要在AD写入时改变配置寄存器的值,主要是MUX的值是么?烦请解答,谢谢!
是的,如果有PGA值需要改变也一起改变。配置后请等待一下在开始转换,因为它需要一个startup time
如果是one shot模式,MUX改变后下一次转换就是新的通道的数据;如果是连续转换模式,MUX 改变不改变当前的转换状态,当这一次转换完成后才切换到下一个通道开始转换。所以MUX切换后的第2租数据才是新通道的有效数据
您好!我尝试按照您说的改了一下,可是结果还是一样,后面附带了我的代码,麻烦您抽空帮忙看一下,感激不尽!
#include<avr/io.h>
#include<stdio.h>
#include <util/delay.h>
#include<avr/interrupt.h>
#define SS 2
#define SCK 5
#define MOSI 3
#define DDR_SPI DDRB
#define PORT_SPI PORTB
#define SET_SCL DDRD&=~_BV(PD6) //*****
#define CLR_SCL DDRD|=_BV(PD6)
#define SET_SDA DDRD&=~_BV(PD7)
#define CLR_SDA DDRD|=_BV(PD7)
#define SDA_PIN (PIND&_BV(PD7))
#define ADS1115_WRITE 0x90 // SDA地址寄存器(写)
#define ADS1115_READ 0x91 // SDA地址寄存器(读)
#define TwiWaitAck() while(SDA_PIN);
void delay(void);
void adc_init(void);
void uart_init(void);
void uart_send(unsigned char);
void SPI_MasterInit(void);
void SPI_MasterTransmit(unsigned char cData);
unsigned char EEPROM_read(unsigned int uiAddress);
void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
void twi_delay_bus(void);
void twi_ack(unsigned char ack);
void TwiInit(void);
unsigned char TwiStart(void);
void TwiStop(void);
unsigned char TwiWriteByte(unsigned char c);
unsigned char TwiReadByte(unsigned char ack);
void write_ads1115(unsigned char configreg);
void ads1115_read_adc_val(int k);
void ads1115_start_convert(unsigned char configreg);
volatile unsigned char StartFlag;
volatile unsigned char RecvIndex;
volatile unsigned char DacFlag;
unsigned char ADCResult[10][2];
unsigned char RecvData[5];
SIGNAL(SIG_UART_RECV);
int main(void)
{
int i,j;
volatile unsigned char RomH,RomL; //volatile易变的,不是由程序去改变,而是由硬件去改变
cli();
DDRC=0x00; //AVR单片机的IO是3态门,DDRC是C口的方向寄存器,PORTC是C口的数据寄存器,DDRC为0时,C口为输入,IO的高低从PORTC可以读出,DDRC为1时,c为输出,输出高低有PORTC控制。
PORTC=0x00;
DDRD|=0x20; //PD组,PD5输出,其他为输入
//PORTD&=0xDF;
PORTD|=0x20; //PD5置1,LED2不亮
StartFlag=0;
DacFlag=0;
RecvIndex=0;
TwiInit();
uart_init();
SPI_MasterInit();
PORT_SPI|=(1 << SS);
RomH=EEPROM_read(8);
RomL=EEPROM_read(7);
if((RomH==0x55)&&(RomL==0xaa)) //第一次下载程序,默认都是255,这时设置为0,防止输出过大
{
RomH=EEPROM_read(4);
RomL=EEPROM_read(3);
PORT_SPI&=(~(1<<SS));
SPI_MasterTransmit(0x18);//DA1
SPI_MasterTransmit(RomH);
SPI_MasterTransmit(RomL);
PORT_SPI|=(1<<SS);
delay();
}
else
{
EEPROM_write(8,0x55);
EEPROM_write(7,0xaa);
EEPROM_write(4,0x0);
EEPROM_write(3,0x0);
PORT_SPI&=(~(1<<SS));
SPI_MasterTransmit(0x18);
SPI_MasterTransmit(0);
SPI_MasterTransmit(0);
PORT_SPI|=(1<<SS);
delay();
}
RomH=EEPROM_read(6);
RomL=EEPROM_read(5);
if((RomH==0x55)&&(RomL==0xaa)) //第一次下载程序,默认都是255,这时设置为0,防止输出过大
{
RomH=EEPROM_read(2);
RomL=EEPROM_read(1);
PORT_SPI&=(~(1<<SS));
SPI_MasterTransmit(0x19);//DA2
SPI_MasterTransmit(RomH);
SPI_MasterTransmit(RomL);
PORT_SPI|=(1<<SS);
}
else
{
EEPROM_write(6,0x55);
EEPROM_write(5,0xaa);
EEPROM_write(2,0x0);
EEPROM_write(1,0x0);
PORT_SPI&=(~(1<<SS));
SPI_MasterTransmit(0x19);
SPI_MasterTransmit(0);
SPI_MasterTransmit(0);
PORT_SPI|=(1<<SS);
}
RomH=EEPROM_read(18);
RomL=EEPROM_read(17);
if((RomH==0x55)&&(RomL==0xaa)) //第一次下载程序,默认都是255,这时设置为0,防止输出过大
{
RomH=EEPROM_read(14);
RomL=EEPROM_read(13);
PORT_SPI&=(~(1<<SS));
SPI_MasterTransmit(0x1A); //DA3
SPI_MasterTransmit(RomH);
SPI_MasterTransmit(RomL);
PORT_SPI|=(1<<SS);
delay();
}
else
{
EEPROM_write(18,0x55);
EEPROM_write(17,0xaa);
EEPROM_write(14,0x0);
EEPROM_write(13,0x0);
PORT_SPI&=(~(1<<SS));
SPI_MasterTransmit(0x1A);
SPI_MasterTransmit(0);
SPI_MasterTransmit(0);
PORT_SPI|=(1<<SS);
delay();
}
RomH=EEPROM_read(16);
RomL=EEPROM_read(15);
if((RomH==0x55)&&(RomL==0xaa)) //第一次下载程序,默认都是255,这时设置为0,防止输出过大
{
RomH=EEPROM_read(12);
RomL=EEPROM_read(11);
PORT_SPI&=(~(1<<SS));
SPI_MasterTransmit(0x1B); //DA4
SPI_MasterTransmit(RomH);
SPI_MasterTransmit(RomL);
PORT_SPI|=(1<<SS);
}
else
{
EEPROM_write(16,0x55);
EEPROM_write(15,0xaa);
EEPROM_write(12,0x0);
EEPROM_write(11,0x0);
PORT_SPI&=(~(1<<SS));
SPI_MasterTransmit(0x1B);
SPI_MasterTransmit(0);
SPI_MasterTransmit(0);
PORT_SPI|=(1<<SS);
}
sei();
while(1)
{
if(StartFlag) //if (StartFlag!=0)
{ for(i=0;i<10;i++) //获得ADC值{ ADCSRA=0x00; ADMUX=(0x00|i); ADCSRA=0xC6; for(j=0;j<3;j++) {while(!(ADCSRA&0x10));ADCResult[i][1]=ADCL;ADCResult[i][0]=ADCH;ADCSRA|=0x10;ADCSRA|=0x40; } while(!(ADCSRA&0x10)); ADCResult[i][1]=ADCL; ADCResult[i][0]=ADCH; ADCSRA|=0x10; if(i==8) //ADS1115的1#ADC值 {ads1115_start_convert(0xC5); //##############################################ads1115_read_adc_val(8);twi_delay_bus(); }
if(i==9) //ADS1115的2#ADC值 {ads1115_start_convert(0xE5);ads1115_read_adc_val(9); twi_delay_bus(); }
uart_send('#'); //发送ADC值,十六进制码23,十进制码35,ASCII码# uart_send(i); //ADC通道 uart_send(ADCResult[i][0]); uart_send(ADCResult[i][1]); TwiInit();}delay();
}
else
{ADCSRA=0x00;
}
if(DacFlag>0) //接收上位机指令
{if(DacFlag==1) //DA1 腔温控1#{ PORT_SPI&=(~(1<<SS)); SPI_MasterTransmit(0x18); SPI_MasterTransmit(RecvData[3]); SPI_MasterTransmit(RecvData[4]); PORT_SPI|=(1<<SS); EEPROM_write(4,RecvData[3]); EEPROM_write(3,RecvData[4]); }if(DacFlag==2) //DA2 LD驱动电流{ PORT_SPI&=(~(1<<SS)); SPI_MasterTransmit(0x19); SPI_MasterTransmit(RecvData[3]); SPI_MasterTransmit(RecvData[4]); PORT_SPI|=(1<<SS); EEPROM_write(2,RecvData[3]); EEPROM_write(1,RecvData[4]);} if(DacFlag==0x0A) //DA3 腔温控2#{ PORT_SPI&=(~(1<<SS)); SPI_MasterTransmit(0x1A); SPI_MasterTransmit(RecvData[3]); SPI_MasterTransmit(RecvData[4]); PORT_SPI|=(1<<SS); EEPROM_write(14,RecvData[3]); EEPROM_write(13,RecvData[4]); }if(DacFlag==0x0B) //DA4{ PORT_SPI&=(~(1<<SS)); SPI_MasterTransmit(0x1B); SPI_MasterTransmit(RecvData[3]); SPI_MasterTransmit(RecvData[4]); PORT_SPI|=(1<<SS); EEPROM_write(12,RecvData[3]); EEPROM_write(11,RecvData[4]);}DacFlag=0;
}
}
}
void uart_init(void) //串口初始化
{
UCSRB=0X00; //关闭UART0
UCSRA=0X00; //不使用倍速发送(异步)
UCSRC=0X06; //无校验,8位数据,1位停止位
UBRRH=0X00;
UBRRL=0X33; //波特率9600
UCSRB=0X98;
}
SIGNAL(SIG_UART_RECV)
{
unsigned char temp;
cli();
temp=UDR;
if(RecvIndex==0)
{
if(temp==0x55)
RecvData[RecvIndex++]=temp;
}
else
{
RecvData[RecvIndex++]=temp;
}
if(RecvIndex==5)
{
RecvIndex=0;
if(RecvData[1]==0xaa)
{
if(RecvData[2]==3)
{if(RecvData[3]=='s'){ StartFlag=1; PORTD&=0xDF;}if(RecvData[3]=='p') StartFlag=0;
}
else
{if(RecvData[2]==1) DacFlag=1;if(RecvData[2]==2) DacFlag=2;if(RecvData[2]==0x0A) DacFlag=0x0A;if(RecvData[2]==0x0B) DacFlag=0x0B;
}
}
}
sei();
}
void uart_send(unsigned char temp) //串口发送子程序
{
while(!(UCSRA & 0x20));
UDR=temp;
}
void adc_init(void)
{
ADCSRA=0x00;
ADMUX=0x00;
ADCSRA=0xC6;
}
void SPI_MasterInit(void) //输出端初始化
{
DDR_SPI = (1 << SS)|(1 << MOSI)|(1 << SCK);
SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<SPR0);
SPSR = 0x00;
}
void SPI_MasterTransmit(unsigned char cData)
{
SPDR = cData;
while(!(SPSR & (1<<SPIF)));
}
void delay()
{
volatile unsigned char i,j,k,l;
for(i=0;i<200;i++)
{
for(j=0;j<100;j++)
{
for(k=0;k<5;k++)l=k+j;
}
}
}
unsigned char EEPROM_read(unsigned int uiAddress)
{
/* 等待上一次写操作结束 */
while(EECR & (1<<EEWE));
/* 设置地址寄存器 */
EEAR = uiAddress;
/* 设置EERE 以启动读操作 */
EECR |= (1<<EERE);
/* 自数据寄存器返回数据 */
return EEDR;
}
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
/* 等待上一次写操作结束 */
while(EECR & (1<<EEWE));
/* 设置地址和数据寄存器 */
EEAR = uiAddress;
EEDR = ucData;
/* 置位EEMWE */
EECR |= (1<<EEMWE);
/* 置位EEWE 以启动写操作E */
EECR |= (1<<EEWE);
}
void twi_delay_bus(void)
{
_delay_loop_2(10);//20*4/8000000=5us
//_delay_loop_2(20);//20*4/8000000=10us
}
void twi_ack(unsigned char ack)
{
if(!ack) //非应答
SET_SDA;
else //应答
CLR_SDA;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
CLR_SCL;
twi_delay_bus();
}
/*********以下为外部可调用的接口函数***********/
//初始化本模块
void TwiInit(void)
{
PORTD&=~(_BV(PD6)|_BV(PD7)); //置0
DDRD&=~(_BV(PD6)|_BV(PD7)); //输入状态
}
//产生启动信号
unsigned char TwiStart(void)
{
twi_delay_bus();
SET_SDA;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
CLR_SDA;
twi_delay_bus();
CLR_SCL;
twi_delay_bus();
return 1;
}
//产生停止信号
void TwiStop(void)
{
twi_delay_bus();
CLR_SDA;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
SET_SDA;
twi_delay_bus();
}
//向总线写一字节,并返回有无应答
unsigned char TwiWriteByte(unsigned char c)
{
unsigned char i,ack;
for(i=0;i<8;i++)
{
if(c&0x80)
SET_SDA;
else
CLR_SDA;
_delay_loop_2(1);
SET_SCL;
twi_delay_bus();
CLR_SCL;
c<<=1;
twi_delay_bus();
}
twi_delay_bus();
SET_SDA;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
if(SDA_PIN)
ack=0; //失败
else
ack=1;
_delay_loop_2(1);
CLR_SCL;
twi_delay_bus();
return ack;
}
//读一字节 ack: 1时应答,0时不应答
unsigned char TwiReadByte(unsigned char ack)
{
unsigned char i,ret;
ret=0;
SET_SDA;
for(i=0;i<8;i++)
{
twi_delay_bus();
CLR_SCL;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
ret<<=1;
if(SDA_PIN)
ret++;
}
CLR_SCL;
twi_delay_bus();
twi_ack(ack);
return(ret);
}
/******************************
往ADS1115写入一个字节
*******************************/
void write_ads1115(unsigned char configreg)
{
twi_delay_bus();
TwiStart(); //产生启动信号
TwiWriteByte(ADS1115_WRITE); // #define ADS1115_WRITE 0x90 =10010000 地址寄存器 最后那个0标识 写
TwiWriteByte(0x01); // 0x01=00000001 写入指针寄存器指向配置寄存器
TwiWriteByte(configreg); //Config reg的前8位,改变AD通道 1#0xC4 2#0xE4
TwiWriteByte(0x83); //Config reg的后8位,不变
TwiStop(); //产生停止信号
twi_delay_bus();
TwiStart(); //产生启动信号
TwiWriteByte(ADS1115_WRITE); // #define ADS1115_WRITE 0x90 =10010000 地址寄存器 最后那个0标识 写
TwiWriteByte(0x00); // 0x00=00000000 写入指针寄存器指向转换寄存器
TwiStop(); //产生停止信号
twi_delay_bus();
}
/******************************
从ADS1115读取ADC值
*******************************/
void ads1115_read_adc_val(int k)
{
unsigned char DH,DL;
twi_delay_bus();
TwiStart(); //产生启动信号
TwiWriteByte(ADS1115_READ); //#define ADS1115_READ 0x91=10010001 最后那个1标识 读
DH=TwiReadByte(1); //读一字节数据 ack: 1时应答,0时不应答
DL=TwiReadByte(1); //读一字节数据
TwiStop(); //产生停止信号
twi_delay_bus();
ADCResult[k][1]=DL;
ADCResult[k][0]=DH;
twi_delay_bus();
TwiInit();
}
//开始一次转换
void ads1115_start_convert(unsigned char configreg)
{
write_ads1115(configreg); //SDA写入 指针寄存器指向配置寄存器
}
稍等我仔细看看回复你
请这样试一下:
if(i==8) //ADS1115µÄ1#ADCÖµ
{
ads1115_start_convert(0xC5); //##############################################
twi_delay_bus();//给足够的建立时间
ads1115_read_adc_val(8);
}
if(i==9) //ADS1115µÄ2#ADCÖµ
{
ads1115_start_convert(0xE5);
twi_delay_bus();//给足够的建立时间
ads1115_read_adc_val(9);
}
uart_send('#'); //·¢ËÍADCÖµ£¬Ê®Áù½øÖÆÂë23£¬Ê®½øÖÆÂë35£¬ASCIIÂë#
uart_send(i); //ADCͨµÀ
uart_send(ADCResult[i][0]);
uart_send(ADCResult[i][1]);
//TwiInit();
另外,如果还不行,建议你使用one shot模式配合OS位或者RDY信号精确控制。事实上这样更好,可以确保一个通道关闭,另外一个通道打开
您好!感谢您的指导,我采用您的建议在写入后加了一个延时,同时重复调用3次,就实现了,感谢您的指导!
if(i==9) //ADS1115的2#ADC值 {
for(ql=0;ql<3;ql++){ ads1115_start_convert(0xE5); twi_delay_bus(); twi_delay_bus(); ads1115_read_adc_val(9); twi_delay_bus();} }
不客气!很高兴你的问题解决了!
