Go Down

Topic: Trying to scan rows with port manipulation MEGA256 (Read 1 time) previous topic - next topic

Deuplonicus

Hi all! I am learning and trying my best to find out how to efficiently scan rows on and off for a large matrix, 8 x 96 LED's.

For some reason I cannot for the life of me get any port bit manipulation working, I've tried every port to no avail. Any suggestions?

Code: [Select]
/* Beginings of LED matrix  controlled by arduino mega 2560*/
#include "avr/io.h"
#include "avr/pgmspace.h"
#include "avr/interrupt.h"

/*******************************************************************************
************************** Global Variables ************************************
*******************************************************************************/
volatile uint8_t Row;                        //  DO NOT MODIFY!

/*********************************************************************************
************************ Port Settings *******************************************
*********************************************************************************/



//ROW SCANNER INTERRUPT SERVICE ROUTINE
ISR(TIMER1_OVF_vect) {
 cli();
 TCNT1=0xFD62; // set initial value to remove time error (16bit counter register) FBEF=60?
 Row++;
 if (Row == 8)
             Row = 0; // fixes overlap of transferByte counter
 if (Row == 0)
             PORTD = B10000000; // Turns on row 1
 if (Row == 1)
             PORTD = B01000000; // Turns on row 2
 if (Row == 2)
             PORTD = B00100000; // Turns on row 3
 if (Row == 3)
             PORTD = B00010000; // Turns on row 4
 if (Row == 4)
             PORTD = B00001000; // Turns on row 5
 if (Row == 5)
             PORTD = B00000100; // Turns on row 6
 if (Row == 6)
             PORTD = B00000010; // Turns on row 7
 if (Row == 7)
             PORTD = B00000001; // Turns on row 8  
sei();
}


void setup()
{
 DDRD = B11111111; // sets Arduino pins 0-7 as outputs
 Row = 0; //Preparing volatiles
 TIMSK1=0x01; // enabled global and timer overflow interrupt;
 TCCR1A = 0x00; // normal operation page 148 (mode0);
 TCNT1=0xFD62; // set initial value to remove time error (16bit counter register)
 TCCR1B = 0x04; // start timer/ set clock
 pinMode(8, OUTPUT);
 pinMode(9, OUTPUT);
 pinMode(10, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(12, OUTPUT);

}
int main()
{
setup();

 
}

void loop()
{
 
 digitalWrite(11, LOW);  //SET OUTPUT ENABLE ON
 digitalWrite(10, HIGH);   // set Strobe/Latch LOW
 digitalWrite(8, HIGH);   // set clock LOW
 digitalWrite(9, HIGH);   // set the data output high
 digitalWrite(8, LOW);   // set clock LOW
 digitalWrite(8, HIGH);   // set the clock HIGH
 delay(200);              // wait for a second
 digitalWrite(8, LOW);   // set clock LOW
 digitalWrite(8, HIGH);   // set the clock HIGH
 delay(200);              // wait for a second
 digitalWrite(9, LOW);   // set the data output
 digitalWrite(8, LOW);   // set clock LOW
 digitalWrite(8, HIGH);   // set the clock HIGH
 delay(200);              // wait for a second
 digitalWrite(8, LOW);   // set clock LOW
 digitalWrite(8, HIGH);   // set the clock HIGH
 delay(200);              // wait for a second
}

Coding Badly

Code: [Select]

// [glow]Use less-then and greater-then so your future self (or anyone else using your code) knows that these are system headers...[/glow]

#include [glow]<[/glow]avr/io.h[glow]>[/glow]

...

//ROW SCANNER INTERRUPT SERVICE ROUTINE
ISR(TIMER1_OVF_vect) {
// [glow]Remove the following line.  Enabling / disabling interrupts in an interrupt service routine is a bad idea.[/glow]
//  cli();
...
// [glow]Remove the following line.  Enabling / disabling interrupts in an interrupt service routine is a bad idea.[/glow]
//sei();
}


// [glow]The pins should be configured before enabling the timer...[/glow]

void setup()
{
 DDRD = B11111111; // sets Arduino pins 0-7 as outputs
 Row = 0; //Preparing volatiles
 pinMode(8, OUTPUT);
 pinMode(9, OUTPUT);
 pinMode(10, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(12, OUTPUT);
[glow]
 TIMSK1=0x01; // enabled global and timer overflow interrupt;
 TCCR1A = 0x00; // normal operation page 148 (mode0);
 TCNT1=0xFD62; // set initial value to remove time error (16bit counter register)
 TCCR1B = 0x04; // start timer/ set clock
[/glow]
}

// [glow]Completely remove main...[/glow]

/*
int main()
{
setup();
}
*/

PaulS

Code: [Select]
 if (Row == 0)
             PORTD = B10000000; // Turns on row 1
 if (Row == 1)
             PORTD = B01000000; // Turns on row 2
 if (Row == 2)
             PORTD = B00100000; // Turns on row 3
 if (Row == 3)
             PORTD = B00010000; // Turns on row 4
 if (Row == 4)
             PORTD = B00001000; // Turns on row 5
 if (Row == 5)
             PORTD = B00000100; // Turns on row 6
 if (Row == 6)
             PORTD = B00000010; // Turns on row 7
 if (Row == 7)
             PORTD = B00000001; // Turns on row 8

How many of these if statements can be true on any one execution of the function? As written, each statement needs to be evaluated. If you change this to if/else if/else if/.../else, then when the first one evaluates to true, the rest can be skipped.

Since you are doing direct port manipulation, in an ISR, presumably speed is important. Wasting time evaluating 7 if statements is not in keeping with the speed theme.

Deuplonicus

Thanks for the advice everyone. I was curious why some tutorials in the arduino library show "" and some show <> for the system headers.

Please forgive my crummy code, as I am just now converting over from propeller basic stamps.  

PaulS, Yes you are correct about my wasting of those commands, but at the time, and still possibly now, I couldn't even get port manipulation working so I threw in some random code to do the switching.

Basically the port manipulation is to turn on one pin, then turn it off and turn on the next pin, and do this in a loop one change per ISR call, effectively creating a common cathode duty cycle of 12.5% per pin. Those pins are connected to n-mosfets.

I would love to learn a better way than if-then statements, in fact I will likely be Forced to in order to keep the program running fast. Would you suggest a better way? or point me in the right direction? I am good at searching, but alas searching returns bad coders and good coders, I have yet to be that good at knowing what I'm looking at.

PaulS

#4
Dec 23, 2010, 03:43 pm Last Edit: Dec 23, 2010, 03:46 pm by PaulS Reason: 1
Quote
I would love to learn a better way than if-then statements, in fact I will likely be Forced to in order to keep the program running fast.

If you look at the value you are setting PORTD to, you see that there is an inverse relationship between the value and the value in Row. You could do this
Code: [Select]
byte portdVal = 0;
bitSet(portdVal, (8-Row));
PORTD = portdVal;

and skip all the if tests.

You could even learn about bit shifting, and combine all three statements into one.

Go Up