FuShenxiao 发表于 2024-8-8 15:17

小熊派BearPi-Pico H2821星闪开发板测评(二)——GPIO与PWM测试

本帖最后由 FuShenxiao 于 2024-8-8 15:16 编辑

<p>上期说明:上期测评说到BurnTool.exe运行可能会消失,发现是360将其看作病毒拦截了,将其设置为可信任文件即可。</p>

<p><strong><span style="font-size:18px;">扩展板设计</span></strong></p>

<p>为了实现部分板载资源所无法实现的功能,我设计了一块扩展板。扩展板的设计也是较为简单,仅在引出核心板引脚的基础上加入了LED、按键、ADC采样和部分测试接口。</p>

<p>在嘉立创EDA中绘制原理图如下</p>

<p align="center"> &nbsp;</p>

<p>PCB绘制如下</p>

<p align="center"> &nbsp;</p>

<p>得到最终的扩展板(原谅我部分器件没有到货,但是这篇文章所用到的器件都能得到保证)</p>

<p style="text-align: center;"> &nbsp;</p>

<p><strong><span style="font-size:18px;">LED灯控制</span></strong></p>

<p>由扩展板原理图可知,GPIO11,GPIO12,GPIO13分别控制红绿蓝三色灯,同时,GPIO31控制着板载的LED灯</p>

<p align="center"> &nbsp;</p>

<p>代码实现:</p>

<pre>
<code>#include "boards.h"
#include "pinctrl.h"
#include "gpio.h"
#include "osal_debug.h"
#include "cmsis_os2.h"
#include "app_init.h"

#define BLINKY_TASK_STACK_SIZE    0x1000
#define BLINKY_TASK_PRIO          (osPriority_t)(17)

static void *blinky_task(const char *arg)
{

    unused(arg);
    uapi_pin_set_mode(CONFIG_BLINKY_PIN, HAL_PIO_FUNC_GPIO);
    uapi_gpio_set_dir(CONFIG_BLINKY_PIN, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(CONFIG_BLINKY_PIN, GPIO_LEVEL_LOW);
    uapi_pin_set_mode(11, HAL_PIO_FUNC_GPIO);
    uapi_gpio_set_dir(11, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(11, GPIO_LEVEL_LOW);
    uapi_pin_set_mode(12, HAL_PIO_FUNC_GPIO);
    uapi_gpio_set_dir(12, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(12, GPIO_LEVEL_LOW);
    uapi_pin_set_mode(13, HAL_PIO_FUNC_GPIO);
    uapi_gpio_set_dir(13, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(13, GPIO_LEVEL_LOW);

    while (1) {
        osDelay(CONFIG_BLINKY_DURATION_MS);
        uapi_gpio_toggle(CONFIG_BLINKY_PIN);
        uapi_gpio_toggle(11);
        uapi_gpio_toggle(12);
        uapi_gpio_toggle(13);
    }
    return NULL;
}

static void blinky_entry(void)
{
    osThreadAttr_t attr;

    attr.name = "BlinkyTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = BLINKY_TASK_STACK_SIZE;
    attr.priority = BLINKY_TASK_PRIO;

    if (osThreadNew((osThreadFunc_t)blinky_task, NULL, &amp;attr) == NULL) {
        /* Create task fail. */
    }
}

/* Run the blinky_entry. */

app_run(blinky_entry);</code></pre>

<p>其中</p>

<p>uapi_pin_set_mode为设置引脚运行模式</p>

<p>uapi_gpio_set_dir为设置引脚为输入还是输出</p>

<p>uapi_gpio_set_val为设置引脚电平</p>

<p>osDelay为中断延时函数</p>

<p>uapi_gpio_toggle为电平翻转</p>

<p>GPIO控制函数的传参中,第一位是引脚编号,只需输入GPIO的引脚编号即可</p>

<p align="center"> &nbsp;</p>

<p style="text-align: justify;">演示结果如下:</p>

<p style="text-align: justify;">52b746a29fdbab688f0f7a24e0764424</p>

<p><strong><span style="font-size:18px;">中断实现按键控制</span></strong></p>

<p>SW1,SW2,SW3分别由GPIO16,GPIO17,GPIO18控制</p>

<p>代码实现:</p>

<pre>
<code>#include "boards.h"
#include "pinctrl.h"
#include "gpio.h"
#include "osal_debug.h"
#include "cmsis_os2.h"
#include "app_init.h"

static void gpio_callback_func(pin_t pin, uintptr_t param)
{
    UNUSED(pin);
    UNUSED(param);
    osal_printk("Button pressed.\r\n");
}

static void gpio_callback_func1(pin_t pin, uintptr_t param)
{
    UNUSED(pin);
    UNUSED(param);
    osal_printk("SW1 pressed.\r\n");
}

static void gpio_callback_func2(pin_t pin, uintptr_t param)
{
    UNUSED(pin);
    UNUSED(param);
    osal_printk("SW2 pressed.\r\n");
}

static void gpio_callback_func3(pin_t pin, uintptr_t param)
{
    UNUSED(pin);
    UNUSED(param);
    osal_printk("SW3 pressed.\r\n");
}

static void button_entry(void)
{
    uapi_pin_set_mode(CONFIG_BUTTON_PIN, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_pull(CONFIG_BUTTON_PIN, PIN_PULL_UP);
    uapi_gpio_set_dir(CONFIG_BUTTON_PIN, GPIO_DIRECTION_INPUT);   
    uapi_gpio_register_isr_func(CONFIG_BUTTON_PIN,GPIO_INTERRUPT_DEDGE, gpio_callback_func);

    uapi_pin_set_mode(16, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_pull(16, PIN_PULL_UP);
    uapi_gpio_set_dir(16, GPIO_DIRECTION_INPUT);   
    uapi_gpio_register_isr_func(16, GPIO_INTERRUPT_DEDGE, gpio_callback_func1);

    uapi_pin_set_mode(17, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_pull(17, PIN_PULL_UP);
    uapi_gpio_set_dir(17, GPIO_DIRECTION_INPUT);   
    uapi_gpio_register_isr_func(17, GPIO_INTERRUPT_DEDGE, gpio_callback_func2);

    uapi_pin_set_mode(18, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_pull(18, PIN_PULL_UP);
    uapi_gpio_set_dir(18, GPIO_DIRECTION_INPUT);   
    uapi_gpio_register_isr_func(18, GPIO_INTERRUPT_DEDGE, gpio_callback_func3);
}

/* Run the button_entry. */

app_run(button_entry);</code></pre>

<p>在uapi_gpio_rigister_isr_func函数中可以看出,按键中断为下降沿触发,由于按键抖动的问题,这种中断方式不可避免地会导致中断多次触发,结果如下图所示,可以看到中断被多次触发。</p>

<p align="center"> &nbsp;</p>

<p><strong><span style="font-size:18px;">PWM输出控制</span></strong></p>

<p>由于该核心板IO口可复用为任意功能,因此利用核心板和扩展板上的LED灯实现呼吸灯</p>

<p>以实现LED1的呼吸灯效果为例</p>

<pre>
<code>#include "pinctrl.h"
#include "pwm.h"
#include "osal_debug.h"
#include "cmsis_os2.h"
#include "app_init.h"
#include "tcxo.h"

#define PWM_CHANNEL                0
#define PWM_GROUP_ID               0
#define TEST_MAX_TIMES             5
#define DALAY_MS                   100
#define TEST_TCXO_DELAY_1000MS     1000
#define PWM_TASK_STACK_SIZE        0x1000
#define PWM_TASK_PRIO              (osPriority_t)(17)

static void *pwm_task(const char *arg)
{
    UNUSED(arg);
    pwm_config_t cfg_led1 = {
        0,
        250,
        0,
        0,
        true
    };

    uint8_t flag_led1 = 0;
    uapi_pin_set_mode(11, HAL_PIO_PWM0);
    uapi_pwm_init();
    uint8_t channel = PWM_CHANNEL;
    uapi_pwm_set_group(PWM_GROUP_ID, &amp;channel, 1);
    uapi_pwm_open(PWM_CHANNEL, &amp;cfg_led1);
    uapi_pwm_config_preload(PWM_GROUP_ID, channel, &amp;cfg_led1);
    uapi_pwm_start(PWM_GROUP_ID);

    while (1)
    {
        if(cfg_led1.low_time == 0)
            flag_led1 = 1;
        else if(cfg_led1.high_time == 0)
            flag_led1 = 0;
        if(flag_led1 == 0)
        {
            cfg_led1.high_time++;
            cfg_led1.low_time--;
        }
        else
        {
            cfg_led1.high_time--;
            cfg_led1.low_time++;
        }

        uapi_pwm_open(PWM_CHANNEL, &amp;cfg_led1);
        uapi_pwm_config_preload(PWM_GROUP_ID, channel, &amp;cfg_led1);
        uapi_pwm_start(PWM_GROUP_ID);
        osDelay(10);
    }
    return NULL;
}

static void pwm_entry(void)
{
    osThreadAttr_t attr;

    attr.name = "PWMTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = PWM_TASK_STACK_SIZE;
    attr.priority = PWM_TASK_PRIO;

    if (osThreadNew((osThreadFunc_t)pwm_task, NULL, &amp;attr) == NULL) {
        /* Create task fail. */
    }
}

/* Run the pwm_entry. */

app_run(pwm_entry);</code></pre>

<p>其中,结构体pwm_config_t实现了PWM相关参数的设置,包括低电平时间,高电平时间,相位,重复次数,是否连续输出。</p>

<p>演示结果如下:</p>

<p>2dbd4902cf667f6341fe9bcf75728992</p>

秦天qintian0303 发表于 2024-8-9 15:29

<p>这板子应该做成统一了,就跟好看了&nbsp;&nbsp;</p>
页: [1]
查看完整版本: 小熊派BearPi-Pico H2821星闪开发板测评(二)——GPIO与PWM测试