矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 1186|回复: 17

Raspberry Pi Pico的GPIO端口SIO类结构体不好使

[复制链接]
     
发表于 2025-2-1 12:11:18 | 显示全部楼层 |阅读模式
本帖最后由 量子隧道 于 2025-2-1 12:17 编辑

Raspberry Pi Pico的SIO是一系列与其它设备统一进行地址编址的寄存器。通过对SIO寄存器的直接访问,可以便捷地对IO进行批量赋值和读取。我在熟悉它的过程中,发现其中的  sio_hw->gpio_oe_set和sio_hw->gpio_oe等寄存器操作不好使。非要调用arduino IDE框架下的pinMode,才能设置管脚为输出。如下是示例程序。其中的四句pinMode函数是不可缺少的。有玩树莓派pico的坛友遇到过和我一样的问题吗?

  1. #include <Arduino.h>
  2. #include "pico/stdlib.h"
  3. #include "hardware/gpio.h"

  4. #define LED_PIN_1 25
  5. #define LED_PIN_2 2
  6. #define LED_PIN_3 3
  7. #define LED_PIN_4 4


  8. void setup() {
  9.   // 设置 GPIO 为输出模式
  10.   pinMode(LED_PIN_1,OUTPUT);
  11.   pinMode(LED_PIN_2,OUTPUT);
  12.   pinMode(LED_PIN_3,OUTPUT);
  13.   pinMode(LED_PIN_4,OUTPUT);
  14.   sio_hw->gpio_oe_set = 0x3fffffff;
  15.   Serial.begin(115200);
  16. }

  17. void loop() {
  18.   //轮流点亮LED
  19.   sio_hw->gpio_out = 1<<LED_PIN_1 ;
  20.   delay(500);
  21.   sio_hw->gpio_out = 1<<LED_PIN_2 ;
  22.   delay(500);
  23.   sio_hw->gpio_out = 1<<LED_PIN_3 ;
  24.   delay(500);
  25.   sio_hw->gpio_out = 1<<LED_PIN_4 ;
  26.   delay(500);
  27.   //同时点亮所有 LED
  28.   sio_hw->gpio_set = (1 << LED_PIN_1) | (1 << LED_PIN_2) | (1 << LED_PIN_3) | (1 << LED_PIN_4);
  29.   delay(500);
  30.   // 同时关闭所有 LED
  31.   sio_hw->gpio_clr = (1 << LED_PIN_1) | (1 << LED_PIN_2) | (1 << LED_PIN_3) | (1 << LED_PIN_4);
  32.   delay(500);

  33.   Serial.println("***************");
  34. }
复制代码

评分

1

查看全部评分

发表于 2025-2-1 12:32:55 | 显示全部楼层
本帖最后由 girlexplorer 于 2025-2-1 12:37 编辑

老衲不懂编程,问了一下AI:

其中的四句pinMode函数是不可缺少的吗?


AI回答:

在上述代码中,`pinMode(LED_PIN_1, OUTPUT);`、`pinMode(LED_PIN_2, OUTPUT);`、`pinMode(LED_PIN_3, OUTPUT);`和`pinMode(LED_PIN_4, OUTPUT);`是必不可少的。这些函数用于将指定的GPIO引脚设置为输出模式,以便能够控制LED灯的状态。

具体来说:

1. **初始化阶段**:
   - `sio_hw->gpio_oe_set = 0x3fffffff;` 将所有GPIO引脚设置为输出状态。
   - 这一步是必要的,因为如果没有将这些引脚设置为输出模式,后续的写操作(如`sio_hw->gpio_out`、`sio_hw->gpio_set`和`sio_hw->gpio_clr`)将会导致未定义的行为。

2. **主循环**:
   - 在每次循环中,通过调用 `pinMode(LED_PIN_1, OUTPUT);` 等函数来确保LED引脚仍然处于输出模式。虽然在每个循环的开头已经设置了所有GPIO为输出状态,但为了明确表示这一点,并且避免潜在的问题,这些函数通常会在每一步操作之前再次被调用。

因此,在实际应用中,即使在初始化阶段将所有GPIO设置为输出状态,`pinMode(LED_PIN_1, OUTPUT);`等函数仍然需要在每次写操作前进行调用。


(感觉这次AI回答的不靠谱。主循环里好像没有再次调用pinmode)



回复 支持 反对

使用道具 举报

     
发表于 2025-2-1 12:44:23 | 显示全部楼层
本帖最后由 scoopydoo 于 2025-2-1 12:45 编辑

看了下数据手册,你这个 pinMode 函数应该是对应 GPIO 控制寄存器的 0..4 bit 的,必须要设置啊!

你看数据手册的 2.19.2. Function Select 就清楚了。

评分

2

查看全部评分

回复 支持 反对

使用道具 举报

发表于 2025-2-1 12:46:29 | 显示全部楼层
(AI编出了类似程序,不知这个AI编的程序是否可行。这个程序里,AI也用了pinmode)


您:(提出要求)

使用Arduino和Pico微控制器控制四个LED灯的亮灭。逐个点亮每个LED,每次点亮一个LED后等待500毫秒。同时点亮所有四个LED,然后等待500毫秒。同时关闭所有四个LED,然后等待500毫秒。每次循环结束后,打印一行“***************”。请编出程序。


AI回答:

以下是一个使用Arduino和Pico微控制器控制四个LED灯的示例程序。这个程序逐个点亮每个LED,然后同时点亮所有四个LED,关闭所有四个LED,并在每次循环结束后打印一行“***************”。

```cpp
#include <Arduino.h>

// 定义LED引脚
const int led1 = 2; // Pico上的GPIO2连接到第一个LED
const int led2 = 3; // Pico上的GPIO3连接到第二个LED
const int led3 = 4; // Pico上的GPIO4连接到第三个LED
const int led4 = 5; // Pico上的GPIO5连接到第四个LED

void setup() {
  // 初始化所有LED为输出模式
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);

  Serial.begin(9600); // 启动串口通信,用于调试和打印信息
}

void loop() {
  // 逐个点亮每个LED
  digitalWrite(led1, HIGH);
  delay(500);
  digitalWrite(led2, HIGH);
  delay(500);
  digitalWrite(led3, HIGH);
  delay(500);
  digitalWrite(led4, HIGH);
  delay(500);

  // 同时点亮所有四个LED
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
  digitalWrite(led4, LOW);
  delay(500);

  // 关闭所有四个LED
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  digitalWrite(led3, HIGH);
  digitalWrite(led4, HIGH);
  delay(500);

  // 打印一行“***************”
  Serial.println("*****************");
}
```

### 解释:
- **引脚定义**:`const int led1 = 2;` 到 `const int led4 = 5;` 定义了四个LED的GPIO引脚。
- **初始化**:在 `setup()` 函数中,使用 `pinMode()` 将所有LED设置为输出模式,并启动串口通信以进行调试和打印信息。
- **循环体**:
  - 首先逐个点亮每个LED,每次点亮后等待500毫秒。
  - 然后同时关闭所有四个LED,再次等待500毫秒。
  - 最后,打印一行“***************”以表示一次完整的循环结束。

这个程序可以在Arduino IDE或Pico SDK中运行。确保你的开发环境已经正确配置,并且连接了正确的硬件设备(如Arduino板和Pico微控制器)。


评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2025-2-1 12:57:49 | 显示全部楼层
scoopydoo 发表于 2025-2-1 12:44
看了下数据手册,你这个 pinMode 函数应该是对应 GPIO 控制寄存器的 0..4 bit 的,必须要设置啊!

你看 ...

你说的是指2.19.2里的“ The SIO function (F5) must be selected for the processors to drive a GPIO”,而pinMode()函数就是用来设置管脚为“F5”功能的?那就清楚了。
只不过,我以为,这个“设置为F5”功能在SIO结构体里已经定义了呢,而且我以为它就是sio_hw->gpio_oe_set寄存器呢。看来不是。
这个编程框架有点不伦不类。按理说,应该在sio结构体里定义这个设置,而不应该一会儿pico sdk,一会儿arduino ide,显得这个程序框架像个大杂烩。

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
发表于 2025-2-1 13:03:02 | 显示全部楼层
量子隧道 发表于 2025-2-1 12:57
你说的是指2.19.2里的“ The SIO function (F5) must be selected for the processors to drive a GPIO” ...

俺没实验,但是俺觉得应该是这样的,一般来说单片机的 IO 引脚在使用前都要先选择功能的,毕竟都是多功能复用的。

俺对 Arduino 框架不熟悉,手里有两块 Nano 系列的 Arduino 小板子(33 IOT 和 Matter),但是基本只是拿来验证网上找到的一些 Arduino 代码 ...

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2025-2-1 13:03:58 | 显示全部楼层
本帖最后由 量子隧道 于 2025-2-1 13:08 编辑
girlexplorer 发表于 2025-2-1 12:46
(AI编出了类似程序,不知这个AI编的程序是否可行。这个程序里,AI也用了pinmode)


程序应该没问题,但是很可惜,它没有使用SIO类结构体和寄存器,而是调用了arduino的管脚控制函数(digitalwrite)来实现的。

--读了一下,看来AI还是个智障,程序是有基本逻辑错误的。不过框架应该没问题。

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2025-2-1 14:02:34 | 显示全部楼层
找到了pinMode()函数的定义,看起来若定义为output的话,库函数是啥都没做。这下子彻底风中凌乱了。。。
屏幕截图 2025-02-01 135938.png
回复 支持 反对

使用道具 举报

     
发表于 2025-2-1 14:20:48 | 显示全部楼层
先别凌乱,为啥俺看到的代码和你的不一样呢?
Screenshot 2025-02-01 172001.png
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2025-2-1 14:47:16 | 显示全部楼层
scoopydoo 发表于 2025-2-1 14:20
先别凌乱,为啥俺看到的代码和你的不一样呢?

我的wiring_digital.cpp文件的头两行注释是这样式儿的,你看看你的是不是:

pinMode and digitalRead/Write for the Raspberry Pi Pico RP2040

Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
回复 支持 反对

使用道具 举报

     
发表于 2025-2-1 14:50:55 | 显示全部楼层
量子隧道 发表于 2025-2-1 14:47
我的wiring_digital.cpp文件的头两行注释是这样式儿的,你看看你的是不是:

pinMode and digitalRead/ ...

俺看到的头两行是这样婶儿的,估计你那个是对的

  wiring_digital.cpp - digital input and output functions
  Part of Arduino - http://www.arduino.cc/


回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2025-2-1 14:52:45 | 显示全部楼层
scoopydoo 发表于 2025-2-1 14:50
俺看到的头两行是这样婶儿的,估计你那个是对的

我这是装了:
https://github.com/earlephilhowe ... e_rp2040_index.json
这个RP2040支持库的结果。
回复 支持 反对

使用道具 举报

     
发表于 2025-2-1 14:57:13 | 显示全部楼层
量子隧道 发表于 2025-2-1 14:52
我这是装了:
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp20 ...

哈哈,刚好俺也搜到这个,之前用的是 mBed 那个。

俺装上这个看看 .......
回复 支持 反对

使用道具 举报

     
发表于 2025-2-1 15:24:20 | 显示全部楼层
本帖最后由 scoopydoo 于 2025-2-1 15:37 编辑

应该是找到答案了,在 pico-sdk 的 gpio.c 文件的 gpio_init 函数里面:

  1. void gpio_init(uint gpio) {
  2.     gpio_set_dir(gpio, GPIO_IN);
  3.     gpio_put(gpio, 0);
  4.     gpio_set_function(gpio, GPIO_FUNC_SIO);
  5. }
复制代码


具体的实现是这样婶儿的:

  1. /// \tag::gpio_set_function[]
  2. // Select function for this GPIO, and ensure input/output are enabled at the pad.
  3. // This also clears the input/output/irq override bits.
  4. void gpio_set_function(uint gpio, gpio_function_t fn) {
  5.     check_gpio_param(gpio);
  6.     invalid_params_if(HARDWARE_GPIO, ((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) & ~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS);
  7.     // Set input enable on, output disable off
  8.     hw_write_masked(&pads_bank0_hw->io[gpio],
  9.                    PADS_BANK0_GPIO0_IE_BITS,
  10.                    PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS
  11.     );
  12.     // Zero all fields apart from fsel; we want this IO to do what the peripheral tells it.
  13.     // This doesn't affect e.g. pullup/pulldown, as these are in pad controls.
  14.     io_bank0_hw->io[gpio].ctrl = fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
  15. #if !PICO_RP2040
  16.     // Remove pad isolation now that the correct peripheral is in control of the pad
  17.     hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_ISO_BITS);
  18. #endif
  19. }
  20. /// \end::gpio_set_function[]
复制代码
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2025-2-1 16:48:20 | 显示全部楼层
本帖最后由 量子隧道 于 2025-2-1 17:00 编辑
scoopydoo 发表于 2025-2-1 15:24
应该是找到答案了,在 pico-sdk 的 gpio.c 文件的 gpio_init 函数里面:


问题在于,如果pinmode()函数里设置管脚为OUTPUT,那么gpio_init()函数得不到执行的机会啊

----啥也没干,就让管脚变成了function5(SIO)模式了?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-25 23:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表