国民技术
直播中

hehung

9年用户 659经验值
擅长:嵌入式技术
私信 关注
[经验]

【国民技术N32项目移植】1. 新建工程+LED与按键跳坑总结

前言

拿到板子有段时间了,但是一直没有上手实践,这次春节期间,正好抽出来一点时间上手试一试。本来以为和之前使用过的国产芯片,如GD32类似,但是在驱动LED和按键的时候就遇到了一些问题,所以本文重点是对这些问题做一些记录。

本文中的代码使用RT-Thread Studio开发,使用了RT-Thread OS。

新建工程

本来打算将RT-Thread OS集成到N32G457中的,但是我打开RT-Thread Studio新建工程的时候就发现官方已经集成好了,所以直接拿过来使用即可。

安装SDK

我的板子是N32G45XVL-STB,如下图安装SDK,其他型号的板子方法类似,选择自己手头板子的型号安装即可。
4.jpg

新建RT-Thread工程

选择“文件 -> 新建 -> RT-Thread项目”,然后进行如下配置。
5.jpg

到此工程就算新建完毕,可以直接编译下载了,下载之后的程序可以看到LED闪烁。

编写LED流水灯线程

按照RT-Thread一贯的操作流程:
新建线程,使能线程;
初始化三个LED的GPIO口为输出模式;
然后依次控制三个LED输出;

但是发现LED2(PB4)一直处于亮的状态,而且亮度也比较微弱,最开始还以为是LED坏掉了,但是查看了数据手册发现是PB4的默认工作方式是NJTRST模式,不是普通IO口。
3.jpg

所以通过重映射,将PB4设置为普通IO口就可以解决这个问题。

/* PB4 default used for NJTRST, re-map it as no NJTRST */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
    GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_NO_NJTRST,ENABLE);

整个LED的控制代码如下,可以实现流水灯的逻辑。

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

#include "app_led.h"

#define LED_TOTAL_NUM              (3U)

/* defined the LED3 pin: PB5 */
#define LED3_PIN GET_PIN(B, 5)

/* defined the LED2 pin: PB4 */
#define LED2_PIN GET_PIN(B, 4)

/* defined the LED1 pin: PA8 */
#define LED1_PIN GET_PIN(A, 8)


typedef struct
{
    rt_base_t led_pin;
    rt_base_t led_val;
} s_LedCtrlType;

/* Led thread */
static rt_thread_t led_tid = RT_NULL;

static s_LedCtrlType led_ctrl[LED_TOTAL_NUM] =
{
    {.led_pin = LED1_PIN, .led_val = PIN_HIGH},
    {.led_pin = LED2_PIN, .led_val = PIN_LOW},
    {.led_pin = LED3_PIN, .led_val = PIN_LOW}
};


static void Led_ThreadRunning(void *param);


static void Led_ThreadRunning(void *param)
{
    uint8_t i;
    rt_base_t temp_pin;

    /* PB4 default used for NJTRST, re-map it as no NJTRST */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
    GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_NO_NJTRST,ENABLE);

    /* set LED pin mode to output */
    rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);

    while(1)
    {
        temp_pin = led_ctrl[0].led_val;
        for (i = 0; i < LED_TOTAL_NUM; i++)
        {
            rt_pin_write(led_ctrl[i].led_pin, led_ctrl[i].led_val);

            if (i != (LED_TOTAL_NUM - 1))
            {
                led_ctrl[i].led_val = led_ctrl[i+1].led_val;
            }
            else
            {
                led_ctrl[i].led_val = temp_pin;
            }
        }

        rt_thread_mdelay(500);
    }
}

void Led_Init(void)
{
    /* 创建线程 1,名称是 thread1,入口是 thread1_entry*/
    led_tid = rt_thread_create("led_thread",
                                Led_ThreadRunning,
                                RT_NULL,
                                2048,     /* Stack */
                                20,    /* priority */
                                5);    /* timeslice */

    if (led_tid != RT_NULL)
        rt_thread_startup(led_tid);
}

编写按键线程

与上述控制LED同样的方式将KEY相关的三个引脚(PA4,PA5,PA6)设置为输入模式,但是发现按下按键之后根本就不工作,反馈的电平一直是0。
找了一段时间,发现是驱动模式设置的不对,驱动模式设置为上拉输入就可以了(PIN_MODE_INPUT_PULLUP)。

/* set KEY pin mode to input */
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY3_PIN, PIN_MODE_INPUT_PULLUP);

完整代码如下,实现了40ms的按下/释放的软件滤波功能:

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-06-25     hehung       the first version
 */

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

#include "app_key.h"

#define KEY_TOTAL_NUM              (3U)

#define KEY_PRESSED                (1U)
#define KEY_RELEASED               (0U)

#define KEY_FILTER_THD             (4U)

/* defined the KEY3 pin: PA6 */
#define KEY3_PIN GET_PIN(A, 6)

/* defined the KEY2 pin: PA5 */
#define KEY2_PIN GET_PIN(A, 5)

/* defined the KEY1 pin: PA4 */
#define KEY1_PIN GET_PIN(A, 4)


typedef struct
{
    rt_base_t key_pin;
    rt_base_t key_val;
    uint8_t   key_status;
    uint8_t   key_pre_status;
    uint8_t   key_pending_cnt;
} s_KeyCtrlType;

/* key thread */
static rt_thread_t key_tid = RT_NULL;

static s_KeyCtrlType key_ctrl[KEY_TOTAL_NUM] =
{
    {
        .key_pin = KEY1_PIN,
        .key_val = PIN_LOW,
        .key_status = KEY_RELEASED,
        .key_pre_status = KEY_RELEASED,
        .key_pending_cnt = 0U
    },
    {
        .key_pin = KEY2_PIN,
        .key_val = PIN_LOW,
        .key_status = KEY_RELEASED,
        .key_pre_status = KEY_RELEASED,
        .key_pending_cnt = 0U
    },
    {
        .key_pin = KEY3_PIN,
        .key_val = PIN_LOW,
        .key_status = KEY_RELEASED,
        .key_pre_status = KEY_RELEASED,
        .key_pending_cnt = 0U
    }
};

static void Key_ThreadRunning(void *param);


static void Key_ThreadRunning(void *param)
{
    uint8_t i;
    rt_base_t temp_pin;

    /* set KEY pin mode to input */
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY3_PIN, PIN_MODE_INPUT_PULLUP);

    while(1)
    {
        for (i = 0; i < KEY_TOTAL_NUM; i++)
        {
            key_ctrl[i].key_val = rt_pin_read(key_ctrl[i].key_pin);
//            rt_kprintf("Key%d: %d, gpio:%d -- ", i, key_ctrl[i].key_val, key_ctrl[i].key_pin);
            if (key_ctrl[i].key_val == PIN_LOW)
            {
                if (key_ctrl[i].key_pending_cnt < KEY_FILTER_THD)
                    key_ctrl[i].key_pending_cnt ++;
            }
            else
            {
                if (key_ctrl[i].key_pending_cnt > 0U)
                    key_ctrl[i].key_pending_cnt --;
//                led_ctrl[i].key_pending_cnt = 0U;
            }

            /* Filter */
            if (key_ctrl[i].key_pending_cnt >= KEY_FILTER_THD)
            {
                key_ctrl[i].key_status = KEY_PRESSED;
            }
            else if (key_ctrl[i].key_pending_cnt == 0U)
            {
                key_ctrl[i].key_status = KEY_RELEASED;
            }

            key_ctrl[i].key_pre_status = key_ctrl[i].key_status;
            rt_kprintf("Key%d: %d", i, key_ctrl[i].key_status);
        }

        rt_kprintf("\n");

        rt_thread_mdelay(10);
    }
}

void Key_Init(void)
{
    /* 创建线程 1,名称是 thread1,入口是 thread1_entry*/
    key_tid = rt_thread_create("key_thread",
                                Key_ThreadRunning,
                                RT_NULL,
                                2048,     /* Stack */
                                3,    /* priority */
                                5);    /* timeslice */

    if (key_tid != RT_NULL)
        rt_thread_startup(key_tid);
}

更多回帖

发帖
×
20
完善资料,
赚取积分