-5
\$\begingroup\$

I am using ATmega32-A microcontroller and CodeVisionAVR compiler. I am able to read values from an AD7798 external ADC successfully. I am also generating wave from with an AD9833 using SPI communication. I am passing the generated signal to a sensor as well as an ADG1408-EP analog multiplexer. I use the multiplexer to send either the waveform input to the sensor or the output of the sensor to the external ADC for conversion.

Here is a simplified schematic:

enter image description here

I have written the following code:

unsigned adc,RawData, WaveFreq,WavePhase;
unsigned int mux1,mux2;
float v1,v2,Analog_Voltage;


void runCom(void)
{
    switch(Command){

        case(INF):
            RawData=readADC();
             printf("ADC RawData:%d\r\n", RawData);
            Analog_Voltage = voltage(RawData);
             printf("Demodulator Voltage Level:%f [v]\r\n",Analog_Voltage);
            Command = 0;
            break;

        case(WGF):
            if(Param < 500)
                SetWGFreq(Param);
            WaveFreq = Param;
            Command = 0;
            break;

        case(MUXSEL):
            printf("MUX selection. ");
            selcase(WaveFreq);
            Command = 0;
            break;
        default:
            Command = 0;
            break;
    }
}

void selcase(unsigned int arg)
{
    unsigned char c;
    c = getchar();

    switch(c){

        case '1':
            PORTB=0x00;
            SetWGFreq(arg);
            Delay(1000);
            mux1 = readADC();
            printf("muxchanel 1 ADC RawData:%d\r\n",mux1);
            v1 = voltage(mux1);
            printf("Muxchanel 1 Demodulator Voltage Level:%f [v]\r\n",v1);
            Command = 0;
            break;

        case '2':
            PORTB=0x04;
            SetWGFreq(arg);
            Delay(1000);
            mux2 = readADC();
            printf("muxchanel 2 ADC RawData:%d\r\n",mux2);
            v2 = voltage(mux2);
            printf("Muxchanel 2 Demodulator Voltage Level:%f [v]\r\n",v2);
            Command = 0;
            break;
        default:
            Command = 0;
            break;
    }
}

From the above code I am able to read a converted value from the ADC correctly. But the problem is when I switch the multiplexer to channel 2 and read the ADC value after I've already read the ADC value of channel 1, I read back the same value I received for channel 1.

If I read the ADC value of channel 2 twice in a row, the second time I read it, it is the correct value.

I have tried to print readADC value in the INF command. It was printing exactly, no need to enter case twice. In INF command it was giving exactly the right value when I change the multiplexer channel and checked with the INF command. Values are changing so quickly when I enter the multiplexer selection.

The only problem is in the nested switch case I am trying to print ADC values but I have to enter the case twice to get the correct value. I have tried with delay function also but still the problem is same.

Why do I need to perform two reads to obtain the correct multiplexer channel conversion result?

\$\endgroup\$
  • \$\begingroup\$ Nthing to do with electronic design. \$\endgroup\$ – Leon Heller Oct 23 '12 at 20:06
  • 2
    \$\begingroup\$ @LeonHeller This is an embedded software question dealing with interfacing to an external ADC. I thought it was agreed that such a question was on topic: meta.electronics.stackexchange.com/questions/2457/… \$\endgroup\$ – embedded.kyle Oct 23 '12 at 20:36
  • \$\begingroup\$ What is PORTB for? If you have the input going to one ADC channel and the output going to another ADC channel, you would select which channel is returned via SPI. Can you post a schematic of how these devices are connected together? \$\endgroup\$ – embedded.kyle Oct 23 '12 at 20:58
  • 2
    \$\begingroup\$ Leon I notice you have a unique perspective on the bandwidth of the actual spectrum of what the industry defines as Electronic Design. Software/Hardware/Communication You may be interested in this free trade journal edn.com Note all the design centers of interest under RSS: DESIGN CENTERS \$\endgroup\$ – Tony Stewart Sunnyskyguy EE75 Oct 24 '12 at 0:11
  • \$\begingroup\$ @embedded.kyle PORTB is to select MUX channel. I am changing only PB.0, PB.1, PB.2 for selecting MUX channel. I have added simple schematic can you see that. \$\endgroup\$ – verendra Oct 24 '12 at 8:39
0
\$\begingroup\$

I think your problem is with this line:

while ((statusreg & 0x80) != 0);

I'm honestly not sure how that is working at all. It may be getting optimized out.

What that line says is: "while this bit in this variable is set, do nothing". But you're never updating the variable. So if it was set when it entered, it should loop forever. If it was cleared when it was entered, it should drop right through. What you want is something more like this:

unsigned int readADC(void)
{
    init_io();

    AD7798_16(0x10, 0x0010);
    value = AD7798_16(0x50, 0xFFFF);
    while ((read_status() & 0x80) != 0)
    {
        #asm("nop");              //Or however you call assembly nop in CodeVision
    }
    adc = AD7798_16(0x58, 0xFFFF);
    return adc;
}

unsigned int read_status(void)
{
    return AD7798_8(0x40, 0xFF);;
}

That way you'll continuously read the status register until the conversion is ready. The nop should prevent the compiler from optimizing out the loop which it seems like it's doing.

You might also want to change to using Single-Conversion Mode on your ADC. That should help ensure that you start and complete a new conversion each time you switch channels. So it should help avoid reading previous conversion results.

\$\endgroup\$
  • \$\begingroup\$ Yes may be your point of view is also correct but, I have resolved it by increasing delay. My delay function is wrong so I have checked with break points in AVR Studio 6. I have used built in function for delay. Now it is working. I am going to test you way also. \$\endgroup\$ – verendra Oct 25 '12 at 7:30
0
\$\begingroup\$

The solution for above post is, i have to set proper delay between mux selection and ADC read. The delay function that i have used in the above code is not working. Now i have changed it. Its working.

I have changed the delay like

delay_ms(100);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.