MSP430杂谈--AD7745硬件IIC驱动与模拟IIC驱动

和上一篇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;
}

 

上一篇:AutoCAD VBA 批量导出源代码


下一篇:Windows 2016 & Windows 10 中IIS安装和配置PHP的步骤