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

问题描述 投票:0回答:1

我开始使用树莓派 pico 学习汇编语言和 ARM。

我什至一直在关注《RP2040汇编语言编程》这本书,但是没有关于如何仅使用汇编读取输入引脚的说明。 这是我的设置:我有一个按钮,未按下时发送 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"

到目前为止,我尝试查阅数据表,但我没有足够的知识来识别我所做的是否是写的或错误的。

assembly arm cortex-m led raspberry-pi-pico
1个回答
0
投票

这是 C,使用原始 picos 上的 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); }

严格从文档中查找所有这些地址和信息是,嗯......

PUT32 只是一个存储字,GET32 只是一个加载字。延迟只是一个计数到零的循环。

GPIO通常默认/重置为输入,清除out/oe并使其成为我可能直接从他们的库中获得的输入,这是必需的吗?不知道,也许可以读取那些寄存器并看到。

您确实需要释放 I/O 块上的复位,所以也许您在其他地方这样做。

上面的 LED 闪烁 5 次,然后进入轮询循环,读取 GPIO 并隔离 GPIO 1(如果为高电平),然后点亮 LED(如果为低电平,则不点亮 LED)。

将其转换为 asm 很简单,应该能够看到你所做的和我所做的差异,并决定是否需要清除 out/oe 设置。您的地址错误,正在写入您应该读取的内容,并且 IO 块至少无法重置。

© www.soinside.com 2019 - 2024. All rights reserved.