raspberrypi / pico-sdk

BSD 3-Clause "New" or "Revised" License
3.74k stars 928 forks source link

gpio_get() doesn't work for high numbered channels #786

Closed Gavin-Perry closed 2 years ago

Gavin-Perry commented 2 years ago

gpio_get() doesn't seem to work for channels 26-28 and possibly others above 16? example

gpio_set_dir(27, GPIO_IN); gpio_pull_up(27); // set to 1 or // gpio_pull_down(27); // set to 0 // Try it... my27Val = gpio_get(27); // or if (gpio_get(26)) ChanGroup = 1; // ALWAYS returns 0

I used a work around using analogRead() which works so it's not a hardware issue. if (analogRead(27)>400) my27Val = 1; else my27Val=0; // // I suppose just would work my27Bool = (analogRead(27)>400);

lurch commented 2 years ago

If you're mixing up analog code and digital code, then I think setting an "ADC-capable GPIO" (i.e. GPIO26-GPIO29) into analog mode disconnects it from the digital controls? Can you paste a full example program that demonstrates the problem please, rather than just a short snippet?

Gavin-Perry commented 2 years ago

This is the first thing I do so there isn't any more relevant code:

int ChanGroup = 0; // 7 groups of channels available (16 per group) groups 0-7 int StartChannel = BASE_ADDRESS + (NUM_CHANNELS ChanGroup); // Default to lowest group void setup() {
delay(200); // Figure out which channel group we are to use for this board // A simple way to read 3 pins to get 0-7 - Set to input pull-up for this // doc's say "pull-up means the pushbutton's logic is inverted" WTF? pull_up just means default is high gpio_set_dir(26, GPIO_IN); gpio_pull_up(26); gpio_set_dir(27, GPIO_IN); gpio_pull_up(27); gpio_set_dir(28, GPIO_IN); gpio_pull_up(28); /
// This doesn't work right! bool (non zero <>1?) vs int vs byte? ChanGroup = gpio_get(26); ChanGroup = ChanGroup + (gpio_get(27)<<1); ChanGroup = ChanGroup + (gpio_get(28)<<2); //*/

// Why is get (or digitalRead() always returning 0? if (gpio_get(26)) ChanGroup = 1; else ChanGroup = 0; if (gpio_get(27)) ChanGroup = ChanGroup + 2; if (gpio_get(28)) ChanGroup = ChanGroup + 4; if (ChanGroup >6) ChanGroup = 6; // Groups 0 to 6 only allowed

// Update the start channel StartChannel = BASE_ADDRESS + (NUM_CHANNELS * ChanGroup); // always getting BASE_ADDRESS

geurtv commented 2 years ago

Seems like those pins are already set to some alternate function (by SDK or bootloader?) or something. I don't know what or why but when I run your example I get the same results so pull-up doesn't work. Anyway, you need to start with gpio_init(), then it works for me:

gpio_init(26)
gpio_set_dir(26, GPIO_IN);
gpio_pull_up(26);
... etc
lurch commented 2 years ago

Seems like those pins are already set to some alternate function (by SDK or bootloader?) or something. I don't know what or why

In Section 2.3.1.2 of https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf it says "To drive a pin with the SIO’s GPIO registers, the GPIO multiplexer for this pin must first be configured to select the SIO GPIO function." and I believe that's what the gpio_init() function does. Looking up the GPIO0_CTRL register (in Table 295) shows that the FUNCSEL field defaults to NULL, i.e. each external GPIO pin is "non-functioning" until assigned to a specific function-select.

Also, once you have the GPIOs and pull-ups properly configured, I guess your gpio-reading code could (optionally) be reduced down to something like:

ChanGroup = (gpio_get_all() & (1<<26 | 1<<27 | 1<<28)) >> 26;

to read all three GPIOs into a single 3-bit value with just one function-call.

Gavin-Perry commented 2 years ago

Thank you guys for your help. That should do it. I'll try it when I get home. Your ChanGroup assignment code is even better than what I thought to use with individual gpio_get() per pin I suppose one could use ChanGroup = (gpio_get_all() & (7<<26 )) >> 26; for these particular pins I hadn't looked up the mapping of gpio_get_all(). It makes sense that the pin numbers would correspond to bit numbers but I haven't seen anything that sane since I started working with Arduino They didn't like to use proper pin or Dx values but assign IO numbers based on how the board was laid out.

lurch commented 2 years ago

I guess this can be closed now?