avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] altering array variable and interrupts


From: Philipp Burch
Subject: Re: [avr-gcc-list] altering array variable and interrupts
Date: Wed, 16 Jan 2008 17:18:02 +0100
User-agent: Thunderbird 2.0.0.9 (Windows/20071031)

Hi,

since I don't know your hardware, I can't tell you exactly how your code must look. But if I guess right, you want to have the digit-signal output on PORTD and need a strobe Signal on Pin PC3 to let the counter (74HC161) do a step (Sounds like a multiplexed display with 7-segment-digits). The code for this is quite simple and does not need any delayloop, since the counter has a minimum pulse width of a few nanoseconds, so it is enough to enable the pin, do a "nop" and disable it again (It might even work without the "nop", but I don't know, how the signal then really looks like...). PROGMEM is an attribute to tell the compiler/linker to place a variable in (read-only) FLASH memory instead of RAM. Refer to the avr-libc-documentation for details, it's quite good explained (Keyphrase: "Data in program memory").
In my opinion, your code should be something like this (untested):

#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdint.h>
#include <avr/pgmspace.h>

#define MAX_LEDS 16
#define A 1
#define B 2
#define C 4
#define D 8
#define E 16
#define F 32
#define G 64
#define DP 128

#define Digit_0 (B + C + D + E + F + A)
#define Digit_1 (B + C)
#define Digit_2 (A + B + G + E + D)
#define Digit_3 (A + B + G + C + D)
#define Digit_4 (F + G + B + C)
#define Digit_5 (A + F + G + C + D)
#define Digit_6 (F + E + D + C + G)
#define Digit_7 (A + B + C)
#define Digit_8 (A + B + C + D + E + F + G)
#define Digit_9 (A + B + C + D + F + G)
#define Digit_A (A + B + C + E + F + G)
#define Digit_B (A + B + C + D + E + F + G + DP)
#define Digit_C (A + F + E + D)
#define Digit_D (A + B + C + D + E + F + DP)
#define Digit_E (A + D + E + F + G)
#define Digit_F (A + E + F + G)
#define Digit_G (A + C + D + E + F + G + DP)
#define Digit_H (B + C + E + F + G)
#define Digit_DP DP

volatile uint8_t Display[MAX_LEDS];
uint8_t Characters[] PROGMEM = {Digit_0, Digit_1, Digit_2, Digit_3,
                               Digit_4, Digit_5, Digit_6, Digit_7,
                               Digit_8, Digit_9, Digit_A, Digit_B,
                               Digit_C, Digit_D, Digit_E, Digit_F};

ISR(TIMER0_OVF_vect){
   static uint8_t dig;

  PORTD = pgm_read_byte(&Characters[Display[dig] & 0x0f]);
  PORTC &= _BV(PC3);  //Strobe
  asm("nop");
  PORTC |= _BV(PC3);

  if (++dig == MAX_LEDS) dig = 0;
}


int main(){

        //PORTD output
        DDRD = 0xFF;
        PORTD = 0xFE;
        //PORTC PC3 output and LOW initially
        DDRC = (1 << PC3);
        PORTC = (0 << PC3);
        //setup timer, played with different prescallers
        TCCR0 = (1 << CS00);// | (1 << CS02);
        TIFR = (1 << TOV0);
        TIMSK = (1 << TOIE0);
        //setup array to bahe progressive values
        int j;
        for (j = 0; j < 16; ++j) {
                Display[j] = j;
        }
        //enable interrupts
        sei();

        //try to change first led value
        Display[0] = 8;

        while (1){
                }
        return 0;
}


That's about how I would do that.
I've not checked your timer initialization.

Philipp
Hi,
Thanks for pointing out reply issue, I didn't notice. I'm not sure what do you mean about PROGMEM, I have declarations volatile uint8_t CurrLed;
volatile uint8_t Leds[MAX_LEDS];
maybe I am wrong but volatile declaration shouldn't tell the compiler to fetch value each time it's access it? I think you are right about second statement, the interrupt uses too much time and the execution of the next instruction never happens. Placing a CLI does not stop the display. I think I have to rewrite the interrupt to match the HCT 161 transitions. Regarding previous advice about dropping character generation at the runtime, it is necesary, because the CPU will do just led display, nothing else. Data comes via TWI and it's not formatted, format is position and then value, for example 0, 0 means first digit must display 0, hence need adjustement to diplay that value as led digits. If you have a better proposal I'll be glad to hear it. Cornel

----- Original Message ----
From: Philipp Burch <address@hidden>
To: address@hidden
Sent: Tuesday, January 15, 2008 10:41:58 PM
Subject: Re: [avr-gcc-list] altering array variable and interrupts

Hi,

ok, if you need to modify the characters, then you can just declare the
mentioned array volatile and not PROGMEM.
What do you mean with "I don't think this really completely stops
execution"? Have you tested it, or are you just guessing? What's the
interval of the interrupt, how is F_CPU defined and do you use
optimization? There's an easy way to check if the program continues:
Place a cli(); instruction right before your mainloop. If it doesn't
hang in the interrupt, the program should then just run inside the
infinite loop and hence not do anything with the controllers pins, so
you can easy check.

btw: You should reply to "address@hidden <mailto:address@hidden>", or I'm the only
recipient of the mail.

Philipp
> Hi,
> > Thanks for reply. I do want to modify that array of char not to
> prevent changing them. Basicaly each time interrupt occurs it should
> read the array and output values, and I will change values often. I
> know delay inside interrupt is not a good tactic but I just didn't
> have time to compute the right low-to-high transaction time in CPU
> clocks to match the 74hc161 4-bit counter logical diagaram I clock
> from interrupt; hence I used a delay. I don't think this really
> completely stops execution of the program so the value never change.
> > Cornel
>
> ----- Original Message ----
> From: Philipp Burch <address@hidden <mailto:address@hidden>>
> To: address@hidden <mailto:address@hidden>
> Sent: Tuesday, January 15, 2008 8:24:17 PM
> Subject: Re: [avr-gcc-list] altering array variable and interrupts
>
> Hi,
>
> I guess, your ISR takes too long. Delayloops in ISRs are very, very bad
> style, because they block the whole CPU. I suppose, the Interrupt comes
> more often than every 3ms, so there is no way for the AVR to execute any
> code outside the ISR. You should rewrite the complete program, there are
> many unnecessary things, such as character generation at runtime. Just
> declare a PROGMEM array with all your digits and read from it with
> pgm_read_byte() (From avr/pgmspace.h, check the manual of avr-libc),
> that saves RAM and initialization work. And it prevents the characters
> from getting modified (Or do you really need this "feature"?).
>
> Philipp
> > sorry I forgot to put url: http://rafb.net/p/fxrljj42.html
> >
> >



_______________________________________________
AVR-GCC-list mailing list
address@hidden <mailto:address@hidden>
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


------------------------------------------------------------------------
Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now. <http://us.rd.yahoo.com/evt=51733/*http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ%20>
------------------------------------------------------------------------

_______________________________________________
AVR-GCC-list mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list





reply via email to

[Prev in Thread] Current Thread [Next in Thread]