如何定义指向端口地址的指针

时间:2013-09-24 02:56:11

标签: c microcontroller avr-gcc

我对struct有一点问题,并从atmega328p定义。

我有以下代码:

typedef struct {
    char port;
    unsigned char pin;
    unsigned long timestamp;
} BUTTONS;

BUTTONS button_1;
BUTTONS button_2;
BUTTONS button_3;

BUTTONS* button[BUTTONS_ID_COUNT] = {&button_1,&button_2,&button_3};

void Button_init(void){

    button[BUTTONS_ID_1]->port = PINB;
    button[BUTTONS_ID_1]->pin = PINB4;
    button[BUTTONS_ID_1]->timestamp = 0;
}

unsigned char Button_instantRead(int id){
    //return PINB & (1 << PINB4);
    return button[id]->port & (1 << button[id]->pin);
}

我想使用我的Button_instantRead()只能给它一个ID号来读取任何端口。我使用我的init函数来设置哪个引脚与哪个端口相关联。但由于某种原因,当我调用Button_instantRead()功能时,即使按下开关,我也不会得到1。

我使用注释行在我的主文件中尝试了我的配置,一切都运行得很好。

我在return行中做错了什么?

经过一些谷歌搜索后,我发现char可能不是引用端口的正确类型。我想我会更好地使用指向端口地址的第一个元素的指针,但我又不知道怎么做,也找不到答案。

2 个答案:

答案 0 :(得分:2)

我建议先查看PINB的定义。我发现了this link到功能点演示文稿,它似乎引用了正确的头文件。

值得注意的文件是:

  1. sfr_defs.h
  2. iom328p.h
  3. 您需要定义自己指向PINB的指针所需的所有信息。

    以下内容应该按照您的要求运行:

    typedef struct {
        volatile uint8_t * port;
        uint8_t pin;
        unsigned long timestamp;
    } BUTTONS;
    
    BUTTONS button_1;
    BUTTONS button_2;
    BUTTONS button_3;
    
    BUTTONS* button[BUTTONS_ID_COUNT] = {&button_1,&button_2,&button_3};
    
    void Button_init(void){
        button[BUTTONS_ID_1]->port = &PINB;
        button[BUTTONS_ID_1]->pin = PINB4;
        button[BUTTONS_ID_1]->timestamp = 0;
    }
    
    unsigned char Button_instantRead(int id){
        //return PINB & (1 << PINB4);
        return *(button[id]->port) & (1 << button[id]->pin);
    }
    

    请注意,端口是一个指针。

    修改

    我必须检查自己volatile结构成员的使用情况,发现this SO questionthis other SO question非常有趣。

    编辑2:

    如果您正在使用 gcc (我认为您不是因为它是AVR但我可能错了)您可以跳过找出PINB的确切类型的步骤是,并按如下方式声明您的结构:

    typedef struct {
        typeof(PINB)* port;
        uint8_t pin;
        unsigned long timestamp;
    };
    

    typeof operator是C语言的 gcc 扩展程序,因此您可能无法使用它,但了解它是很好的。

答案 1 :(得分:1)

PINB是否有波动?那不是实际读取的端口吗?如果是,则在Button_init中读取端口的值,而不是Button_instantRead

换句话说,button[id]->port包含在Button_init中读取时的端口值,而不是稍后可以使用的对PINB的引用。

小心:自从我做完atmega之后已经有好几年了。

你可以这样重新编码:

unsigned char Button_instantRead(int id){
    switch(id) {
        case ID_A: return PINA & (1 << button[id]->pin);
        case ID_B: return PINB & (1 << button[id]->pin);
        // etc
    }
}