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();} }
不客气!很高兴你的问题解决了!