Is it possible to use an AVR port as a variable which can be passed around?
For example
LED myLed(PORTA,7); //myLED hooked to PORTA, Pin 7
I would like to make LED be able to take any PORT / Pin combination, so I would rather not hard code it in.
Note that the PORTs are defined as:
#define PINA _SFR_IO8(0x00)
#define DDRA _SFR_IO8(0x01)
#define PORTA _SFR_IO8(0x02)
PORTA symbol resolves to (*(volatile uint8_t *)((0x02) + 0x20))
I believe this would allow me to do something like the following, but I am unsure whether I would need the volatile keyword or not, nor whether it will actually work as expected
class LED{
public:
LED(volatile uint8_t* port, uint8_t pin);
{
Port=port;
Pin=pin;
}
void write(bool val)
{
if(val) (*Port) |= 1 << Pin;
else (*Port) &= ~(1 << Pin);
}
private:
uint8_t Pin
volatile uint8_t* Port;
}
Finally, is there a way to set Port / Pin as an Output from the LED Constructor? This would involve finding the relative DDR# register for the Given PORT#. Can I assume &DDR# will always be &PORT#-1?
The register macros are basically pointers to the memory location, where the appropriate register resides, so yes, you can use uint8_t volatile *
. However, the compiler will not generate the most efficient code this way -- it will use indirect addressing instead of direct writes.
This is what I do instead, using avrlib.
#include <avrlib/porta.hpp>
#include <avrlib/pin.hpp>
using namespace avrlib;
typedef pin<porta, 4> led_pin;
Then you can use the led_pin
typedef, e.g.
led_pin::set();
This is how I did it, im not very experienced in AVR,
#include <avr/io.h>
void LED(volatile uint8_t* port, uint8_t pin)
{
// First set DDRx ; DDRx on ATmega32 is one address below port address
*(port -1) |= (1<< pin);
// Now set the pin high
*port |= (1<< pin);
}
int main(void)
{
LED(&PORTB,1);
LED(&PORTC,2);
LED(&PORTD,3);
while (1)
{
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With