Pandora IOT Development Board Learning (RT-Thread) - Experiment 3 Button Experiment (Study Notes)

The code in this article refers to RT-Thread official BSP

Experimental features

Routine source code: (main.c)

The function realized in this experiment: press KEY0, LED_R lights up, release KEY0, LED_R goes out.

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-08-23     balanceTWK   first implementation
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

int main(void)
{
    
    
    unsigned int count = 1;

    /* 设置 RGB 红灯引脚的模式为输出模式 */
    rt_pin_mode(PIN_LED_R, PIN_MODE_OUTPUT);
    /* 设置 KEY0 引脚的模式为输入模式 */
    rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT);

    while (count > 0)
    {
    
    
        /* 读取按键 KEY0 的引脚状态 */
        if (rt_pin_read(PIN_KEY0) == PIN_LOW)
        {
    
    
            rt_thread_mdelay(50); // 消除抖动
            if (rt_pin_read(PIN_KEY0) == PIN_LOW)
            {
    
    
                /* 按键已被按下,输出 log,点亮 LED 灯 */
                LOG_D("KEY0 pressed!");
                rt_pin_write(PIN_LED_R, PIN_LOW);
            }
        }
        else
        {
    
    
            /* 按键没被按下,熄灭 LED 灯 */
            rt_pin_write(PIN_LED_R, PIN_HIGH);
        }
        rt_thread_mdelay(10);
        count++;
    }
    return 0;
}

Code Analysis

rt_pin_mode()

The function of this function is the initialization of GPIO Pin, which is defined as

/* RT-Thread Hardware PIN APIs */
void rt_pin_mode(rt_base_t pin, rt_base_t mode)
{
    
    
    RT_ASSERT(_hw_pin.ops != RT_NULL);
    _hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode);
}

The parameter pin is an rt_base_t variable (long). The following GET_PIN()is the STM32 pin value macro definition. The first parameter is filled with capital letters, and the second parameter is filled with numbers.

#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA)/(0x0400UL) )) + PIN)

#define __STM32_PORT(port)  GPIO##port   // ## 是字符连接符,假如 port 为 A,则表示 GPIOA

For example, in the experiment #define PIN_LED_R GET_PIN(E, 7), it means GPIOE GPIO_Pin7

The pin working modes currently supported by RT-Thread include:

#define PIN_MODE_OUTPUT 0x00            /* 输出 */
#define PIN_MODE_INPUT 0x01             /* 输入 */
#define PIN_MODE_INPUT_PULLUP 0x02      /* 上拉输入 */
#define PIN_MODE_INPUT_PULLDOWN 0x03    /* 下拉输入 */
#define PIN_MODE_OUTPUT_OD 0x04         /* 开漏输出 */

In the bsp drv_gpio.cfile , there is the underlying GPIO driver, and the following is the driver function for setting the GPIO mode of STM32 (you should be familiar with the GPIO initialization code written in the HAL library)

static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
{
    
    
    const struct pin_index *index;
    GPIO_InitTypeDef GPIO_InitStruct;

    index = get_pin(pin);
    if (index == RT_NULL)
    {
    
    
        return;
    }

    /* Configure GPIO_InitStructure */
    GPIO_InitStruct.Pin = index->pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    if (mode == PIN_MODE_OUTPUT)
    {
    
    
        /* output setting */
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    }
    else if (mode == PIN_MODE_INPUT)
    {
    
    
        /* input setting: not pull. */
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    }
    else if (mode == PIN_MODE_INPUT_PULLUP)
    {
    
    
        /* input setting: pull up. */
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
    }
    else if (mode == PIN_MODE_INPUT_PULLDOWN)
    {
    
    
        /* input setting: pull down. */
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    }
    else if (mode == PIN_MODE_OUTPUT_OD)
    {
    
    
        /* output setting: od. */
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    }

    HAL_GPIO_Init(index->gpio, &GPIO_InitStruct);
}

rt_pin_read()

GPIO read function, the following is the definition of the function:

int  rt_pin_read(rt_base_t pin)
{
    
    
    RT_ASSERT(_hw_pin.ops != RT_NULL);
    return _hw_pin.ops->pin_read(&_hw_pin.parent, pin);
}

Similar to the GPIO mode configuration function, it will call the corresponding function in the underlying driver, and the underlying function obtains the GPIO level HAL_GPIO_ReadPin()through .

static int stm32_pin_read(rt_device_t dev, rt_base_t pin)
{
    
    
    int value;
    const struct pin_index *index;

    value = PIN_LOW;

    index = get_pin(pin);
    if (index == RT_NULL)
    {
    
    
        return value;
    }

    value = HAL_GPIO_ReadPin(index->gpio, index->pin);

    return value;
}

rt_thread_mdelay()

This is the millisecond delay function of RT-Thread, defined as follows:

rt_err_t rt_thread_mdelay(rt_int32_t ms)
{
    
    
    rt_tick_t tick;

	// 获取需要的时钟节拍
    tick = rt_tick_from_millisecond(ms);
	
	// 阻塞相应的节拍时间
    return rt_thread_sleep(tick);
}

rt_tick_from_millisecond()


/**
 * 算出 ms 对应的时钟节拍数
 * 
 *
 * @param ms the specified millisecond
 *           - Negative Number wait forever
 *           - Zero not wait
 *           - Max 0x7fffffff
 *
 * @return the calculated tick
 */
rt_tick_t rt_tick_from_millisecond(rt_int32_t ms)
{
    
    
    rt_tick_t tick;

    if (ms < 0)
    {
    
    
        tick = (rt_tick_t)RT_WAITING_FOREVER;  // -1 
    }
    else
    {
    
    
    	// 将“每秒节拍数” / 1000 * ms,算出对应的秒节拍数
        tick = RT_TICK_PER_SECOND * (ms / 1000);
		
		// 加上小于 1000ms 部分的节拍数
        tick += (RT_TICK_PER_SECOND * (ms % 1000) + 999) / 1000;
    }
    
    /* return the calculated tick */
    return tick;
}

rt_thread_sleep()

Thread sleep (suspend) function, the parameter is the number of system ticks:

/**
 * 该函数能让当前线程挂起一段时间(由 tick 决定)
 *
 * @param tick the sleep ticks
 *
 * @return RT_EOK
 */
rt_err_t rt_thread_sleep(rt_tick_t tick)
{
    
    
    register rt_base_t temp;
    struct rt_thread *thread;

    /* set to current thread */
    thread = rt_thread_self();
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);

    /* disable interrupt */
    temp = rt_hw_interrupt_disable();

    /* suspend thread */
    rt_thread_suspend(thread);

    /* reset the timeout of thread timer and start it */
    rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
    rt_timer_start(&(thread->thread_timer));

    /* enable interrupt */
    rt_hw_interrupt_enable(temp);

    rt_schedule();

    /* clear error number of this thread to RT_EOK */
    if (thread->error == -RT_ETIMEOUT)
        thread->error = RT_EOK;

    return RT_EOK;
}

LOG_D()

In this experiment, we can regard LOG_D()as rt_kprintf(),

#define dbg_log_line(lvl, color_n, fmt, ...)                \
    do                                                      \
    {
      
                                                             \
        _DBG_LOG_HDR(lvl, color_n);                         \
        rt_kprintf(fmt, ##__VA_ARGS__);                     \
        _DBG_LOG_X_END;                                     \
    }                                                       \
    while (0)

LOG_D is a log printing function in the RT-Thread kernel. For details, see: "RT-Thread Documentation Center - ulog Log"

RT-Thread's logging API includes:

insert image description here

rt_pin_write()

GPIO write function, the following is the definition of the function,

void rt_pin_write(rt_base_t pin, rt_base_t value)
{
    
    
    RT_ASSERT(_hw_pin.ops != RT_NULL);
    _hw_pin.ops->pin_write(&_hw_pin.parent, pin, value);
}

Similar to the GPIO mode configuration function, it will call the corresponding function in the underlying driver, and the underlying function is HAL_GPIO_WritePin()to complete the modification of the GPIO Pin through .

static void stm32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
{
    
    
    const struct pin_index *index;

    index = get_pin(pin);
    if (index == RT_NULL)
    {
    
    
        return;
    }

    HAL_GPIO_WritePin(index->gpio, index->pin, (GPIO_PinState)value);
}

Guess you like

Origin blog.csdn.net/weixin_43772810/article/details/125561455