assembly 如何使用Raspberry Pi皮科读取ARM中的GPIO输入引脚?

ftf50wuq  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(91)

我开始学习汇编语言和ARM使用树莓派皮科。
我甚至一直在遵循这本书RP2040 Assembly Language programming,但没有说明如何读取输入引脚只使用汇编。
以下是我的设置:我有一个按钮,发送3,3V时,不按下和0V时,按下.
我希望能够读取不同的状态,这已经使用GPIO引脚,但尽管看了功能的控制器(我几乎不明白,因为这是我第一次处理它),我不知道我在做什么有意义。
下面是我的代码:

led_loop:
    @  set the control for the push
    ldr r0, =ctrl2      @  control register for GPIO1 0x40014008
    mov r1, #5          @  Function 5, select SIO for GPIO1 2.19.2
    str r1, [r0]        @  Store function_5 in GPIO1 control register
@ shifts over "1" the number of bits of GPIO pin
    mov r2, #1          @  load a 1 into register 1
    lsl r2, r2, #1      @  move the bit over to align with GPIO1
    ldr r0, =sio_base   @  SIO base 0xd0000000
    str r1, [r0, #0x00000004]   @  0x004 GPIO input enable
    ldr r0, =helloworld
    BL printf
    b led_loop          @  do the loop again

.data
    .align 4
helloworld: .asciz "Hello World %d\n"

到目前为止,我试着咨询过编辑,但我没有足够的知识来认识到我所做的是写还是错了。

xoshrz7s

xoshrz7s1#

您正在正确的轨道上,但似乎使用了错误的寄存器值或以错误的方式使用它们。你有一个printf,所以这是非常奇怪的,这意味着你有一吨,吨,更多的代码,这可能会或可能不会有帮助。
这是C和使用原来的pico上的led,这不确定是否是这种情况了。

void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void DELAY ( unsigned int );

#define RESETS_BASE                 0x4000C000

#define RESETS_RESET_RW             (RESETS_BASE+0x0+0x0000)
#define RESETS_RESET_XOR            (RESETS_BASE+0x0+0x1000)
#define RESETS_RESET_SET            (RESETS_BASE+0x0+0x2000)
#define RESETS_RESET_CLR            (RESETS_BASE+0x0+0x3000)

#define RESETS_RESET_DONE_RW        (RESETS_BASE+0x8+0x0000)
#define RESETS_RESET_DONE_XOR       (RESETS_BASE+0x8+0x1000)
#define RESETS_RESET_DONE_SET       (RESETS_BASE+0x8+0x2000)
#define RESETS_RESET_DONE_CLR       (RESETS_BASE+0x8+0x3000)

#define SIO_BASE                    0xD0000000

#define SIO_GPIO_IN                 (SIO_BASE+0x04)

#define SIO_GPIO_OUT_RW             (SIO_BASE+0x10)
#define SIO_GPIO_OUT_SET            (SIO_BASE+0x14)
#define SIO_GPIO_OUT_CLR            (SIO_BASE+0x18)
#define SIO_GPIO_OUT_XOR            (SIO_BASE+0x1C)

#define SIO_GPIO_OE_RW              (SIO_BASE+0x20)
#define SIO_GPIO_OE_SET             (SIO_BASE+0x24)
#define SIO_GPIO_OE_CLR             (SIO_BASE+0x28)
#define SIO_GPIO_OE_XOR             (SIO_BASE+0x2C)

#define IO_BANK0_BASE               0x40014000

#define IO_BANK0_GPIO25_CTRL_RW     (IO_BANK0_BASE+0x0CC+0x0000)
#define IO_BANK0_GPIO25_CTRL_XOR    (IO_BANK0_BASE+0x0CC+0x1000)
#define IO_BANK0_GPIO25_CTRL_SET    (IO_BANK0_BASE+0x0CC+0x2000)
#define IO_BANK0_GPIO25_CTRL_CLR    (IO_BANK0_BASE+0x0CC+0x3000)

#define IO_BANK0_GPIO1_CTRL_RW     (IO_BANK0_BASE+0x00C+0x0000)
#define IO_BANK0_GPIO1_CTRL_XOR    (IO_BANK0_BASE+0x00C+0x1000)
#define IO_BANK0_GPIO1_CTRL_SET    (IO_BANK0_BASE+0x00C+0x2000)
#define IO_BANK0_GPIO1_CTRL_CLR    (IO_BANK0_BASE+0x00C+0x3000)

int notmain ( void )
{
    unsigned int ra;
    PUT32(RESETS_RESET_CLR,1<<5); //IO_BANK0
    while(1)
    {
        if((GET32(RESETS_RESET_DONE_RW)&(1<<5))!=0) break;
    }
    PUT32(SIO_GPIO_OE_CLR,1<<25);
    PUT32(SIO_GPIO_OUT_CLR,1<<25);
    PUT32(IO_BANK0_GPIO25_CTRL_RW,5); //SIO
    PUT32(SIO_GPIO_OE_SET,1<<25);
    for(ra=0;ra<10;ra++)
    {
        PUT32(SIO_GPIO_OUT_XOR,1<<25);
        DELAY(0x40000);
    }

    PUT32(SIO_GPIO_OE_CLR,1<<1);
    PUT32(SIO_GPIO_OUT_CLR,1<<1);
    PUT32(IO_BANK0_GPIO1_CTRL_RW,5); //SIO
    while(1)
    {
        ra=GET32(SIO_GPIO_IN);
        if(ra&2)
        {
            PUT32(SIO_GPIO_OUT_SET,1<<25);
        }
        else
        {
            PUT32(SIO_GPIO_OUT_CLR,1<<25);
        }
    }
    return(0);
}

严格从文档中找到所有这些地址和信息...
PUT 32只是一个存储字,GET 32只是一个加载字。延迟只是一个计数到零的循环。
GPIO通常默认/重置为输入,清除out/oe并使其成为我可能直接从他们的库中获得的输入,这是必需的吗?不知道,也许可以看看那些登记簿。
您确实需要在I/O块上释放reset,所以可能您正在其他地方这样做。
上面的led Flink 5次,然后进入一个轮询循环阅读gpio和隔离gpio 1,如果高,然后亮起led,如果低,然后不。
将其转换为asm很简单,应该能够看到你和我所做的不同之处,并决定是否需要清除out/oe设置。你有错误的地址,写的东西,你应该阅读和IO块的复位在最低限度。

相关问题