小熊派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"> </p>
<p>PCB绘制如下</p>
<p align="center"> </p>
<p>得到最终的扩展板(原谅我部分器件没有到货,但是这篇文章所用到的器件都能得到保证)</p>
<p style="text-align: center;"> </p>
<p><strong><span style="font-size:18px;">LED灯控制</span></strong></p>
<p>由扩展板原理图可知,GPIO11,GPIO12,GPIO13分别控制红绿蓝三色灯,同时,GPIO31控制着板载的LED灯</p>
<p align="center"> </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, &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"> </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"> </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, &channel, 1);
uapi_pwm_open(PWM_CHANNEL, &cfg_led1);
uapi_pwm_config_preload(PWM_GROUP_ID, channel, &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, &cfg_led1);
uapi_pwm_config_preload(PWM_GROUP_ID, channel, &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, &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>
<p>这板子应该做成统一了,就跟好看了 </p>
页:
[1]