Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

AD5933 code example with AVR

Status
Not open for further replies.

north2012

Member level 3
Joined
Apr 1, 2013
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,813
Hello,

Does anybody have c example for communication between AD5933 (Impedance converter) and AVR ATmega 128 or 32?
I found example for ARM but it does not work after changes which I made. The original code is
Code:
/
***************************************************************************

 Author        : sean brennan dac applications

 Date          : APRIL. 2006

 File          : AD5933_I2C_Master.c

 Hardware      : Applicable to ADuC702x rev H or I silicon
                 Currently targetting ADuC7026.

 Description   : I2C master	to demonstrate with I2C_Slave.c
             
             Operates in two modes, read & write (called recieve and 
             transmit here). At the begining of an I2C transmission, the 
             Master sends an address. The LSB of this address determines 
             if the Master is to read (1) or write (0).

             This code also demonstrates basic UART functionality.
             The baudrate is calculated with the following formula:
 
               DL = HCLK										   
                  _______										   
                  Baudrate * 2 *16
      
***************************************************************************/

#include<ADuC7020.h>				  // 	Include ADuC7020 Header File
#include"stdio.h"                     // include standard i/o Header file 


void IRQ_Handler(void) __irq;    //	IRQ Funtion Prototype 
void delay(int);
void i2c_write ( unsigned int reg_address, unsigned int reg_write_data);
int AD5933_read (unsigned int register_address);
void i2c_read(void);
char hexidecimal_ascii(char toconv);   //hex to ascii conversion
void send_data_uart(short to_send);  // sends data up UART
extern int write (char * ptr, int len);   // Functions used to  
extern int getchar (void);           // to output data 	 
extern int putchar (int);                // Write character to Serial Port
void Measure_Temp (void);               
void sweep (void);
void convert (short bin, char *str); // converts real/imag (2's complement to hex/decimal) 


#define count 0x0;					// Number of bytes to be recieved - 1
#define address_pointer_command 0xB0;



int i = 0, Receive_byte[1];              // Size of receive_byte should be (count + 1)
char a;
short int status_register ;  
unsigned char jchar = 0x30;                           
unsigned int real_data;
unsigned int imag_data;
unsigned char binary[16];// array used to convert 2's complement to binary  


int main(void)
   {
	
   IRQEN = PLA_IRQ0_BIT+SM_MASTER1_BIT ;             // Enable i2c in IRQEnable  
   GP4DAT = 0x04040000;            // Configure P4.2 as output
   GP3DAT = 0xff000000;            // Configure port 3 as output
   GP1CON = 0x2211;                // I2C on P1.2 and P1.3
   I2C1CFG = 0x82;                 // Master Enable & Enable Generation of Master Clock

   // I2C-Master setup
   I2C1DIV = 0xcfcf;              // 0x3232 = 400kHz
   								  // 0xCFCF = 100kHz
   	
   // UART set up at 9600bps
   // Start setting up UART at 9600bps
   COMCON0 = 0x080;           // Setting DLAB
   COMDIV0 = 0x088;           // Setting DIV0 and DIV1 to DL calculated
   COMDIV1 = 0x000;
   COMCON0 = 0x007;           // Clearing DLAB

   // Transmit	to start frequency register 
   // program 30khz start frequency assuming internal osc of 16.776Khz
   i2c_write ( 0x84, 0x45);
   i2c_write ( 0x83, 0xA6);    
   i2c_write ( 0x82, 0x0E);

   // Transmit to frequency increment register 
   // program 1Khz frequency increment assuming internal osc of 16.776Khz
   i2c_write ( 0x87, 0x02);
   i2c_write ( 0x86, 0x7D);    
   i2c_write ( 0x85, 0x00);

   // Transmit to NUMBER OF INCREMENTS register 
   // program 10 frequency increments
   i2c_write ( 0x89, 0x0A);
   i2c_write ( 0x88, 0x00);

   // Transmit to settling time cycles register 
   // program 15 output cycles at each frequency before a adc conversion
   i2c_write ( 0x8B, 0x0F);
   i2c_write ( 0x8A, 0x00);


   // Transmit to CONTROL register 
   // place the AD5933 in standby mode
   i2c_write ( 0x80, 0xB0);

   // Choose the internal system clock
   i2c_write ( 0x81, 0x00);

   // Choose range 1 (2vp-p, 1.6v) PGA = x1	 
   i2c_write ( 0x80, 0x01);

   // initialise the sensor with contents of start frequency regsister with range 1 (2vp-p, 1.6v) PGA = x1
   i2c_write ( 0x80, 0x10);
   // start of frequency sweep  (2vp-p, 1.6v) PGA = x1
   i2c_write ( 0x80, 0x20);
   // initialise the sweep sequence
   sweep ();

   //issue a measure temperature command to the control register 
   i2c_write ( 0x80, 0x90);
   // read the temperature data and send to uart
   Measure_Temp();



   while(1)
      {
      // do nothing
      };

   return 0;
   }





/////////////////////////////////////// function's///////////////////////////////////////////
void delay (int length)
   {
   while(length >0)
      length--;
   }

void i2c_write ( unsigned int reg_address, unsigned int reg_write_data)
   {

   I2C1MTX =   reg_address;   //  register address.send i2c byte address	 			  
   I2C1MTX =   reg_write_data;      // register data. send i2c byte address	
   I2C1ADR =   0x1A;       //  device address. set i2c address(LSB = 0, Master Write)
   delay(4000);  // nominal delay 			  
   return;
   }

int AD5933_read (unsigned int register_address)
   {
   i2c_write(0xB0,register_address);    // set the address pointer
   i2c_read();
   return(Receive_byte[0]);
   }

void i2c_read(void)
   {
   i = 0;
   I2C1CNT =   count;            // Number of bytes to be read from slave
   I2C1ADR =  0x1B;       //  device address. set i2c address(LSB = 1, Master Read)
   delay(4000);           
   return;     
   }

void send_data_uart(short to_send)  // sends data up UART
   {
   //while(!(0x020==(COMSTA0 & 0x020))){}
   //	COMTX = 0x0A;						// output Line feed 
   //while(!(0x020==(COMSTA0 & 0x020))){}
   //	COMTX = 0x0D;						// output Carrage return 
   while(!(0x020==(COMSTA0 & 0x020)))
      {
      }
   COMTX = (hexidecimal_ascii ((to_send >> 12) & 0x0F));
   while(!(0x020==(COMSTA0 & 0x020)))
      {
      }
   COMTX = (hexidecimal_ascii ((to_send >> 8) & 0x0F));
   while(!(0x020==(COMSTA0 & 0x020)))
      {
      }
   COMTX = hexidecimal_ascii ((to_send >> 4) & 0x0F);                
   while(!(0x020==(COMSTA0 & 0x020)))
      {
      }
   COMTX = hexidecimal_ascii(to_send & 0x0F);
   while(!(0x020==(COMSTA0 & 0x020)))
      {
      }
   COMTX = 0x0A;                 // output Line feed 
   while(!(0x020==(COMSTA0 & 0x020)))
      {
      }
   COMTX = 0x0D;                 // output Carrage return 	 							
   return;
   }
char hexidecimal_ascii(char toconv)   //hex to ascii conversion
   {
   if(toconv<0x0A)
      {
      toconv += 0x30;
      } else
      {
      toconv += 0x37;
      }

   return(toconv);
   }


void sweep (void)
   {
   unsigned int real_byte_high;
   unsigned int real_byte_low;

   unsigned int imag_byte_high;
   unsigned int imag_byte_low;


   signed short int imag_data;
   signed short int real_data;

   //write(output3,25); // output "start sweep" to uart
   printf ("Start of Frequency sweep\n");       // printf function call   

   for(;;)
   // status reg D0 = valid temp, D1 = valid real/imag data, D2 = frequency sweep complete
      {
      // D1 status reg loop
      status_register = AD5933_read(0x8F);     // read the status register
      status_register = (status_register & 0x2); // mask off the valid data bit
      if( ((status_register)| 0xFD )==  0xFF)  // valid data should be present after start freqy command
         {
         // D1 true condition
         //printf ("Status register is %u (dec) \n",status_register);       // printf function call

         if( (AD5933_read(0x8F)| 0xFB )!=  0xFF)// D2 test condition
            {

            real_byte_high = AD5933_read(0x94);
            real_byte_low = AD5933_read(0x95);
            imag_byte_high = AD5933_read(0x96);
            imag_byte_low =  AD5933_read(0x97);

            real_data = ((real_byte_high << 8) |  real_byte_low);
            imag_data = ((imag_byte_high << 8) |  imag_byte_low);

            // real data

            convert(real_data,binary);
            printf ("original  Real register = 0x%x\n",(unsigned int)((unsigned short)real_data));       // printf function call
            //printf ("processed Real register = %s (binary equivilant of above)\n",binary);
            // printf ("\n%s ",binary);
			//printf ("processed real register = %d(decimal equivilant)\n",(int)real_data);
            //printf ("\n");

            binary[0x0]='\0';


            convert(imag_data,binary);
            printf ("original  imag register = 0x%x\n",(unsigned int)((unsigned short)imag_data));       // printf function call
            //printf ("processed imag register = %s (binary equivilant of above)\n",binary);
			//printf ("\n%s",binary);
            //printf ("processed imag register = %d(decimal equivilant)\n%d\r",(int)imag_data);
            //printf ("\n");

            binary[0x0]='\0';

            // increment to the next frequency
            i2c_write ( 0x80, 0x30);

            } // end of D2 test condition

         else // End of frequency sweep exit loop
            {
            //printf ("Status register is %u (dec) \n",status_register);
            break;
            }

         } // end of D1 true condition
      } // end of for loop


   }// end of sweep function

void convert (short bin, char *str) // converts from 2s complement to hex.
   {
   unsigned short mask;      // used to check each individual bit, unsigned
                             //    to alleviate sign extension problems

   mask = 0x8000;           // Set only the high-end bit
   while(mask)             // Loop until MASK is empty
      {
      if(bin & mask)     // test the masked bit
         *str = '1';   // if true, value is 1
      else
         *str = '0';   // if false, value is 0
      str++;              // next character
      mask >>= 1;         // shift the mask 1 bit
      }
   *str = 0;               // add the trailing null
   }



////////////////////////////////////////////////////////////////////////////////////////////


/*************************************************/
/*************************************************/
/************	IRQ Service Routine  *************/
/*************************************************/
/*************************************************/

void IRQ_Handler() __irq
{


   // i2c Recieve
   if((I2C1MSTA & 0x8) == 0x8)                // Master Recieve IRQ	 	
      {
      Receive_byte[0] = I2C1MRX;

      }
   //  wait until the user has released push button 
   //	while(GP0DAT & 0x00010)	{} // increment to the next frequency

   //     I2C1ADR = 	0x1A;	 		//  device address. set i2c address(LSB = 0, Master Write) MMR 0XXFFFF081C
   //     I2C1MTX =   0x80;			//  register address.send i2c byte address	 			   MMR OXFFFF0814
   //     I2C1MTX =   0x30;			// register data. send i2c byte address	 			       MMR OXFFFF0814
   //     GP4DAT &= 0x04000000;		// Turn on led to indicate sweep point
   // 	write(output1,25);		// Output  string to hyperterminal 	



   return ;

}

Best regards.
 

Hello,

I wrote code in C for communication between AD5933 and AVR Atmega 128 (please see attachemt).

After mcu and lcd initialization, calibrating is performing with known impedance of 22 kOhms as Z while Rfb is 20 kOhms. With that parameters the Gain factor is calculated and in next steps I am performing only measuring with GF correction. After calibrating I kept 22 kOhms in Z holder and measuring is correct (approximately 22000.65 Ohms) but after that if I change Z (in range 15-50 kOhms) all results are very close to 22 kOhms. If I completely remove Z (open circuit), the measuring is ok with results in order of MOhms. Do you have any suggestion what is wrong with my code? All functions, except for LCD are written in ANSI C so I believe that there is no problem with syntax because I used micro C compiler.

I downloaded “AD5933 theoretical” and ADC is not saturated and impedance range is ok.

Best regards

Code:
//internal osc of 16.776 MHz

// LCD module connections
sbit LCD_RS at PORTC3_bit;
sbit LCD_EN at PORTC2_bit;
sbit LCD_D4 at PORTC4_bit;
sbit LCD_D5 at PORTC5_bit;
sbit LCD_D6 at PORTC6_bit;
sbit LCD_D7 at PORTC7_bit;

sbit LCD_RS_Direction at DDC3_bit;
sbit LCD_EN_Direction at DDC2_bit;
sbit LCD_D4_Direction at DDC4_bit;
sbit LCD_D5_Direction at DDC5_bit;
sbit LCD_D6_Direction at DDC6_bit;
sbit LCD_D7_Direction at DDC7_bit;
// End LCD module connections
#define SUCCESS 0xff        //Flag

//Command
#define Start 0xa4
#define Stop 0x94
#define Trans 0x84
#define ACK 0xc4

//I2C bus Status
#define START 0x08
#define ReSTART 0x10
#define SLA_W 0x1a
#define SLA_R 0x1b
#define MT_SLA_ACK 0x18
#define MT_SLA_NACK 0x20
#define MR_SLA_ACK 0x40
#define MR_SLA_NACK 0x48
#define MT_DATA_ACK 0x28
#define MT_DATA_NACK 0x30
#define MR_DATA_ACK 0x50
#define MR_DATA_NACK 0x58
#define TWINT 0x80

//AD5933 control codes
#define Init 0x10        //Initialize with start Freq
#define Sweep 0x20        //Start Frequency Sweep
#define IncFreq 0x30        //Increment Frequency
#define RepFreq 0x40        //Repeat Frequency
#define MeaTemp 0x90        //Measure Temperature
#define PowerDown 0xa0        //Power down mode
#define Standby 0xb0        //Standby mode
#define Range2V 0x00        //Output Voltage range 2V
#define Range1V 0x06        //Output Voltage range 1V
#define Range400mV 0x04 //Output Voltage range 400mV
#define Range200mV 0x02 //Output Voltage range 200mV
#define gainx5 0x00        //PGA gain x5
#define gainx1 0x01        //PGA gain x1

//AD5933 Register addresses
#define Control_high 0x80
#define Control_low 0x81
#define Freq_high 0x82
#define Freq_mid 0x83
#define Freq_low 0x84
#define FreqInc_high 0x85
#define FreqInc_mid 0x86
#define FreqInc_low 0x87
#define NumInc_high 0x88
#define NumInc_low 0x89
#define NumSettle_high 0x8a
#define NumSettle_low 0x8b
#define Status 0x8f
#define Temp_high 0x92
#define Temp_low 0x93
#define Real_high 0x94
#define Real_low 0x95
#define Imag_high 0x96
#define Imag_low 0x97

unsigned char Init_TWI(void)
{
        TWBR = 0x18;            //Set baud-rate to 250 KHz at 16 MHz xtal
        TWCR = 0x04;                //Enable TWI-interface
        return 1;
}

void Wait_TWI_int(void)
{
        while(!(TWCR & TWINT));
}

unsigned char Send_start(void)
{
        TWCR=Start;                //Send START

        Wait_TWI_int();                //Wait for TWI interrupt flag to be set

            if((TWSR & 0xF8)!=START || (TWSR & 0xF8)!=ReSTART)
                return TWSR;        //If it failed, return the TWSR value
            return SUCCESS;                //If succeeded, return SUCCESS
}

void Send_stop(void)
{
        TWCR = Stop;                //Send a STOP condition
}

unsigned char Send_adr(unsigned char adr)
{
        Wait_TWI_int();                //Wait for TWI interrupt flag set

        TWDR = adr;
        TWCR = Trans;           //Clear int flag to send byte

        Wait_TWI_int();                //Wait for TWI interrupt flag set

        if((TWSR & 0xF8)!= MT_SLA_ACK || (TWSR & 0xF8)!= MR_SLA_ACK)
                return TWSR;        //If NACK received return TWSR

        return SUCCESS;                //Else return SUCCESS
}

unsigned char Send_byte(unsigned char ddata)
{
        Wait_TWI_int();                //Wait for TWI interrupt flag set

        TWDR = ddata;
         TWCR = Trans;           //Clear int flag to send byte

        Wait_TWI_int();                //Wait for TWI interrupt flag set

        if((TWSR & 0xF8)!= MT_DATA_ACK)
                return TWSR;        //If NACK received return TWSR
        return SUCCESS;                //Else return SUCCESS
}

unsigned char Set_pointer(unsigned char reg_loc)
{
        Send_start();
         Send_adr(SLA_W);
            Send_byte(0xb0);        //Pointer command code '1011 0000'
            Send_byte(reg_loc);        //a register location at which the pointer points
            return 1;
}

unsigned char Byte_write(unsigned char reg_addr, unsigned char ddata)
{
        Send_start();
         Send_adr(SLA_W);
            Send_byte(reg_addr);
           Send_byte(ddata);
           Send_stop();
        return 1;
}

unsigned char Block_write(unsigned char reg_loc, unsigned char byte_num, unsigned char* data_p)
{
        unsigned char i;

        Set_pointer(reg_loc);        //set the pointer location
            Send_start();                //write the data block
         Send_adr(SLA_W);
            Send_byte(0xa0);        //Block write command code '1010 0000'
            Send_byte(byte_num);        //Num of data to be sent

            for(i = 0;i < byte_num;i++)  //Send the data bytes
            {
                    Send_byte(*(data_p+i));
            }
            Send_stop();
           return 1;
}

unsigned char Byte_read(unsigned char reg_loc)
{
        Set_pointer(reg_loc);        //set the pointer location

        //Receive a byte
        Send_start();
         Send_adr(SLA_R);
        TWCR = Trans;
        Wait_TWI_int();         //Wait for TWI interrupt flag set
        return TWDR;
}

unsigned char Block_read(unsigned char reg_loc, unsigned char byte_num)
{
        unsigned char i;
        unsigned char* data_p;

        Set_pointer(reg_loc);        //set the pointer location

        //write the data block
         Send_start();
         Send_adr(SLA_W);
         Send_byte(0xa1);        //Block read command code '1010 0001'
         Send_byte(byte_num);        //Num of data to be received

         Send_start();
         Send_adr(SLA_R);
         for(i = 0;i < byte_num;i++)        //Receive all the bytes
           {
                TWCR = ACK;                //Clear int flag and enable acknowledge to receive data.
                Wait_TWI_int();                //Wait for TWI interrupt flag set
                *(data_p+i)=TWDR;
        }

        TWCR = Trans;
        Wait_TWI_int();                        //Wait for TWI interrupt flag set

        *(data_p+i)=TWDR;                //Save Last byte

         Send_stop();
         return data_p;
}

unsigned long int Data_proc(unsigned char data_high, unsigned char data_low)
{
        unsigned long int ddata;
        ddata=(unsigned long int)data_high*256+data_low;
        if(ddata > 0x7fff)
        {
                ddata=0x10000-ddata;
        }
        return ddata;
}

void Display(unsigned long int real, unsigned long int imag, float Res)
{
        char txt1[12];
        char txt2[12];
        char txt3[15];

        lcd_cmd(_lcd_clear);
        lcd_out(1, 1, "R=");
        lcd_out(2, 1, "I=");
        lcd_out(3, 1, "Z=");
        longtostr(real, txt1);
        longtostr(imag, txt2);
        floattostr(Res, txt3);
        lcd_out(1, 3, txt1);
        lcd_out(2, 3, txt2);
        lcd_out(3, 3, txt3);
}

void main(void)
{
unsigned char a = 0x00, b = 0x00;
unsigned long int R = 0x00000000, I = 0x00000000;
float Z = 0.0, GF = 1.0, Result = 0.0;

//start of program
Lcd_Init();                        // Initialize LCD
delay_ms(100);
Lcd_Cmd(_LCD_CLEAR);               // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
Init_TWI();
lcd_out(4,1,"INIT DONE...");
delay_ms(750);
lcd_out(4,1,"CALIBRATING...");
delay_ms(1000);
//start frequency register - 50 kHz
  Byte_write ( 0x84, 0x99);
  Byte_write ( 0x83, 0x99);
  Byte_write ( 0x82, 0x19);
//frequency increment register - 1 kHz
  Byte_write ( 0x87, 0x02);
  Byte_write ( 0x86, 0x7D);
  Byte_write ( 0x85, 0x00);
//number of increments
  Byte_write ( 0x89, 0x0A);
  Byte_write ( 0x88, 0x00);
//settling time cycles register - 15
  Byte_write ( 0x8B, 0x0F);
  Byte_write ( 0x8A, 0x00);
  
//CONTROL register
//AD5933 in standby mode
  Byte_write ( 0x80, 0xB0);
//internal clock
  Byte_write ( 0x81, 0x00);
//range 1 (1vp-p, 1.6v) PGA = x1
  Byte_write  ( 0x80, 0x01);
  Byte_write(Control_high, 0x10);
  Byte_write(Control_high, 0x21); //start sweep
  
  while(!(Byte_read(Status) & 0x02));
  //real data
  a = 0x00; b = 0x00;
  a = Byte_read(Real_high);
  b = Byte_read(Real_low);
  R = Data_proc(a, b);
  //Imag data
  a = 0x00; b = 0x00;
  a = Byte_read(Imag_high);
  b = Byte_read(Imag_low);
  I = Data_proc(a, b);
  Z = sqrt(R*R+I*I);
  GF = 1.0/(Z*22000.0);
while(1)
{
  lcd_out(4,1,"MEASURING... ");
  R = 0x00000000; I = 0x00000000;
  delay_ms(750);
  //start frequency register - 50 kHz
  Byte_write ( 0x84, 0x99);
  Byte_write ( 0x83, 0x99);
  Byte_write ( 0x82, 0x19);
//frequency increment register - 1 kHz
  Byte_write ( 0x87, 0x02);
  Byte_write ( 0x86, 0x7D);
  Byte_write ( 0x85, 0x00);
//number of increments
  Byte_write ( 0x89, 0x0A);
  Byte_write ( 0x88, 0x00);
//settling time cycles register - 15
  Byte_write ( 0x8B, 0x0F);
  Byte_write ( 0x8A, 0x00);
//CONTROL register
//AD5933 in standby mode
  Byte_write ( 0x80, 0xB0);
//internal clock
  Byte_write ( 0x81, 0x00);
//range 1 (2vp-p, 1.6v) PGA = x1
  Byte_write ( 0x80, 0x01);
  Byte_write(Control_high, 0x10);
  Byte_write(Control_high, 0x21); //start sweep
  while(!(Byte_read(Status) & 0x02));
  //Initialize
  Byte_write(Control_high, 0x10);
  Byte_write(Control_high, 0x21); //start sweep
  while(!(Byte_read(Status) & 0x02));
  a = 0x00; b = 0x00;
  //real data
  a = Byte_read(Real_high);
  b = Byte_read(Real_low);
  R = Data_proc(a, b);
  a = 0x00; b = 0x00;
  //Imag data
  a = Byte_read(Imag_high);
  b = Byte_read(Imag_low);
  I = Data_proc(a, b);
  Z = sqrt(R*R+I*I);
  Result = 1.0/(Z*GF);
  Display(R, I, Result);
  delay_ms(3000);
}
}
 
Which software can be used for simulation of circuits containing AD5933 with atmega microcontroller?
What is “AD5933 theoretical”?
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top