[讨论] 关于ADS1115的一点问题

偶尔瞌睡   2013-8-13 22:52 楼主


最近一直在调ADS1115这款AD,用I/O口模拟的I2C时序,结果总是不理想。读出来的数字我表示看不出规律,输入什么都不接有的时候是满值65535,有的时候乱跳。下面是我的程序,大家看下。我感觉我写的时序没什么问题,但是我的SDA总是低电平 首先IIC头文件 #ifndef _IIC_H_ #define _IIC_H_ #define S_SCL (P1OUT |= BIT1) #define C_SCL (P1OUT &= ~BIT1) //p1.1 时钟 #define S_SDA (P1DIR &= ~BIT7) //P1.7 数据 #define C_SDA (P1DIR |= BIT7) #define ALERT (P1IN&BIT3) //P1.3 (ADS1115 的 ALERT脚信号输入,数据转换完成后被拉低 #define SDA P1IN #define uchar unsigned char #define uint unsigned int void wait(void) //短延时函数 { uchar i=3; while(i--); _NOP(); } void start(void) //产生起始信号(在时钟线为1时,数据线要有下降沿) { S_SDA; //数据线拉高 wait(); S_SCL; //时钟线拉高 wait(); C_SDA; //数据线拉低(数据线下降沿) wait(); C_SCL; //时钟线拉低 wait(); } void stop(void) //产生停止信号(在时钟线为1时,数据线要有上升沿) { C_SCL; //时钟线为低 wait(); C_SDA; //数据线为低 wait(); S_SCL; //时钟线为高 wait(); S_SDA; //数据线为高(数据线上升沿) } void ack(void) //主机应答函数(数据线为低的时候,时钟线有上升沿和下降沿,一个完整的时钟) { C_SDA; //数据线为低 wait(); S_SCL; //时钟线为高 wait(); C_SCL; //时钟线为低 wait(); S_SDA; //数据线为高 } uchar check_ack(void) //检I2C应答 { uchar ack; S_SDA; //数据线为高 wait(); S_SCL; //时钟线为高 wait(); ack=SDA & 0x80; //从设备应答会把数据线拉低 C_SCL; //时钟线为低 _NOP(); if(ack) return 1; //无应答 else return 0; //有应答 } void write_byte(uchar byte) //发送一个8位数据 { uchar i; C_SCL; //拉低时钟线 for(i=0;i<8;i++) //连续发送8位数据 { if(byte & 0x80) S_SDA; //变数据(为1发送高电平,为0发送低电平) else C_SDA; //先从最高位发送 wait(); S_SCL; //拉高时钟线,送数据 wait(); C_SCL; //再把时钟拉低 byte <<= 1; //准备下一位 } } uchar read_byte(void) //读数据 { uchar byte=0,i; P1DIR &= ~BIT7; //输入模式 wait(); for(i=0;i<8;i++) { S_SCL; //拉高时钟线 wait(); byte <<= 1; if(SDA & 0X80) byte |= 0x01; //判断P1.7是高电平还是低电平 C_SCL; //拉低时钟线 wait(); } return byte; } void write_word(uchar addr,uint word) { uchar byte=0x90; //1001 0000 start(); write_byte(byte); //I2C地址,操作为写 byte = check_ack(); write_byte(addr); //指向相应寄存器 byte = check_ack(); write_byte(word>>8); //写高字节 byte = check_ack(); write_byte(word); //写低字节 byte = check_ack(); stop(); } uint read_word(uchar addr) { uint word; uchar byte=0x90; //1001 0000 start(); write_byte(byte); //I2C地址,操作为写 byte = check_ack(); write_byte(addr); //指向相应寄存器 byte = check_ack(); stop(); wait(); start(); byte=0x91; //1001 0001 write_byte(byte); //地I2C址,操作为读 byte = check_ack(); word = read_byte(); //读高字节 ack(); word <<= 8; byte = read_byte(); //读低字节 ack(); word += byte; stop(); return word; } #endif 这是主函数 #include #include"iic.h" uint value; float sum; void clk_init(void) //配置主时钟函数 { unsigned int i; FLL_CTL0 |= XCAP18PF; // Set load capacitance FLL_CTL1 &= ~XT2OFF; // Turn on XT2 do { IFG1 &= ~OFIFG; // Clear oscillator fault flag for (i = 0xff; i; i--); // Delay } while (IFG1 & OFIFG); // Test osc fault flag FLL_CTL1 = SELS + SELM_XT2; // Select SMCLK source as XT2CLK } void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT clk_init(); //配置主时钟 P1DIR |= BIT1; P1OUT &= ~BIT7; stop(); while(1) { write_word(0x01,0x4283); //100 0010 1000 0011,001 : FS = ±4.096V while(ALERT); //等待方式,转换完成则读取数据 value = read_word(0x00); //读取值 //sum=(4.096*value/65536); //------- your code -------// } }

 

本帖最后由 paulhyde 于 2014-9-15 03:53 编辑

回复评论 (3)



“输入什么都不接有的时候是满值65535,有的时候乱跳”输入什么都不接出现这种情况正常啊,只要接上要测得电压,测出来的值准、稳定就行

 

本帖最后由 paulhyde 于 2014-9-15 03:53 编辑
点赞  2013-8-14 11:03


输入悬空测量不能作为采样正确的判定标准,楼主可以测量 在量程内均匀分布的几个值然后再确定问题

 

本帖最后由 paulhyde 于 2014-9-15 03:53 编辑
点赞  2013-8-14 12:08
请教您一个问题,跟你遇到的问题一样,如果只按手册上的配置输出的是7ffff啊,不知道怎么做了,后来你怎么做的?
点赞  2015-4-27 12:19
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复