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.

Reading values from external ADC using ATmega32-A.

Status
Not open for further replies.

veerubiji

Full Member level 2
Joined
Feb 24, 2011
Messages
122
Helped
3
Reputation
6
Reaction score
3
Trophy points
1,298
Activity points
2,301
I have started newly working with AVR microcontroller.I am using ATmega32-A microcontroller. I have connected one external ADC(AD7798). I want read external ADC values using SPI communication.I have tried so much but i am not able to get ADC values.My project is I have to generate waveform using microcontroller with programmable waveform generator. I am successfully doing this and giving this signal to sensor. I want read sensor output from ADC. I have attached simple circuit diagram below. I wrote code like this
Code:
    // I have initialized PORTB like this

    PORTB=0x00;
    DDRB=0xBF;
   
    // SPI initialisation
    // SPI clock rate fck/16
    // SPI master
    // SPI MSB first
    // SPI CPOL = 1, CPHA = 1

    SPCR=0x5D;
    PORTB.3 = 1; 
    
     void UniCom(void){

        switch(Command){
       
            case(INF):
                printf("\r\n\r\n");
                printf("sweden\r\n");
                printf("university\r\n");
                printf("masters\r\n");
                Command = 0;
                break;
            case(WGF):
                if(Param < 500)
                    SetWGFreq(Param);   
                    Command = 0;
                break; 
            case(MEM): 
                printf("adc Value");
                ReadAd()                                
                Command = 0;
                break;
            case(CLEARM):
                  MeasureAll();
                Command = 0;
                break;
            default:
                Command = 0;
                break;   
        }
      }
     void main(void){
      
        status = 0x0010;
        init();     //Initialize controller                                
        SetWGFreq(125);   //Initialize waveformgenerator 125 kHz                 
        Command = INF;  
        debug = 0;    //Controls output during motor running                                    
        
        while (1){
            
            if(rx_counter0) getCom();
            if(Command)     runCom();
            -------------------
            ------------------
            #asm("WDR");        //Reset WD timer            
        }  // EOF "while(1)"
    } // EOF "main(void)"

I wrote all function in another file

    #define ADC_CS PORTB.3
    #define WG_CS PORTB.4
    #define MOSI PORTB.5
    #define MISO PINB.6
    #define SCK PORTB.7

    #define ADC_CS_PIN PINB.3
    #define WG_CS_PIN PINB.4

    char spi(char data)
     {
    //Start transmision
    SPDR = data;
    //Wait for transmision complete
    while(!(SPSR & 0x80));
    return SPDR;
     } 

    //Sets the waveform generator output to given kHz
    void SetWGFreq(unsigned int freq)
    {
    unsigned long freg;
    -----------
    -----------
    }

    unsigned int ReadAd(void)
    {
    unsigned int data;
     ChipSelectAd(1);
    //Read data
    CheckStatus();         //Wait for data ready in 
                             adc register
    spi(0x58);              //Place readinstruction 
                            in communication register
    data = (spi(0xFF)<<8);    //Read 8 most significant 
                             bits from data register
    data |= spi(0xFF);      //Read 8 leastsignificant 
                             bits from data register  
    return data;
    }

    void CheckStatus(void)
    {
    //char adcStatus;
    adcStatus = 0xFF;                                           
    //Read status
    while(!(adcStatus & 0x80))
    {
        spi(0x40);
        adcStatus = spi(0xFF);
    }
    }     
                                      
    void ChipSelectAd(char s)
    {
    if(s == 1){
        PORTB.3 = 0;    //Switch on AD
        while(PINB.3);  //Wait for chip select pin
    }
        else
            PORTB.3 = 1;    //Switch of AD
     }
from using above code I am not able to read ADC values,nothing is printing.I have checked the signal before ADC using Oscilloscope i am getting signal. So i have tried to read values form AVdd and AIN1 of ADC.For that i have wrote code like this
Code:
    void Avdd(void)
    {
    //Set configuration register
    spi(0x10);
    spi(0x00);   //Bipolar, gain 1
    spi(0x07);   //AVDD monitor selected
    }

     void PressCh(void)
    {
    //Set configuration register
    spi(0x10);
    spi(0x27);   //Burnout current, bipolar, gain 128
    spi(0x10);   //BUF, AIN1 selected
    } 

    void SensorPower(char p)
    {
    if(p == 1)
        p = 0x10;
    else
        p = 0x00;
            
    //Set mode register
    spi(0x08);
    spi(p);      //PSW on/of
    spi(0x09);   //50 Hz rejection mode 80 dB
    }

    unsigned int AnalogVoltCalc(unsigned int raw)
    {
    return (unsigned int)(raw*0.21423-6988); 
    }

    unsigned int PressCalc(unsigned int raw)
    {
    //return (unsigned int)(raw*0.91701-30049);       //This gives pressure in psia
    return (unsigned int)(raw*1.0261-34117);       //This gives pressure in psia
    }

     void MeasureAll(void)
    {
    ChipSelectAd(1);
    SensorPower(1);
                
    Avdd();                             //Set adc to measure regulated voltage
    for (i = 0; i < 30000; i++);        //Give circuit time to settle
    //Wait(delay);
    for (i = 0; i < 3; i++)
        analogVoltRaw = ReadAd();
    
    PressCh();                          //Set adc to measure pressure
    for (i = 0; i < 30000; i++);        //Give circuit time to settle 
    //Wait(delay);    
    for (i = 0; i < 3; i++)
        pressRaw = ReadAd();
            
    SensorPower(0);
    ChipSelectAd(0);
    
    analogVolt = AnalogVoltCalc(analogVoltRaw);
    press = PressCalc(pressRaw);            
    }
even still i am not able to get these values. Anyone can suggest me what mistake i am doing and how to modify it. I have attached simple circuit connections please have a look at. I am little bit confusing about MISO and MOSI but they are looking correct.

Thanks in advance.
 

Attachments

  • img-X01172857-0001.pdf
    61.7 KB · Views: 78

I've noticed a couple of things in your code

Code:
data = (spi(0xFF)<<8);    //Read 8 most significant
The spi function return an 8bit char so the above code shifts left 8bits the char variable and then assigns it to a 16bit variable, the result will always be 0.
In order to actually shift the data to the left you need to typecast them first to a 16bit type variable.


Code:
unsigned int AnalogVoltCalc(unsigned int raw)
    {
    return (unsigned int)(raw*0.21423-6988); 
    }
Are you sure that this will give you what you want?
It may easily result in a negative number typecasted into an unsigned integer

- - - Updated - - -

I'm also not sure if you set properly the directions of the port pins

Code:
// I have initialized PORTB like this

PORTB = 0x00;
DDRB = 0xBF;

MISO should be an input
MOSI, SCK should be an output

I don't see that in your code.
 

1)
The spi function return an 8bit char so the above code shifts left 8bits the char variable and then assigns it to a 16bit variable, the result will always be 0.
In order to actually shift the data to the left you need to typecast them first to a 16bit type variable.
As you said I have to typecast from char to unsigned int. I am new to this so i have tried like this

data = ((unsigned char)spi(0xFF)<<8);

I am not sure is it right or not? I haven't checked output not yet with this but please correct me if it is wrong.

2)
Are you sure that this will give you what you want?

It may easily result in a negative number typecasted into an unsigned integer
I have used this function to calculate original value, I have called this function later. you can see in my code.

3)
MISO should be an input
MOSI, SCK should be an output

I don't see that in your code.

Coming to the port directions
I have set DDRB=0xBF=0b10111111

PB7=1(SCK), PB6=0(MISO), PB5=0(M0SI), PB4=0(WG_CS), PB3=0(ADC_CS), PB2=0(MUX_A0), PB1=0(MUX_A1), PB0=0(MUX_A2).

PORTB=0b00000000.
I think I have set as you said.

Thank you very much for your reply. please suggest me in type casting is it right or not? because i haven't checked output until now.
 
Last edited:

You are right about the port direction setting, my mistake.

The typecasting is not correct, unsigned char is still an 8bit variable type, you have to use an unsigned int
 

after type casting as you said char into unsigned int variable, still not working I am not able to read ADC values.

Code:
unsigned int ReadAd(void)
{
    unsigned int data;
      
     ChipSelectAd(1);
    //Read data
    CheckStatus();                                           //Wait for data ready in adc register
    spi(0x58);                                                //Place readinstruction in communication register
    data = ((unsigned int)spi(0xFF)<< 8));   //Read 8 most significant bits from data register
    data |=((unsigned int)spi(0xFF));         //Read 8 least significant bits from data register
    
    return data;
}

I have tried like this at least to print values.

Code:
unsigned int ReadAd(void)
{
    unsigned int data=20;
      
     ChipSelectAd(1);
    //Read data
    CheckStatus();                                           //Wait for data ready in adc register
    spi(0x58);                                                //Place readinstruction in communication register
   //data = ((unsigned int)spi(0xFF)<< 8));   //Read 8 most significant bits from data register
    //data |=((unsigned int)spi(0xFF));         //Read 8 least significant bits from data register
    
    return data;
}

I have assigned an integer value 20 to data variable and returning the same. but still nothing is reading from ADC.
 
Last edited:
Hi all,
I have tried differently this time but while trying to read ADC value i am getting either value"0" or value"255".
I have changed little modifications in the code.
Code:
    #define ADC_CS PORTB.3 
    #define WG_CS PORTB.4 
    #define MOSI PORTB.5 
    #define MISO PINB.6 
    #define SCK PORTB.7 

    #define ADC_CS_PIN PINB.3 
    #define WG_CS_PIN PINB.4 

    char spi(char data) 
     { 
       //Start transmision 
       SPDR = data; 
       //Wait for transmision complete 
       while(!(SPSR & 0x80)); 
       return SPDR; 
     } 


    //Sets the waveform generator output to given phase 
    void SetWGPhase(unsigned int phase) 
     { 
       SPCR = 0x5A; 
       WG_CS = 0; 
       while(WG_CS_PIN); 
       spi(0x20); 
       spi(0x00); 
       spi((char)((phase>>8)|0xC0));     //Load into phase register 0 
       spi((char)(phase & 0x00FF)); 
       WG_CS = 1; 
    } 

    unsigned int ReadAd(void) 
    { 
       unsigned int data; 
       ADC_CS = 1;
       //Read data 
       CheckStatus();         //Wait for data ready in 
                             adc register 
       spi(0x58);              //Place readinstruction 
                            in communication register 
       data = (spi(0xFF))<< 8)|spi(0xFF);    
           ADC_CS = 0;                  
         return data; 
    } 

unsigned char CheckStatus(void) 
    { 
       unsigned char adcStatus; 
           
            spi(0x40);
            adcStatus = spi(0xFF);
      return adcStatus;
    }
I have deleted "ChipSelect" function it is little bit confusing, I have selected ADC using ADC_CS pin. Now when i try to read values from ADC it is printing "0"when 0V at adc input and printing "255" when 0.6V at ADC input.
I am printing in this way
Code:
printf("Adc value = (percentage symbol)2d\n",ReadAd());
1)why it is printing only "0" or "255"?
2) why it is not printing "0" to "65535"?(16 bit ADC, and unsigned int data);

any help lease......

Thanks in advance.
 
ADC register setup problem

I am new to micro controller programming, I am using ATmega32-A micro controller. My problem is I am trying to read external ADC values, Initially I want set registers of ADC AD7798. Its not working, this my main problem. how to setup and read adc register setup? I have tried like this but it is not working.
Code:
    #define ADC_CS_PIN PINB.3
    #define ADC_CS PORTB.3
    #define MOSI PORTB.5
    #define MISO PINB.6
    #define SCK PORTB.7

    extern char adcStatus;
    extern char adcStatus1;
    extern char adcId;
    extern unsigned int adcMode;
    extern unsigned int adcConfig;

     char spi(char data)
      {
        //Start transmision
        SPDR = data;
        //Wait for transmision complete
        while(!(SPSR & 0x80));
        return SPDR;
       } 

       void ChipSelectAd(char s)
      {                            
          SPCR = 0x5D;  
    
          if(s == 1){
          PORTB.3 = 0;    //Switch on ADC
          while(PINB.3);  //Wait for chip select pin
        }
          else
          PORTB.3 = 1;    //Switch of AD
        }

      void setupAd(){
        ChipSelectAd(1); 
        //SPCR = 0x5D;   //I am calling chipselect so SPCR automatically called by using CS
        spi(0x10);  
        spi(0x07);        //set up communication register for configuration reg.
        spi(0x10);
        ChipSelectAd(0);

        ChipSelectAd(1);
        spi(0x08);  
        spi(0x00);        //set up communication register for mode reg.
        spi(0x0A);
        ChipSelectAd(0);
        } 
        
         //read setup registers.
    
    void ReadAdModeReg(void)
     {
      // SPCR = 0x5D;
        ChipSelectAd(1);
        spi(0x48);
        adcMode = spi(0xFF) << 8;
        adcMode |= spi(0xFF);      
        ChipSelectAd(0);
      }

     void ReadAdConfReg(void)
     {              
      //SPCR = 0x5D;
        ChipSelectAd(1);
        spi(0x50);
        adcConfig = spi(0xFF) << 8;
        adcConfig |= spi(0xFF);   
        ChipSelectAd(0);
      }
   
      //read adc
     unsigned int ReadAd(void)
      {
        unsigned int val;
        SPCR = 0x5D;
        CheckStatus();
        ChipSelectAd(1);
        //Read data
        spi(0x58);          //Place read instruction in communication register
        val = spi(0xFF)<<8;    //Read 8 most significant bits from data register
        val |=spi(0xFF);      //Read 8 least significant bits from data register
        ChipSelectAd(0);
        return val;                               
       }
 
      unsigned char CheckStatus(void)
        {
               char adcStatus; 
                  SPCR = 0x5D;
               ChipSelectAd(1);
             do{
               spi(0x40);
               adcStatus = spi(0xFF); 
                } while(!(adcStatus & 0x80));                                     
      
              ChipSelectAd(0);
              return adcStatus;
               }
I am tryin to read ADC registers using "printf" function like This

          ReadAdModeReg();
          printf("modereg:%d",adcMode); 
          ReadAdConfReg();
          printf("configreg:%d",adcConfig);
I have posted the whole code that to setup the ADC register, to read the ADC setup and read ADC values. I have some questions.
1) When I read 16-bit Config and mode registers using above code it is printing "modereeg=10"(decimal), configreg=255. but when power of/on the configreg also printing value"16". I think default. After that config reg is giving value"255" and mode reg is giving "10"(decimal). If i set any configuration also those are giving same values. My problem is why my register configuration is not working. or any faults in setup and reading ADC setup. why it is displaying "255", may be because of unsigned range? then how it will display configureg setup"0x0710". what can I have to do to set and check that value correctly.

My chip select and clock polarity's are ok. I am using SPI mode3 (I think right)for AD7798 adc. remaining register set up also exact. please suggest me if it is wrong.

Please help me in Register setup of ADC, or any faults with reading ADC setup, or Even with SPI function. I am not able to find where i am doing wrong. Please suggest me.

I have posted previously but If i edited there then it is becoming large code so i have posted clearly here. any suggestion appreciated.

Thanks in advance.
https://www.analog.com/static/imported-files/data_sheets/AD7798_7799.pdf
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top