和上一篇AD7793类似,项目中也涉及到利用AD7745读取电容值,来测环境湿度。编写了以及MSP430的AD7745的硬件IIC驱动和模拟IIC驱动,分享给大家。
1. AD7745的硬件IIC驱动
MCU:MSP430F57XX
AD7745的硬件IIC驱动失败的几个原因有:单片机配置IIC资源错误(包括IIC的时钟,IIC的运行模型等配置错误),单片机的系统时钟配置错误(注意MCLK, SMCLK, ACLK的分配)
1.1 AD7745的写函数
void AD7745_W(unsigned char addr, unsigned char data)
{
while(UCB0STAT& UCBBUSY)
InitUCB0();
UCB0CTL1 |= UCTR;
UCB0CTL1 |= UCTXSTT;
UCB0TXBUF = addr;
delayus(200);
while(!(UCB0IFG & UCTXIFG0));
UCB0TXBUF = data;
delayus(200);
while(!(UCB0IFG & UCTXIFG0));
UCB0CTL1 |= UCTXSTP;
while (UCB0CTL1 & UCTXSTP);
}
1.2 AD7745的读函数
void AD7745_R(unsigned char addr, unsigned char *buffer, char n)
{
unsigned char index;
UCB0CTL1 |= UCTR;
UCB0CTL1 |= UCTXSTT;
delayus(200);
UCB0TXBUF = addr;
delayus(200);
while(!(UCB0IFG & UCTXIFG0));
while (UCB0CTL1 & UCTXSTP);
UCB0CTL1 &=~ UCTR;
RXByteCtr = n;
UCB0CTL1 |= UCTXSTT;
delayus(200);
while (UCB0CTL1 & UCTXSTP);
for(index=0; index < n-1; index++)
{
while(!(UCB0IFG & UCRXIFG0));
*buffer++ = UCB0RXBUF;
delayus(200);
}
UCB0CTL1 |= UCTXSTP+UCTXNACK;
delayus(200);
while((UCB0IFG&UCRXIFG)==0);
*buffer = UCB0RXBUF;
delayus(200);
while (UCB0CTL1 & UCTXSTP);
}
1.3 AD7745的复位
void Reset_AD7745()
{
while(UCB0STAT& UCBBUSY)
InitUCB0();
UCB0CTL1 |= UCTR;
UCB0CTL1 |= UCTXSTT;
delayus(200);
UCB0TXBUF = 0xBF;
while(!(UCB0IFG & UCTXIFG0));
UCB0CTL1 |= UCTXSTP;
while (UCB0CTL1 & UCTXSTP);
}
1.4 AD7745的初始化
void Init_AD7745(void)
{
AD7745_W(0x0D, offset_buf[0]);
AD7745_W(0x0E, offset_buf[1]);
capdac_offset = Capdac_Parameter;
out_buff[4] = 0x80+capdac_offset; //CAPDACA is set to capdac_offset
out_buff[5] = 0x80; //CAPDACB is set to 0
CAPDAC = (float)(capdac_offset*CAPDAC_UNIT); //CAPDAC只会取4值,即4.25,8.5,12.75,17
AD7745_W(0x07, out_buff[0]); // data collect
AD7745_W(0x08, out_buff[1]);
AD7745_W(0x09, out_buff[2]);
AD7745_W(0x0A, out_buff[3]);
AD7745_W(0x0B, out_buff[4]);
AD7745_W(0x0C, out_buff[5]);
memset(DataArr,0,sizeof(float)*DataNumber);
}
1.5 读取测量数据
void ReadData(void)
{
AD7745_R(0x01, in_buff, sizeof(in_buff)); // read the data register
CDC_Register_data = in_buff[1];
CDC_Register_data = 0;
CDC_Register_data = in_buff[1];
CDC_Register_data <<= 8;
CDC_Register_data += in_buff[2];
CDC_Register_data <<= 8;
CDC_Register_data += in_buff[0];
CDC_Register_data &= 0x00ffffff;
CDC_Capacitance2 = (float)(FULL_SCALE-SEMI_SCALE);
if(CDC_Register_data>= SEMI_SCALE)
{
CDC_Capacitance1 = (float)(CDC_Register_data-SEMI_SCALE);
CDC_Capacitance = 4.096 * (CDC_Capacitance1/CDC_Capacitance2);
}
else
{
CDC_Capacitance1 = (float)(SEMI_SCALE-CDC_Register_data);
CDC_Capacitance = -4.096 * (CDC_Capacitance1/CDC_Capacitance2);
}
CDC_Capacitance = CAPDAC+CDC_Capacitance;
Capacitance = CDC_Capacitance;
}
2. AD7745模拟IIC驱动
模拟IIC驱动失败的最主要原因是:时钟!时钟!时钟!注意时钟的配置和延时的处理
2.1 AD7745基础子函数的处理
void start()
{
SCL_OUT;
SDA_OUT;
SDA_H;
delayms(1);
SCL_H;
delayms(1);
SDA_L;
delayms(1);
SCL_L;
delayms(1);
}
void stop()
{
SDA_OUT;
SCL_OUT;
SDA_L;
delayms(1);
SCL_H;
delayms(1);
SDA_H;
delayms(1);
}
void Ack()
{
SDA_OUT;
SCL_OUT;
SCL_L;
SDA_L;
delayms(1);
SCL_H;
delayms(1);
SCL_L;
}
void NAck()
{
SDA_OUT;
SCL_OUT;
SCL_L;
SDA_H;
delayus(2);
SCL_H;
delayus(2);
SCL_L;
}
unsigned int WAck()
{
SDA_H;
SDA_IN;
SCL_H;
while(P1IN & BIT6)
{
}
SCL_L;
delayms(1);
return 0;
}
1.2 读取字节数据
uchar read_byte()
{
uchar i,read_data;
SDA_OUT;
SCL_L;
SDA_H;
for(i = 0;i<8;i++)
{
SDA_H;
delayus(2);
SCL_H;
SDA_IN;
delayus(2);
read_data <<= 1;
if(P1IN & BIT6)
read_data |= 0x01;
SDA_OUT;
SCL_L;
}
delayms(5);
return(read_data);
}
1.3 写字节数据
void write_byte(uint data)
{
uchar i;
SCL_OUT;
SDA_OUT;
for(i = 0;i<8;i++)
{
if(data & 0x80)
SDA_H;
else
SDA_L;
delayms(1);
SCL_H;
delayms(1);
SCL_L;
delayms(1);
data = data << 1;
}
delayms(5);
}
1.4 向指定地址写数据
void write_dat(uchar addr,uchar write_data)
{
start();
write_byte(OP_WRITE);
WAck();
write_byte(addr);
WAck();
write_byte(write_data);
WAck();
stop();
delayus(1000);
}
1.5 从指定地址读数据
uchar read_random(uint random_addr)
{
uchar i;
start();
write_byte(OP_WRITE);
WAck();
write_byte(random_addr);
WAck();
start();
write_byte(OP_READ);
WAck();
i = read_byte();
stop();
return i;
}
1.6 AD7745的初始化
void Init_AD7745()
{
start();
write_byte(0X09);
WAck();
write_byte(0xBF);
delayus(500);
WAck();
stop();
}
1.7 写数组与读数组
void EEPROM_WriteArray (unsigned char dest_addr, unsigned char* src_addr,
unsigned char len)
{
unsigned char i;
start();
write_byte(OP_WRITE);
WAck();
write_byte(dest_addr);
WAck();
for( i = 0; i < len; i++ )
{
write_byte(src_addr[i]);
WAck();
}
stop();
delayus(1000);
}
void EEPROM_ReadArray (unsigned char* dest_addr, unsigned char src_addr,
unsigned char len)
{
uchar i;
start();
write_byte(OP_WRITE);
WAck();
write_byte(src_addr);
WAck();
start();
write_byte(OP_READ);
WAck();
for( i = 0; i < len; i++ )
{
dest_addr[i] = read_byte();
if(i!=len-1)
Ack();
else
NAck();
}
stop();
}
1.8 AD7745的配置
void Capdacsetup(void)
{
EEPROM_WriteArray(0x0D, offset_buf, sizeof(offset_buf)); // OFFSET寄存器初始化
Capdac_Parameter = 127;
capdac_offset = Capdac_Parameter;
out_buff[4] = 0x80+capdac_offset;
out_buff[5] = 0x80; //CAPDACB is set to 0
CAPDAC = (float)(capdac_offset*CAPDAC_UNIT);
EEPROM_WriteArray(0x07, out_buff, sizeof(out_buff)); // data collect
memset(DataArr,0,sizeof(float)*DataNumber);
}
1.9 读取测量数据
void ReadData(void)
{
EEPROM_ReadArray(in_buff, 0x01, sizeof(in_buff)); // read the data register
CDC_Register_data = 0;
CDC_Register_data = in_buff[0];
CDC_Register_data <<= 8;
CDC_Register_data += in_buff[1];
CDC_Register_data <<= 8;
CDC_Register_data += in_buff[2];
CDC_Register_data &= 0x00ffffff;
CDC_Capacitance2 = (float)(FULL_SCALE-SEMI_SCALE);
if(CDC_Register_data>= SEMI_SCALE)
{
CDC_Capacitance1 = (float)(CDC_Register_data-SEMI_SCALE);
CDC_Capacitance = 4.096 * (CDC_Capacitance1/CDC_Capacitance2);
}
else
{
CDC_Capacitance1 = (float)(SEMI_SCALE-CDC_Register_data);
CDC_Capacitance = -4.096 * (CDC_Capacitance1/CDC_Capacitance2);
}
CDC_Capacitance = CAPDAC+CDC_Capacitance;
DataArr[Int_dec++]=CDC_Capacitance;
if(Int_dec==DataNumber)
Int_dec=0;
}