小安派|04 GPIO
本文首先介绍LHAL库的概念,继而使用小安排的GPIO外设。并使用raspberry pi pico作为逻辑分析仪来对GPIO的输出做采样捕获验证。
1. LHAL库外设
博流的LHAL库驱动外设进行了统一的封装。下列表格则是从SDK文档中摘取出来,列举出来小安排使用的BL616芯片外设的在LHAL库中的支持。 其中: √表示已支持,×表示未支持,-表示该芯片没有该外设
parameter | BL616/BL618 |
---|---|
ADC | √ |
CAM | × |
CKS | √ |
DAC | √ |
DMA | √ |
EFUSE | √ |
EMAC | √ |
FLASH | √ |
GPIO | √ |
I2C | √ |
IR | √ |
MJPEG | √ |
PWM_v1 | - |
PWM_v2 | √ |
RTC | √ |
SEC_AES | √ |
SEC_SHA | √ |
SEC_TRNG | √ |
SEC_PKA | √ |
SPI | √ |
TIMER | √ |
UART | √ |
USB_v1 | - |
USB_v2 | √ |
WDG | √ |
上述表格中的所有外设都是使用同一个结构体对其进行配置的:
struct bflb_device_s {
const char *name; //外设名称
uint32_t reg_base; //外设寄存器基地址
uint8_t irq_num; //外设中断号
uint8_t idx; //外设 id,例如 UART0、UART1
uint8_t sub_idx; //外设子id,例如 DMA0_CH0、DMA0_CH1
uint8_t dev_type; //外设类型
void *user_data; //用户数据
};
或者外设对象提供了两个方法: 1.通过外设名称获取
struct bflb_device_s *bflb_device_get_by_name(const char *name)
2.通过外设类型和外设id获取
struct bflb_device_s *bflb_device_get_by_id(uint8_t type, uint8_t idx)
这两个函数的实现可以在aithinker_Ai-M6X_SDK\drivers\lhal\config\bl616\device_table.c
中找到,如下图所示:
2. GPIO配置
有了上面的基础了解之后我们大概就清楚了,如果想要使用gpio外设,那么首先我们就需要get到gpio设备。随后就是用get到的设备进行初始化。sdk中提供的初始化的函数定义如下:
void bflb_gpio_init(struct bflb_device_s *dev, uint8_t pin, uint32_t cfgset);
- 第一个参数就是前面我们通过get得到的gpio设备;
- 第二个参数是对应到硬件上的端口号;
- 第三个参数是将这个pin设置成具体的模式和功能(包括gpio mode、gpio function、gpio pupd、gpio smt、gpio drive)。这些设置可以通过位或的方式进行设置。下列是从sdk中摘录的具体的每个域的设置参数。
// gpio mode
#define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* Input Enable */
#define GPIO_OUTPUT (1 << GPIO_MODE_SHIFT) /* Output Enable */
#define GPIO_ANALOG (2 << GPIO_MODE_SHIFT) /* Analog Enable */
#define GPIO_ALTERNATE (3 << GPIO_MODE_SHIFT) /* Alternate Enable */
// gpio pupd
#define GPIO_FLOAT (0 << GPIO_PUPD_SHIFT) /* No pull-up, pull-down */
#define GPIO_PULLUP (1 << GPIO_PUPD_SHIFT) /* Pull-up */
#define GPIO_PULLDOWN (2 << GPIO_PUPD_SHIFT) /* Pull-down */
// gpio smt
#define GPIO_SMT_DIS (0 << GPIO_SMT_SHIFT)
#define GPIO_SMT_EN (1 << GPIO_SMT_SHIFT)
// gpio drive
#define GPIO_DRV_0 (0 << GPIO_DRV_SHIFT)
#define GPIO_DRV_1 (1 << GPIO_DRV_SHIFT)
#define GPIO_DRV_2 (2 << GPIO_DRV_SHIFT)
#define GPIO_DRV_3 (3 << GPIO_DRV_SHIFT)
// gpio init trig mode
#define GPIO_INT_TRIG_MODE_SYNC_FALLING_EDGE 0
#define GPIO_INT_TRIG_MODE_SYNC_RISING_EDGE 1
#define GPIO_INT_TRIG_MODE_SYNC_LOW_LEVEL 2
#define GPIO_INT_TRIG_MODE_SYNC_HIGH_LEVEL 3
#define GPIO_INT_TRIG_MODE_SYNC_FALLING_RISING_EDGE 4
#define GPIO_INT_TRIG_MODE_ASYNC_FALLING_EDGE 8
#define GPIO_INT_TRIG_MODE_ASYNC_RISING_EDGE 9
#define GPIO_INT_TRIG_MODE_ASYNC_LOW_LEVEL 10
#define GPIO_INT_TRIG_MODE_ASYNC_HIGH_LEVEL 11
// gpio uart function
#define GPIO_UART_FUNC_UART0_RTS 0
#define GPIO_UART_FUNC_UART0_CTS 1
#define GPIO_UART_FUNC_UART0_TX 2
#define GPIO_UART_FUNC_UART0_RX 3
#define GPIO_UART_FUNC_UART1_RTS 4
#define GPIO_UART_FUNC_UART1_CTS 5
#define GPIO_UART_FUNC_UART1_TX 6
#define GPIO_UART_FUNC_UART1_RX 7
顺便看看和初始化相关的几个函数
void bflb_gpio_deinit(struct bflb_device_s *dev, uint8_t pin); //反初始化,相当于回到init之前的状态。io设置为浮空
void bflb_gpio_set(struct bflb_device_s *dev, uint8_t pin); //设置为高电平
void bflb_gpio_reset(struct bflb_device_s *dev, uint8_t pin); //设置为低电平
bool bflb_gpio_read(struct bflb_device_s *dev, uint8_t pin); //读取io电平
3. GPIO配置示例
现在我们就来找一个io对其进行配置,让其间歇性的输出高低电平。随后使用逻辑分析仪来验证我们程序是否正常。 找到小安派的原理图,我们看看IO0是否引出了。 从上图中看到IO0对应对应原理图中标号为I2C_SCL_TOP的网络,我们直接在原理图文件里面搜索,可以找到在J9这个连接件上是接着I2C_SCL_TOP的。 那对应在板子的哪个位置呢?我们再来打开小安派的PCB文件,为了方便查看,先移除掉覆铜。这就看到了这个I2C_SCL_TOP对应在板子上的位置了。 很幸运,这个接口是可以连接的。那么我们就直接使用IO0进行配置了。
#include "bflb_gpio.h"
#include "bflb_mtimer.h"
#include "board.h"
struct bflb_device_s *gpio;
#define gpio_test GPIO_PIN_0
int main(void)
{
board_init();
//获取gpio设备
gpio = bflb_device_get_by_name("gpio");
//配置io 0 为上拉 输出
bflb_gpio_init(gpio, gpio_test, GPIO_OUTPUT | GPIO_PULLUP);
while (1)
{
bflb_gpio_set(gpio, gpio_test); // 拉高
bflb_mtimer_delay_ms(100); // 延时100ms
bflb_gpio_reset(gpio, gpio_test); // 拉低
bflb_mtimer_delay_ms(100);
}
}
将上述代码编译烧录到小安派。接下来就使用rp2040做的逻辑分析仪来测量IO0的输出。
4. 使用逻辑分析仪验证
树莓派pico烧入逻辑分析仪固件,插入到电脑上。配置好plusview。(这个过程不详述。)
将pico的gnd和GP2分别和小安派的GND和I2C_SCL_TOP连接。
运行逻辑分析仪,就可以抓到如下的波形:
从波形中可以看到,电平变化的间隔正好是100ms和我们的程序中的是完全一致的。
至此,gpio功能我们就了解了。
- 原文作者:Binean
- 原文链接:https://bzhou830.github.io/post/20230908%E5%B0%8F%E5%AE%89%E6%B4%BE04/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。