1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

What code can be acceptable on ATmega32A ?

Discussion in 'AVR' started by Georg, Nov 3, 2012.

  1. Georg

    Georg New Member

    Joined:
    Sep 30, 2012
    Messages:
    27
    Likes:
    0
    Dear friends! Please, help me to solve one trouble.

    I have connected R-2R DAC to ATmega32A on port P.
    Digit capacity of DAC is 8 bits, so far as all of outputs of P are attach to R-2R DAC .

    This code shall assign on port P:
    PORTP=00000001;
    PORTP=00000010;
    PORTP=00000100;
    PORTP=00001000;
    etc.
    PORTP=11111111;


    This code manage R-2R DAC which forms output voltage.
    Output voltage is minimum when code is 00000001.
    Output voltage is maximum when code is 11111111.


    My question: How to write the cycle for such code?
    P.S Write the code sorting all importances from 00000001 before 11111111 is not good.
     
    Last edited: Nov 3, 2012
  2. wkrug

    wkrug Active Member

    Joined:
    May 30, 2010
    Messages:
    271
    Likes:
    29
    Location:
    Germany
    You can built a for loop, that adresses a Value Table.

    flash unsigned char uc_table[256]={0x01,0x03,0x04,...0xFD};
    volatile unsigned char uc_count=0;

    for(uc_count=0,uc_count<=255,uc_count++)
    {
    PORTP=uc_table[uc_count];
    };

    So you can generate every periodic Waveform that was pre calculated and stored into the table variable.

    To change the Frequency, you can put it into a counter interrupt and count up the uc_count variable by incrementation ( uc_count++; ).

    ISR (TIM0_OVF_INT)
    {
    ui_loopcounter++;
    if(ui_loopcounter>ui_time)
    {
    PORTP=uc_table[uc_count];
    uc_count++;
    ui_loopcounter=0;
    };
    };

    The Variable definations differ a little bit, depeding from the used Compiler.

    EDIT!
    I've corrected the Value 0x253 to 0xFD
     
    Last edited: Nov 7, 2012
  3. kubeek

    kubeek Well-Known Member

    Joined:
    Mar 11, 2006
    Messages:
    1,486
    Likes:
    185
    Location:
    Prague, Czechia (not Chechnya)
    ONLINE
    Or you could make a function that does that without a large chunk of code, but this depends on how fast do you need the result. Calculating the result will be a few clock cycles slower than using a lookup table, but lookup table wastes more ram and possibly code space.
    For example:
    Code (text):
    if(i<7)PORTP=(1<<i);
    else PORTP=0xff;
    But anyway, since when does any atmega have a port P? Also, are you sure you want the output exactly as you written in the first post?
     
    Last edited: Nov 4, 2012
    • Like Like x 1
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Georg

    Georg New Member

    Joined:
    Sep 30, 2012
    Messages:
    27
    Likes:
    0

    Yes, I have done the misprint. I meant the A port of ATmega32.)

    wkrug, what means the 0x01 ? (I'm beginner in microcontroller programming and have some difficult)
    Should code be this ?

    #include <stdio.h>;
    int main ();
    int values[255];
    for(i=0;i<256;i++);
    {
    values=i
    }
    for(j=0;j<256;j++);
    {
    delay_ms(...);
    PORTA=values[j];
    }
     
  6. kubeek

    kubeek Well-Known Member

    Joined:
    Mar 11, 2006
    Messages:
    1,486
    Likes:
    185
    Location:
    Prague, Czechia (not Chechnya)
    ONLINE
    0xff for example is a hexadecimal notation of nuber 255. Wkrug made a mistake, the series should obviously end in 0xff or 255, but not 0x255 which is 597.

    Georg, do you notice that series 0b00000001, 0b00000010, 0b00000100,0b00010000... is not equivalent to 1,2,3,4... but rather 1,2,4,8... ? (the b in 0b01110111 stands for binary notation, as oposed to hexadecimal)
    And also from your first post it seems you want to have 0b11111111 right after 0b10000000, thus only 9 values total?

    ..Also in the previous post you have a mistake, you should have there int values[256], since the index goes from 0 to 255, so you have 256 writes. If you do that mistake in a microcontroller you will almost certainly overwrite some other variable.
     
    Last edited: Nov 5, 2012
  7. Georg

    Georg New Member

    Joined:
    Sep 30, 2012
    Messages:
    27
    Likes:
    0
    kubeek, thank you for your explanation. It will be of great value to me. I will continue in this direction.
     
  8. wkrug

    wkrug Active Member

    Joined:
    May 30, 2010
    Messages:
    271
    Likes:
    29
    Location:
    Germany
    You only have an 8 bit D/A Converter ( R2R Network ) so there are 8 bit variables large enough in the Lookup table.

    The Idea is to pre calculate the wave form and store that values into a lookup table.

    So you can generate different waveforms only by switching between different tables.

    When using a 8 Bit variable as pointer of the values into the table, it overflows automaticly when the value exceeds 255. The Pointer is then 0 again.

    To get a faster Output you can shorten the Lookup table to 64 or 128Byte, but that degrades the output signal quality.

    To differ the output frequency, You only have to change the time between the reading out's of the table.

    To get independency of other tasks of the controller, I'll suggest you to use a periodic interrupt to change the values of the lookup table.

    To get that easy you can use a counter variable into the timer overflow interrupt, or a comparematch interrupt with CTC ( Clear Timer on Comparematch ) function.

    To decision what the best parameters and method are, You have to know what is the lowest and the highest wished Output Frequency.

    I've done this with an 2kHz Sine Signal and an 64Byte lookup table that AM modulates a DDS Chip from Analog Devices via SPI.
    It can generate Sine Triangle and Rectangular waves, only by switching between the different tables.

    P.S.
    0x255 was wrong. I've corrected this to 0xFF.
     
    Last edited: Nov 8, 2012
  9. Mike odom

    Mike odom Active Member

    Joined:
    Feb 21, 2010
    Messages:
    670
    Likes:
    52
    Location:
    Kansas City, KS, U.S.A.
    shortening your lookup table to 64 or 128 will not increase your lookup speed, as the fastest way to use a lookup table is to set your index register to the table_base and then add the offset (pointer) to the index register. It doesn't matter if you're adding 0-63, 0-127, or 0-255, the add commands will take the same amount of time.
     
  10. wkrug

    wkrug Active Member

    Joined:
    May 30, 2010
    Messages:
    271
    Likes:
    29
    Location:
    Germany
    That's right, but it increases the output frequency, because a lower count of values must be adressed.

    That's right to, but when make steps of 2, You can also shorten the lookup table, because only every 2'nd value will be adressed.
    And the table will be shorter, that saves memory space.

    Another possible Way is to use an DDS frequency generation.
    There will be a very huge value table. The output frequency setting will be done by change the increments of the pointer variable.
    But when I would do that solution, it is better to use a dedicated DDS Chip, because the quality and frequency of the output signal increases and the load of the Controller go down. It cost's money, of course.
     
    Last edited: Nov 12, 2012
  11. Georg

    Georg New Member

    Joined:
    Sep 30, 2012
    Messages:
    27
    Likes:
    0
    Dear wkrug and Mike odom your discussion and proposals are interesting, but output code switching is not so much exigent in this case.
    Your consideration of above mentioned problem is advanced aerobatics in comparison with my skills now !)))
     
  12. wkrug

    wkrug Active Member

    Joined:
    May 30, 2010
    Messages:
    271
    Likes:
    29
    Location:
    Germany
    To use a lookup table is one of the easyest thing's in controller programming.
    You make a table, the values could be precalculated in EXCEL.
    Than the calculated Values e.g. for a sine would be taken into a variable.
    unsigned char uc_sine[256]={0x00,0x01,...0xFF};
    unsigned char uc_pointer=0;

    Now when make a periodic reading with increments of a pointer from that table and put the Values to Your R2R Network, then occours there a sine Wave.

    while(1)
    {
    PORTC=uc_sine[uc_pointer]; //Read out the actual Value for the R2R Network
    uc_pointer++; //Increment Pointer to address the next value in table
    delay_us(20); //Delay function to slow down the output frequency. Higher values give lower frequency
    }

    This little part of code is the whole generation loop!

    The Problem is, when other tasks are running while outputting the wished wave, the output frequency will not be constant and the output waveform has dissortion.
    So you had to make a function, that does not depend from the tasks in main loop.
    To do that, You can write an interrupt function that interrupts the actual main loop to change to the next value in the table and put it out to R2R Network.
    Timer Overflow or Timer Comparematch Interrupts are ideal for such a solution.

    Try it out and put an Oscilloscope at the Output of the R2R Network. You would see there will occour a Wave.
     
    Last edited: Nov 14, 2012

Share This Page