最近一直在调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 编辑