当前文档版本为 v0.4.1,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

Driver: GPIO

1 功能概述

本文主要介绍PAN1080 EVB板GPIO输入,输出,中断模式的使用方法。

2 环境要求

  • board: pan1080a_afld_evb

  • uart (波特率921600): 显示串口log

3 编译和烧录

项目位置:zephyr\samples_panchip\drivers\gpio

目前可使用ZAL工具或quick build脚本进行编译和下载。

脚本位置:quick_build_samples\drivers\gpio.bat

打开脚本后默认会编译项目,编译完成时,可输入字符进行后续下载等操作:

Input the keyword to continue:
  'b' build                         编译项目
  'r' make clean and rebuild        重新编译项目
  'f' flash download                下载
  'e' erase chip                    擦除芯片
  'o' open project by VS Code       打开 `VS Code`,可查看源码,执行编译下载等
  others exit                       退出
wait input:

4 演示说明

  1. GPIO输入和GPIO中断可以通过串口观察打印。

  2. GPIO输出需要通过逻辑分析仪器观察输出电平。

  3. 详情可以参考5.5 测试现象说明

5 开发者说明

5.1 GPIO Block Diagram

image

GPIO/PINMUX模块框图

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 TreePINMUX功能相应文档,该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秒一直输出中断打印,直到关闭中断)