将端口作为变量传递 - AVR

Passing a Port as a variable - AVR

本文关键字:AVR 变量      更新时间:2023-10-16

是否可以使用AVR端口作为可以传递的变量?

例如

LED myLed(PORTA,7);   //myLED hooked to PORTA, Pin 7

我想让LED能够接受任何端口/引脚组合,所以我宁愿不硬编码它。

请注意,端口定义为:

#define PINA  _SFR_IO8(0x00)
#define DDRA  _SFR_IO8(0x01)
#define PORTA _SFR_IO8(0x02)    

PORTA 符号解析为 (*(易失性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;
}

最后,有没有办法将端口/引脚设置为LED构造函数的输出?这将涉及查找给定端口#的相对DDR#寄存器。我可以假设 &DDR# 将始终为 &PORT#-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();

这就是我的做法,我在 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) 
    {
    }
}

端口只不过是 I/O 地址,所以您所要做的就是将 I/O 端口的地址传递给您的 LED 构造函数:

LED *light = new LED(&PORTA, 4);

为什么会这样?正如您已经提到的,PORTA 解析为指针的取消引用:

(*(volatile uint8_t *)((0x02) + 0x20))

因此,在前面添加运算符的地址会创建

&(*(volatile uint8_t *)((0x02) + 0x20))

可以简化为

(volatile uint8_t *)((0x02) + 0x20)