Можно ли использовать порт AVR в качестве переменной, которую можно передавать?
Например
LED myLed(PORTA,7); //myLED hooked to PORTA, Pin 7
Я хотел бы, чтобы светодиод мог принимать любую комбинацию PORT / Pin, поэтому я бы не стал жестко кодировать ее.
Обратите внимание, что порты определены как:
#define PINA _SFR_IO8(0x00)
#define DDRA _SFR_IO8(0x01)
#define PORTA _SFR_IO8(0x02)
Символ PORTA разрешается в (* (volatile uint8_t *) ((0x02) + 0x20))
Я считаю, что это позволило бы мне сделать что-то вроде следующего, но я не уверен, понадобится ли мне ключевое слово volatile или нет, и будет ли оно работать так, как ожидалось
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;
}
Наконец, есть ли способ установить порт / вывод как выход из конструктора светодиодов?
Это будет связано с поиском относительного регистра DDR # для данного номера порта.
Могу ли я предположить &DDR # всегда будет &ПОРТ # -1?
Макросы регистров в основном являются указателями на область памяти, где находится соответствующий регистр, так что да, вы можете использовать uint8_t volatile *
, Однако компилятор не будет генерировать наиболее эффективный код таким способом — он будет использовать косвенную адресацию вместо прямой записи.
Это то, что я делаю вместо этого, используя avrlib.
#include <avrlib/porta.hpp>
#include <avrlib/pin.hpp>
using namespace avrlib;
typedef pin<porta, 4> led_pin;
Тогда вы можете использовать led_pin
typedef, например
led_pin::set();
Порты — это не что иное, как адреса ввода / вывода, поэтому все, что вам нужно сделать, это передать адрес порта ввода / вывода вашему конструктору LED:
LED *light = new LED(&PORTA, 4);
Почему это работает? PORTA разрешает, как вы уже упоминали, разыменование указателя:
(*(volatile uint8_t *)((0x02) + 0x20))
Таким образом, добавление адреса оператора впереди создает
&(*(volatile uint8_t *)((0x02) + 0x20))
который может быть упрощен до
(volatile uint8_t *)((0x02) + 0x20)