Longan Nano: Help needed, GPIO - Page 1
Forum section: electronics / general

author: netmonk
author_rank: Contributor
timestamp: October 11, 2020, 08:59:57 pm
content: Hello,Im playing a little bit with Longan Nano riscv mcu devkit (not lite version). My background is mostly esp32 coding with arduino or esp-idf.So im quite noob about baremetal approach. I understand that Arduino or ESP-IDF provides high abstration layer which helps coders to easely prototype at the cost of control loss of the hardware.So back to the topic here, i modified the basic onboard led control example to roll through the three colors (RED/BLUE/GREEN).As each color is associated to a dedicated pin, those three leds can be activated on same time to produce a combinated color from those three.So far so good, i can produce RED+BLUE, RED+GREEN, GREEN+BLUE, and GREEN+BLUE+RED on top of just RED, BLUE, GREEN.Code:#include "gd32vf103.h"#include "systick.h"#include <stdio.h>/* BUILTIN LED OF LONGAN BOARDS IS PIN PC13 */// green = PA1, blue = PA2, RED PC13#define LED_RED_PIN GPIO_PIN_13#define LED_RED_GPIO_PORT GPIOC#define LED_RED_GPIO_CLK RCU_GPIOC#define LED_GRN_PIN GPIO_PIN_1#define LED_GRN_GPIO_PORT GPIOA#define LED_GRN_GPIO_CLK RCU_GPIOA#define LED_BLU_PIN GPIO_PIN_2#define LED_BLU_GPIO_PORT GPIOA#define LED_BLU_GPIO_CLK RCU_GPIOAint main(void) {/* enable the led clock(s) */rcu_periph_clock_enable(LED_RED_GPIO_CLK);rcu_periph_clock_enable(LED_GRN_GPIO_CLK);rcu_periph_clock_enable(LED_BLU_GPIO_CLK);/* configure led GPIO port(s) */gpio_init(LED_RED_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED_RED_PIN);gpio_init(LED_GRN_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED_GRN_PIN);gpio_init(LED_BLU_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED_BLU_PIN);GPIO_BC(LED_RED_GPIO_PORT) = LED_RED_PIN; // red LED onGPIO_BC(LED_GRN_GPIO_PORT) = LED_GRN_PIN; // green LED onGPIO_BC(LED_BLU_GPIO_PORT) = LED_BLU_PIN; // blue LED onGPIO_BOP(LED_RED_GPIO_PORT) = LED_RED_PIN; // red LED offGPIO_BOP(LED_GRN_GPIO_PORT) = LED_GRN_PIN; // green LED offGPIO_BOP(LED_BLU_GPIO_PORT) = LED_BLU_PIN; // blue LED offwhile(1) {// GPIO_BC(LED_RED_GPIO_PORT) = LED_RED_PIN; // red LED on// delay_1ms(100);// GPIO_BOP(LED_RED_GPIO_PORT) = LED_RED_PIN; // red LED off// GPIO_BC(LED_GRN_GPIO_PORT) = LED_GRN_PIN; // green LED on// delay_1ms(100);// GPIO_BOP(LED_GRN_GPIO_PORT) = LED_GRN_PIN; // green LED off// GPIO_BC(LED_BLU_GPIO_PORT) = LED_BLU_PIN; // blue LED on// delay_1ms(100);// GPIO_BOP(LED_BLU_GPIO_PORT) = LED_BLU_PIN; // blue LED offGPIO_BC(LED_RED_GPIO_PORT) = LED_RED_PIN; // red LED onGPIO_BC(LED_GRN_GPIO_PORT) = LED_GRN_PIN; // green LED onGPIO_BC(LED_BLU_GPIO_PORT) = LED_BLU_PIN; // blue LED ondelay_1ms(10);GPIO_BOP(LED_RED_GPIO_PORT) = LED_RED_PIN; // red LED offGPIO_BOP(LED_GRN_GPIO_PORT) = LED_GRN_PIN; // green LED offGPIO_BOP(LED_BLU_GPIO_PORT) = LED_BLU_PIN; // blue LED offdelay_1ms(1000);}return 0;}In this example, i switch on the three leds in the same time.My first question is about about GPIO.I have hard time to understand the functionrcu_periph_clock_enable(). I might be noob, but i cannot see the association of clock and pin (at least from my experience with ardiuno on esp32).So if someone kind enough would help me to understand, it would be nice.My second question is about how to manage thoses pins.From what i understand those pins are 0 or 1 which from what i imagine 0 == no electricity, 1 == electricity at full voltage.So my conclusion is : what about modulating the voltage feeding thoses pins associated to led, so that i have control on intensity for each leds. This way i would be able to access to a bigger color palette, like with ws2821 or alike.So what would need to be change in my code (the way i declare and use pin => GPIO_MODE_OUT_PP may be), to achieve this, if it's possible (may be im totally wrong and need to be taught)Thank you for your reply.

author: pkplex
author_rank: Contributor
timestamp: October 13, 2020, 06:02:19 am
content: You need to look up a thing called PWM ( Pulse Width Modulation ).The basic gut's of it is that you can make a pin go high for a certain amount of time, and then low, many times per second (think 1Khz +). The amount of time as a percentage it spends high, is called the duty cycle. You can control the perceived 'brightness' of a led by adjusting the PWM duty cycle.As far as actually telling your uC to do it, you can manually code the PWM stuff in some way, using a loop, interrupts, or such... or you can perhaps configure a peripheral to do it for you automagically.

author: netmonk
author_rank: Contributor
timestamp: October 13, 2020, 07:57:07 am
content: I understand the main concept of using PWM for achieving the LED control.But are those 3 pins associated to the onboard led can be used for that ?Those 3 pins are hardwired on the devkit, and i dont know how much i can use pwm on them.I guess only testing will answer this !

author: netmonk
author_rank: Contributor
timestamp: October 13, 2020, 12:18:19 pm
content: From another source, i find out that i should use timer peripheric and not GPIO.But PC13 managing the red color is not attached to Timer peripherial. So it's not possible to achieve a full color palette.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: November 18, 2020, 05:04:17 pm
content: As far as I know this Risc-V chip is very close to a STM32F103, but with the ARM core replaced with Risc-V.With STM32 you have a lot of configuration options of how the clock is both generated and distributed throughout the chip. There are different peripheral buses, and there are different clock enable bits to distribute the clock signal to different peripherals. To get a grip on this you really need to study the datasheet.Again:This clock distribution is something completely different (and much more) then selecting a clock rate for a timer peripheral. This clock distribution effects the way the peripherals themselves behave and even a simple I/O register needs to have it's clock enabled if you want to communicate with it. If a peripheral does not have it's clock enabled, it is just as dead as a Norwegian Blue.

author: newbrain
author_rank: Super Contributor
timestamp: November 18, 2020, 11:15:08 pm
content: While it's true the pin connected to the red LED does not double up as a timer output, you could use a simple trick:From the DS, PA0 can be used a channel 0 output of TIMER1 and from the board schematic this pin is next PC13 on the edge 2.54 mm connectors, and not connected to anything else.Just put a jumper between the two, and don't initialize PC13 GPIO (or set it as input).This way, the R,G, and B LEDs will sit respectively on channels TIM1_CH0, TIM1_CH1, and TIM1_CH2 for you to have fun with PWM.Another minor thing, just to make sure:QuoteLogic 0, or low, does not mean 'no electricity': the output stage connected to the pin will be able to sink current: it's like a low value resistor connected to Vss (0 V, GND...).Exactly as logic 1, or high, is like low value resistor connected to Vdd (+3.3 V).

author: netmonk
author_rank: Contributor
timestamp: January 25, 2021, 09:17:42 am
content: I will have a look at it. i need to dive again on this little board.