|
上篇帖子中,我们介绍了如何安装和激活SEGGER Embedded Studio,以及使用Embedded Studio进行编译、调试。本篇将会介绍如何点亮开发板上的三色LED灯,以及如何使用开发板上的LED控制三色LED灯。
在hpm_sdk/samples子目录下创建gpio_led目录,将hello_world目录内的src目录和CMakeLists.txt复制到gpio_led目录下(当然,嫌麻烦直接在hello_world的基础上进行修改也是可以的),并将src/hello_world.c重命名为gpio_led.c,并将文件内容修改为:
#include <stdio.h>
#include "board.h"
#include "hpm_gpio_drv.h"
#define LED_FLASH_PERIOD_IN_MS 500
int main(void)
{
int u;
board_init();
board_init_led_pins();
//board_timer_create(LED_FLASH_PERIOD_IN_MS, board_led_toggle);
gpio_write_pin(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, 0);
gpio_write_pin(BOARD_G_GPIO_CTRL, BOARD_G_GPIO_INDEX, BOARD_G_GPIO_PIN, 0);
gpio_write_pin(BOARD_B_GPIO_CTRL, BOARD_B_GPIO_INDEX, BOARD_B_GPIO_PIN, 0);
printf("gpio_led start...\\n");
while(1)
{
gpio_write_pin(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, 0);
board_delay_ms(LED_FLASH_PERIOD_IN_MS);
gpio_write_pin(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, 1);
board_delay_ms(LED_FLASH_PERIOD_IN_MS);
}
return 0;
}
CMakeLists.txt文件内容修改为:
# Copyright 2021 hpmicro
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.13)
find_package(hpm-sdk REQUIRED HINTS $ENV{HPM_SDK_BASE})
project(gpio_led)
sdk_compile_definitions(-DBOARD_SHOW_CLOCK=0)
sdk_app_src(src/gpio_led.c)
generate_ses_project()
在hpm_sdk\samples\gpio_led目录运行:generate_project -b hpm6750evkmini -t flash_xip -f命令生产项目文件。
使用SEGGER Embedded Studio打开生产的项目文件,如下图所示:
编译、运行后,就可以看到红色LED闪烁了:
查阅原理图,可以找到三色LED相关的原理图如下:
可以看到三种颜色的控制管脚信息如下:
继续在原理图中搜索PWM1.P0、PWM1.P1和PWM0.P7,可以找到:
这里标号U1的就是HPM6750芯片,PWM1.P0、PWM1.P1和PWM0.P7和引脚标号的对应关系如下:
上面的分析,这和board.h文件里面的代码一致:
#define BOARD_R_GPIO_CTRL HPM_GPIO0
#define BOARD_R_GPIO_INDEX GPIO_DI_GPIOB
#define BOARD_R_GPIO_PIN 19
#define BOARD_G_GPIO_CTRL HPM_GPIO0
#define BOARD_G_GPIO_INDEX GPIO_DI_GPIOB
#define BOARD_G_GPIO_PIN 18
#define BOARD_B_GPIO_CTRL HPM_GPIO0
#define BOARD_B_GPIO_INDEX GPIO_DI_GPIOB
#define BOARD_B_GPIO_PIN 20
将gpio_led.c修改为:
#include <stdio.h>
#include "board.h"
#include "hpm_gpio_drv.h"
#define LED_FLASH_PERIOD_IN_MS 500
int main(void)
{
int u;
board_init();
board_init_led_pins();
//board_timer_create(LED_FLASH_PERIOD_IN_MS, board_led_toggle);
gpio_write_pin(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, 0);
gpio_write_pin(BOARD_G_GPIO_CTRL, BOARD_G_GPIO_INDEX, BOARD_G_GPIO_PIN, 0);
gpio_write_pin(BOARD_B_GPIO_CTRL, BOARD_B_GPIO_INDEX, BOARD_B_GPIO_PIN, 0);
printf("gpio_led start...\\n");
while(1)
{
gpio_write_pin(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, 1);
board_delay_ms(LED_FLASH_PERIOD_IN_MS);
gpio_write_pin(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, 0);
board_delay_ms(LED_FLASH_PERIOD_IN_MS);
gpio_write_pin(BOARD_G_GPIO_CTRL, BOARD_G_GPIO_INDEX, BOARD_G_GPIO_PIN, 1);
board_delay_ms(LED_FLASH_PERIOD_IN_MS);
gpio_write_pin(BOARD_G_GPIO_CTRL, BOARD_G_GPIO_INDEX, BOARD_G_GPIO_PIN, 0);
board_delay_ms(LED_FLASH_PERIOD_IN_MS);
gpio_write_pin(BOARD_B_GPIO_CTRL, BOARD_B_GPIO_INDEX, BOARD_B_GPIO_PIN, 1);
board_delay_ms(LED_FLASH_PERIOD_IN_MS);
gpio_write_pin(BOARD_B_GPIO_CTRL, BOARD_B_GPIO_INDEX, BOARD_B_GPIO_PIN, 0);
board_delay_ms(LED_FLASH_PERIOD_IN_MS);
}
return 0;
}
重新编译、运行,
就可以看到红绿蓝依次闪烁了:
接下来,我们尝试使用GPIO读取PBUTN和WBUTN两个按键的状态,并输出到串口中。
首先需要在原理图中找到,按键相关的原理图:
循环读取并打印PBUTN和WBUTN按键状态的代码段:
uint32_t count = 0;
while (1)
{
count++;
uint8_t pbutn_value = gpio_read_pin(HPM_BGPIO, GPIO_DI_GPIOZ, 2);
uint8_t wbutn_value = gpio_read_pin(HPM_BGPIO, GPIO_DI_GPIOZ, 3);
printf("[%d] pbutn_value=%d, wbutn_value=%d\\n", count, pbutn_value, wbutn_value);
board_delay_ms(500);
}
经测试发现,默认情况下,这两个按键分别是长按关机和长按休眠的功能。
可以使用如下代码段,将这两个引脚功能设置为普通GPIO,并设置为内部上拉状态:
static void init_butn_as_gpio()
{
uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1);
// 设置PZ02、PZ03为GPIO功能
HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_BGPIO_Z_02;
HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = IOC_PZ03_FUNC_CTL_BGPIO_Z_03;
// 设置PZ02、PZ03为GPIO的模式为 内部上拉
HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = pad_ctl;
HPM_IOC->PAD[IOC_PAD_PZ03].PAD_CTL = pad_ctl;
}
本小节实现——通过PBUTN和WBUTN两个按键,切换三色LED等的颜色:
完整代码:
#include <stdio.h>
#include "board.h"
#include "hpm_gpio_drv.h"
static void init_butn_as_gpio()
{
uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1);
// 设置PZ02、PZ03为GPIO功能
HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_BGPIO_Z_02;
HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = IOC_PZ03_FUNC_CTL_BGPIO_Z_03;
// 设置PZ02、PZ03为GPIO的模式为 内部上拉
HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = pad_ctl;
HPM_IOC->PAD[IOC_PAD_PZ03].PAD_CTL = pad_ctl;
}
void app_led_write(uint32_t index, uint8_t state)
{
switch (index)
{
case 0:
gpio_write_pin(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, state);
break;
case 1:
gpio_write_pin(BOARD_G_GPIO_CTRL, BOARD_G_GPIO_INDEX, BOARD_G_GPIO_PIN, state);
break;
case 2:
gpio_write_pin(BOARD_B_GPIO_CTRL, BOARD_B_GPIO_INDEX, BOARD_B_GPIO_PIN, state);
break;
default:
/* Suppress the toolchain warnings */
break;
}
}
uint32_t app_led_next(uint32_t index)
{
return (index + 1) % 3;
}
uint32_t app_led_prev(uint32_t index)
{
return (index + 3 - 1) % 3;
}
int main(void)
{
uint32_t current = 0, next = 0;
board_init();
board_init_led_pins();
init_butn_as_gpio();
while (1)
{
// 读取按键状态
uint8_t pbutn_value = gpio_read_pin(HPM_BGPIO, GPIO_DI_GPIOZ, 2);
uint8_t wbutn_value = gpio_read_pin(HPM_BGPIO, GPIO_DI_GPIOZ, 3);
// 按键状态处理
if (pbutn_value == 0) {
printf("pbutn_value=%d, wbutn_value=%d\\n", pbutn_value, wbutn_value);
next = app_led_next(current);
app_led_write(current, 0);
// app_led_write(next, 1);
current = next;
} else if (wbutn_value == 0) {
printf("pbutn_value=%d, wbutn_value=%d\\n", pbutn_value, wbutn_value);
next = app_led_prev(current);
app_led_write(current, 0);
// app_led_write(next, 1);
current = next;
}
app_led_write(current, 1); // 放这里,第一次能够点亮红色
// 延时,控制扫描频率
board_delay_ms(100);
}
return 0;
}
效果演示:
点灯的过程中发现,SDK 0.9.0(sdk 0.10.0也有这个问题)里面hpm5760evkmini的LED亮灭的高低电平搞反了。我已经向先楫反馈了这个问题,从他们那里了解到HPM6750EVKMINI板子改版过,旧版本是低电平点亮,新版本是高电平点亮,这块的代码没有更新。他们说会在下一个版本中修复这个问题,目前解决这个问题需要修改几处代码,改动都很简单,具体可以参考我的这条提交记录:
(PS:这个代码仓是我个人建立的用于测试HPM6750的,欢迎Star支持~,另外这个HPM6750是我建立的一个码云的组织,RT-Thread的测试也会放上去,并陆续更新,欢迎关注~)