FireBLE/GPIO driver

来自Firefly wiki
跳转至: 导航搜索


  • QN9021 has 15 free configuration GPIO.Take resources include two Uart、two way PWM output、SPI interface、I2C interface、RTCI interface、SWD simulation entrance、comparator output and timer and many other resources.Will inevitably be many resources IO multiplex ,So After the GPIO must be configured to normal use.

  • In this case as a GPIO test,mainly introduced how to configure GPIO Port ,how to configure the pin function and using.

  • Note:Under the deep sleep,only group P0 and P1 IO mouth can wake up to sleep.


Typically driven development process: system initialization-->GPIO configuration-->Each driver module initialization-->The main loop function.The first step in system initialization is necessary to each routine,initialization process is the same,so just call system initialization interface.

The following three parts are all we need to according to their own requirements to implementation,in the previous section we have configured the GPIO,next is the initialization of the various modules.

Initialization function

gpio_init function prototypes:

void gpio_init(gpio_callback_t p_callback)
    // Initialize environment
    gpio_env.callback = p_callback;
/* Enable AHB clock to the GPIO domain. */
/* Set up NVIC when I/O pins are configured as external interrupts. */

Incoming parameters: the callback function of GPIO interrupt occurs.

Initialization function for the three things

  1. If Enable the callback function, set the callback function, the callback function pointer to address have parameters.
  2. Open GPIO Clock.
  3. Open GPIO I2Cnterrupt.

The callback function is realized for LED_PIN invert the output level of the operation.

void cb_gpio(enum gpio_pin pin)
    if (pin == BUTTON_PIN)
	/* toggle the LED_PIN GPIO_LEVEL*/

GPIO Experiment

GPIO Input Experiment

GPIO Experiment mainly shows set a GPIO and set all the GPIO direction method、read a GPIO and reads all GPIO input status.GPIO inputs experiment,need to define the macros GPIO_INPUT_EXAMPLE set as to true,and the other two set to FALSE.

Two global variables in the program,Respectively used to store the current all GPIO input status and P00 input state.

uint32_t result;
enum gpio_level result_level;

Alone Set a IO Port direction function

void gpio_set_direction(enum gpio_pin pin, enum gpio_direction direction)
    if(direction == GPIO_INPUT)
        gpio_gpio_ClrOutEnable(QN_GPIO, pin);
    else /*if(direction == GPIO_OUTPUT)*/
        gpio_gpio_SetOutEnable(QN_GPIO, pin);

Two incoming parameters for the enumeration type variable,so we can ensure the correctness of the parameters,strengthen the logic code can be read.find gpio_pin definition and gpio_direction definition ,you can know, the first incoming parameters is need to be configured for specific GPIO,the second parameter is set the GPIO state input or output. Set all the direction function of GPIO port.

void gpio_set_direction_field(uint32_t pin_mask, uint32_t direction_value)
    direction_value &= pin_mask;
gpio_gpio_SetOutEnable(QN_GPIO, direction_value);
    direction_value ^= pin_mask;
    gpio_gpio_ClrOutEnable(QN_GPIO, direction_value);

Check the information known by the above,chip maximum draw forth 30 GPIO port,QN9021 compatible with QN9020,QN9021 only 15 GPIO port,but the definition of position has not changed.So a 32-bit uint32_t type variables can be in the form of a mask out all the I/o port.Due to the IO port only input and output in both directions,so that we can also use a number uint32_t types of mask all the IO port all that is needed two parameters can be realized at the same time set up multiple IO port direction_value &= pin_mask;and direction_value ^= pin_mask;In order not to affect the operation of the other.

Experiments first set all the GPIO port to input direction

/* Set all pin to input */
    gpio_set_direction_field(GPIO_PIN_ALL, (uint32_t)GPIO_INPUT);

Then ceaseless read IO port state Read all GPIO port input state

/* read all pins input level */
 result = gpio_read_pin_field(GPIO_PIN_ALL);

Read input GPIO_P00 port input state

/* read P0.0 input level*/
 result_level = gpio_read_pin(GPIO_P00);

Function gpio_read_pin_field and gpio_read_pin same is true of the incoming parameters.The user can see the current simulators debugging through GPIO input status,can also by setting the GPIO pull-up and pull-down state to see if the lead when dangling level under different condition.

GPIO Output Experiment

Set all the GPIO as output

/* Set all pin to output */
gpio_set_direction_field(GPIO_PIN_ALL, (uint32_t)GPIO_OUTPUT);

From P00 to P36, which in turn is set to high level.

int i;
for(i=0; i<31; ++i)
            /* Polling all pins to output low level, and the order is from P0.0 to P3.6 */
            gpio_write_pin_field(GPIO_PIN_ALL, ~(1<<i));

Similarly,if you need to set the output level of a certain GPIO separately,can use gpio_write_pin function,the following routines function have a specific application.

GPIO interrupt Experiment

GPIO interrupt experiment mainly realized through key trigger GPIO port interrupt,enter the interrupt processing,interrupt handler will put the plate on the LED to light switch,so as to realize the control of buttons on the LED. GPIO interrupt experiment,need to define the macros GPIO_INTERRUPT_EXAMPLE set to true,and the other two set to FALSE.


First, define the buttons and LED the corresponding pin on the development board.

#define	BUTTON_PIN	        (GPIO_P03)
#define	LED_PIN			(GPIO_P26)

Development board has two buttons,one is joystick, one is ordinary buttons.Ordinary button is reset the development board,Experimental indicate button is joystick,joystick by two IO with the realization of the state of the button work ,which the connection P03 pins in the keys in an arbitrary direction of press will produce a low level,so if only consider P03 level state,joystick is equivalent to a five according to law but the result is as ordinary buttons.

Configuration BUTTON_PIN to pull on state、input mode、rising along the trigger the interrupt and open the interrupt.

 /* set BUTTON_PIN to pull up */
 gpio_pull_set(BUTTON_PIN, GPIO_PULL_UP);
 /* set BUTTON_PIN direction to input*/
 gpio_set_direction(BUTTON_PIN, (uint32_t)GPIO_INPUT);
 /* set BUTTON_PIN interrupt to rising edge*/
 gpio_set_interrupt(BUTTON_PIN, GPIO_INT_RISING_EDGE);
 /* enable BUTTON_PIN interrupt and set the callback function*/

Why do you want to configure BUTTON_PIN pull-up??Because as an input port,IO port must be able to detect the change of the external level.In fact button is equivalent to a switch,when pressing the conduction,released is disconnected.In the design of the hardware buttons at both ends of the a connected to the IO port,at one end connect to the GND.At the time of button presses,IO port is equivalent connect to GND,the CPU can access to the outside world entered a low level,so when key releases,at this time should be a high level.While the button is released as open circuit state,so you need to pull-up resistance level to open up,in this way can we achieve key state judgment.And the like,If the keys meet high level at the other end,At this time should be a pull-down configuration IO port state.

Configure BUTTON_PIN can't realize the control of the LED, because LED_PIN hasn't been initialized

Set the LED_PIN to output state

/* set LED_PIN direction to output*/
gpio_set_direction(LED_PIN, (uint32_t)GPIO_OUTPUT);

Settings the LED_PIN initial level,according to the hardware design,LED_PIN lighten for the low levels,the opposite is extinguish.

/* set LED_PIN to output low level*/
gpio_write_pin(LED_PIN, GPIO_LOW);

So far all the configuration of the work is done,just press the button can change the LED on and off.

Experimental Conclusion

Before using GPIO,make sure the system initialization and GPIO pin function configuration has been completed.

  1. Call gpio_init function initialize the GPIO ,set the callback function and open GPIO clock and interrupt.(Don't think don't need a callback function is not call this function,If there is no call this function will not open the GPIO clock,at the back of the configuration and use will be to no avail.)
  2. Set the GPIO port direction,if an input direction need to set up the IO port pull up and down,output direction you need to initialize IO port initial level.
  3. According to the need to use the GPIO.