- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi all,
I have a periodic fixed timer (100ms) interrupt that seems to work fine but the main code is flipping the output pin twice. I basically want to show a pattern of LED (in my BeMicro MAX10) like this every second, low means LED on, there are 8 LEDs: 11100111 one second delay and next 11011011 one second delay and next 10111101 one second delay and next 01111110 one second delay and go to first I'm using the modulus operator (%) to change the pattern but it triggers (mostly) twice. Like: 11100111 one second delay and next 11011011 no delay 10111101 no delay 01111110 one second delay and go to first The picture attached shows when the isr executes by toggling an output pin (yellow trace). The blue trace is when the code inside the if(ticks % 10==0 && flag==1) executes. I'm pretty new at FPGAs and Nios. BTW I'm using "Reduced device drivers" and "Small C library" for the BSP. What Am I missing? --- Quote Start --- //=========== Global variables ==================================== volatile unsigned int ticks=0; volatile unsigned int flag=0; volatile unsigned char port0Val=0; //=========== main() Function ====================================== int main() { char led_patern[4]={0b11100111,0b11011011,0b10111101,0b01111110}; int i=1; alt_ic_isr_register(TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID, TIMER_0_IRQ, timer_isr, 0, 0); //timer registers are 16-bits wide IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 1); //interrupt enable // PORT0 is 5 bits wide // PORT0 bit 0 = PIN_B1, BeMicro J5-2 // PORT0 bit 1 = PIN_A2, BeMicro J5-4 // PORT0 bit 2 = PIN_A3, BeMicro J5-5 // PORT0 bit 3 = PIN_A4, BeMicro J5-6 // PORT0 bit 4 = PIN_A5, BeMicro J5-10 IOWR(PORT0_BASE,5,0b11111); //5=outclear - ALL LOW //IOWR(PORT0_BASE,4,0b11111); //4=outset - ALL HIGH while(1) { if(ticks % 10==0 && flag==1) { port0Val = IORD(PORT0_BASE,0); //toggle port0 pin 2 -----> BLUE TRACE <-------- if((port0Val & 0b00100)==0b00100) IOWR(PORT0_BASE,5,0b00100); //5=outclear else IOWR(PORT0_BASE,4,0b00100); //4=outset IOWR(LEDS_BASE,0,*(led_patern+i)); //a low value turns LED on i++; if(i>3) i=0; flag=0; } } return 0; } //============== Interrupt Service Function =========================== void timer_isr() { port0Val = IORD(PORT0_BASE,0); //toggle port0 pin 0 -----> YELLOW TRACE <-------- if((port0Val & 0b00001)==1) IOWR(PORT0_BASE,5,0b00001); //5=outclear register, 0x01=0b00001 else IOWR(PORT0_BASE,4,0b00001); //4=outset register, 0x01=0b00001 ticks++; flag=1; IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0); // clear TimeOut flag } --- Quote End ---Link Copied
1 Reply
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The flaw is with the condition if(ticks % 10==0 && flag==1)
Infact your code basically loops on this instruction. So, you have a rough 50% probabilty that the irq triggers between the two ANDed conditions. When you find both conditions true you toggle the blue trace. At this point tick%10==0 stays true until the next irq; but if irq triggers just after you evaluated tick and before you evaluate flag, at the end you would again have the whole if conditional true and would toggle the output one more time. To solve the problem, put the tick%10 condition inside the isr and set flag according to it.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page