Driver: GPIO¶
1 功能概述¶
本文主要介绍PAN1080 EVB板GPIO输入,输出,中断模式的使用方法。
2 环境要求¶
PAN1080 EVB 一块
USB-TypeC 线一条(用于供电和查看串口打印 Log)
硬件接线:
使用 USB 线,将 PC USB 与 EVB USB-TypeC(USB->UART)相连
根据 EVB 核心板芯片的封装不同,使用杜邦线将 EVB 底板上的:
TX0 与 P00 相连, RX0 与 P01 相连(若 EVB 板芯片为 QFN32 或 LQFP64 封装)
TX0 与 P30 相连, RX0 与 P31 相连(若 EVB 板芯片为 QFN48 封装)
PC 软件: 串口调试助手(UartAssist)或终端工具(SecureCRT),波特率921600
3 编译和烧录¶
项目位置:zephyr\samples_panchip\drivers\gpio
使用 ZAL 工具可以对其进行编译、烧录、打开 VS Code 调试等操作。关于 ZAL 工具的详细介绍请参考:Zephyr APP Launcher 工具介绍。
4 演示说明¶
GPIO输入和GPIO中断可以通过串口观察打印。
GPIO输出需要通过逻辑分析仪器观察输出电平。
详情可以参考
5.5 测试现象说明
。
5 开发者说明¶
5.1 GPIO Block Diagram¶
5.2 Zephyr中提供的GPIO工作模式¶
/** Output:典型的输出模式 */
#define OUT_PUSH_PULL 1 //推挽输出,不使能数字输入
#define OUT_PUSH_PULL_IN_DIGTAL 0 //推挽输出,使能数字输入
#define OUT_OPEN_DRAIN 0 //开漏输出,不使能内部的上拉或者下拉电路,1的状态由外部电路决定
#define OUT_OPEN_DRAIN_EXTRA_PULL_UP 0 //开漏输出,使能内部的上拉电路
#define OUT_QUASI_BI_EXTRA_PULL_UP 0 //准双向输出,使能内部的上拉电路;0读时可能需要写1,即确保内部为开漏断开状态
/** Input:典型的输入模式 */
#define IN_DIGTAL 0 //数字输入使能,处于悬空(Floating)
#define IN_DIGTAL_EXTRA_PULL_UP 0 //数字输入使能,使能内部的上拉电路
#define IN_DIGTAL_EXTRA_PULL_DOWN 0 //数字输入使能,使能内部的下拉电路
#define IN_ANALOG 0 //模拟输入,即数字输入关闭
/** Interruption:典型的中断模式 */
#define INT_EDGE_RISING 0 //上升沿中断触发模式
#define INT_EDGE_FALLING 0 //下降沿中断触发模式
#define INT_EDGE_BOTH 0 //边沿触发模式
#define INT_LEVEL_HIGH 0 //高电平中断触发模式
#define INT_LEVEL_LOW 0 //低电平中断触发模式
5.3 测试Case使用说明¶
使能相应的宏为1即打开相应的测试模式case,例如OUT_PUSH_PULL
设置为1,即使能推挽输出测试,详情参考5.2 Zephyr中提供的GPIO工作模式
。注意不支持同时测试多个case,否则会编译失败。
5.4 Sample中GPIO API说明¶
输入输出模式配置¶
/**step1: 获取GPIO端口的port*/
const struct device *port;
port = device_get_binding(PORT);
/**step2: 配置GPIO模式,详细模式参考输入输出模式 */
gpio_pin_configure(port, PIN, GPIO_OUTPUT | GPIO_PUSH_PULL);
/**step3: GPIO读写接口*/
gpio_pin_set(port, PIN, 1); //GPIO设置接口
pin_val = gpio_pin_get(port, PIN); //GPIO读接口
中断模式配置¶
/**step1: 获取GPIO端口的port*/
const struct device *port;
port = device_get_binding(PORT);
/**step2: 配置GPIO模式,此处配置成输入模式 */
gpio_pin_configure(port, PIN, GPIO_OUTPUT);
/**step3: 配置中断模式以及回调函数*/
gpio_init_callback(&gpio_cb, callback_edge, BIT(PIN)); //初始化中断回调函数,添加到gpio_cb
ret = gpio_add_callback(port, &gpio_cb); //将gpio_cb添加到port中
ret = gpio_pin_interrupt_configure(port, PIN, GPIO_INT_EDGE_RISING); //此处中断模式设置为上升沿
//中断回调函数,在触发10次后通过`gpio_pin_interrupt_configure`关闭中断
static void callback_edge(const struct device *port, struct gpio_callback *cb,
gpio_port_pins_t pins)
{
cb_count++;
printk("Detected interrupt on edge:%d\n", cb_count);
if (cb_count >= MAX_INT_CB_COUNT) {
//关闭GPIO中断
gpio_pin_interrupt_configure(port, PIN, GPIO_INT_DISABLE);
printk("Disable GPIO interruption\n");
}
}
关于如何选择GPIO¶
请参考Device Tree
和PINMUX
功能相应文档,该sample选择的是dts中已经设置的led引脚(P21)。
5.5 测试现象说明¶
在测试条件有限时,两个EVB通过该Sample进行互相测试时(箭头左右为不同EVB):
OUT_PUSH_PULL <===> IN_DIGTAL (IN_DIGTAL间隔1秒输出0,1)
OUT_PUSH_PULL_IN_DIGTAL <===> IN_DIGTAL (OUT_PUSH_PULL_IN_DIGTAL, IN_DIGTA均能间隔1秒输出0,1)
OUT_OPEN_DRAIN <===> IN_DIGTAL_EXTRA_PULL_UP(IN_DIGTAL_EXTRA_PULL_UP间隔1秒输出0,1)
OUT_OPEN_DRAIN_EXTRA_PULL_UP <===> IN_DIGTAL(IN_DIGTAL间隔1秒输出0,1)
OUT_QUASI_BI_EXTRA_PULL_UP <===> IN_DIGTAL(IN_DIGTAL间隔1秒输出0,1)
IN_DIGTAL (OUT_PUSH_PULL中已测)
IN_DIGTAL_EXTRA_PULL_UP (上电时读取默认值为1;然后将P21连接到GND,读取值为0)
IN_DIGTAL_EXTRA_PULL_DOWN (上电时读取默认值为0;然后将P21连接到VCC,读取值为1)
IN_ANALOG (未做功能测试,根据相关模拟case自行测试,例如ADC)
INT_EDGE_RISING <===> OUT_PUSH_PULL (INT_EDGE_RISING 间隔2秒输出中断打印)
INT_EDGE_FALLING <===> OUT_PUSH_PULL (INT_EDGE_FALLING 间隔2秒输出中断打印)
INT_EDGE_BOTH <===> OUT_PUSH_PULL (INT_EDGE_BOTH 间隔1秒输出中断打印)
INT_LEVEL_HIGH <===> OUT_PUSH_PULL (INT_LEVEL_HIGH 在OUT_PUSH_PULL初始化一直输出中断打印,直到关闭中断)
INT_LEVEL_LOW <===> OUT_PUSH_PULL (INT_LEVEL_LOW 在OUT_PUSH_PULL初始化后1秒一直输出中断打印,直到关闭中断)
6 RAM/Flash资源使用情况¶
Memory region Used Size Region Size %age Used
FLASH: 17236 B 256 KB 6.58%
SRAM: 3888 B 64 KB 5.93%