本文介绍的数据结构和 API 可以参考 SDK 中 zyf_gpio.h 文件
typedef enum{ PINNAME_WAKE_IN = 0, PINNAME_AP_READY, PINNAME_W_DISABLE, PINNAME_NET_MODE, PINNAME_NET_STATUS, PINNAME_SD_INS_DET, PINNAME_PCM_IN, PINNAME_PCM_OUT, PINNAME_PCM_SYNC, PINNAME_PCM_CLK, PINNAME_SDC2_DATA3, PINNAME_SDC2_DATA2, PINNAME_SDC2_DATA1, PINNAME_SDC2_DATA0, PINNAME_SDC2_CMD, PINNAME_SPI_CS_N, PINNAME_SPI_MOSI, PINNAME_SPI_MISO, PINNAME_SPI_CLK, PINNAME_I2C_SCL, PINNAME_I2C_SDA, PINNAME_STATUS, PINNAME_RI, PINNAME_DCD, PINNAME_CTS, PINNAME_RTS, PINNAME_DTR, PINNAME_MAX }Enum_PinName; 这些引脚均可做为普通 GPIO 使用,除此之外,还可以复用为其它功能。用作普通 GPIO 使用的时候,参考本文的 API 介绍进行配置。如果用做复用功能时,请参考对应文档进行配置
Enum_PinDirection 配置的是 GPIO 的方向是输入还是输出的。配置为输出可做控制使用如 LED 等,配置为输入可做检测使用如中断检测等。 typedef enum{ PINDIRECTION_IN = 0, PINDIRECTION_OUT = 1 }Enum_PinDirection; 当配置 Enum_PinDirection 为 PINDIRECTION_OUT 或 1 时,Enum_PinPullSel则不用关心,我们只需要关心下面的 Enum_PinLevel。配置为低则 GPIO 输出低电平;配置为高则 GPIO 输出高电平。 typedef enum{ PINLEVEL_LOW = 0, PINLEVEL_HIGH = 1 }Enum_PinLevel; 当配置 Enum_PinDirection 为 PINDIRECTION_IN 或 0 时,Enum_PinLevel 则不用关心,我们只需要关心下面的Enum_PinPullSel。配置为 0 则表示禁用拉动选择;配置为 1 则为下拉输入;配置为 2 则为上拉输入。此时的 GPIO 没有输出控制能力,因为配置的方向是输入。 typedef enum{ PINPULLSEL_DISABLE = 0, // Disable pull selection PINPULLSEL_PULLDOWN = 1, // Pull-down PINPULLSEL_PULLUP = 2 // Pull-up }Enum_PinPullSel;
1.3.1 ZYF_GpioInit 此功能启用指定引脚的 GPIO 功能,并初始化配置,包括方向,电平和拉动选择· 函数原型 int32_t ZYF_GpioInit(Enum_PinName pinName, Enum_PinDirection dir, Enum_PinLevel level, Enum_PinPullSel pullSel );
· 参数 pinName:参考 1.1 GPIO 引脚枚举 dir:参考 1.2 GPIO 配置枚举 level:参考 1.2 GPIO 配置枚举 pullSel:参考 1.2 GPIO 配置枚举· 返回值 ZYF_RET_OK,此函数成功 ZYF_RET_ERR_NOSUPPORTPIN,输入 GPIO 无效 ZYF_RET_ERR_PINALREADYSUBCRIBE,在其他地方正在使用 GPIO。 例如,此 GPIO一直用作 EINT
1.3.2 ZYF_GpioSetLevel 此函数用来设置指定 GPIO 的电平高低· 函数原型 int32_t ZYF_GpioSetLevel(Enum_PinName pinName, Enum_PinLevel level);· 参数 pinName:参考 1.1 GPIO 引脚枚举 level:参考 1.2 GPIO 配置枚举· 返回值 ZYF_RET_OK,此函数成功 ZYF_RET_ERR_NOSUPPORTPIN,输入 GPIO 无效 ZYF_RET_ERR_NORIGHTOPERATE,无法操作,可能是 GPIO 未初始化 ZYF_RET_ERR_NOGPIOMODE,输入的 GPIO 不是 GPIO 模式
1.3.3 ZYF_GpioGetLevel 此函数用来获取指定 GPIO 的电平状态。· 函数原型 int32_t ZYF_GpioGetLevel(Enum_PinName pinName);· 参数 pinName:参考 1.1 GPIO 引脚枚举
· 返回值
指定的 GPIO 的电平值,即非负整数 ZYF_RET_ERR_NOSUPPORTPIN,表示输入的 GPIO 无效
1.3.4 ZYF_GpioSetDirection 此函数用来设置指定 GPIO 的方向· 函数原型 int32_t ZYF_GpioSetDirection(Enum_PinName pinName, Enum_PinDirection dir);· 参数 pinName:参考 1.1 GPIO 引脚枚举 dir:参考 1.2 GPIO 配置枚举· 返回值 ZYF_RET_OK 表示此功能成功。 ZYF_RET_ERR_NOSUPPORTPIN,输入 GPIO 无效。 ZYF_RET_ERR_NORIGHTOPERATE,无法操作,可能是 GPIO 未初始化 ZYF_RET_ERR_NOGPIOMODE,输入的 GPIO 不是 GPIO 模式
1.3.5 ZYF_GpioGetDirection 此函数用来获取指定 GPIO 的方向· 函数原型 int32_t ZYF_GpioGetDirection(Enum_PinName pinName);· 参数 pinName:参考 1.1 GPIO 引脚枚举· 返回值 指定 GPIO 的方向,即非负整数 * ZYF_RET_ERR_NOSUPPORTPIN,输入 GPIO 无效。 * ZYF_RET_ERR_NORIGHTOPERATE,无法操作,可能是 GPIO 未初始化 * ZYF_RET_ERR_NOGPIOMODE,输入的 GPIO 不是 GPIO 模式
1.3.6 ZYF_GpioSetPullSelection 此函数用来设置指定 GPIO 的拉动选择· 函数原型 int32_t ZYF_GpioSetPullSelection(Enum_PinName pinName, Enum_PinPullSel pullSel);· 参数 pinName:参考 1.1 GPIO 引脚枚举 pullSel:参考 1.2 GPIO 配置枚举· 返回值 ZYF_RET_OK 表示此功能成功。 ZYF_RET_ERR_NOSUPPORTPIN,输入 GPIO 无效。 ZYF_RET_ERR_NORIGHTOPERATE,无法操作,可能是 GPIO 未初始化 ZYF_RET_ERR_NOGPIOMODE,输入的 GPIO 不是 GPIO 模式
1.3.7 ZYF_GpioGetPullSelection 此函数用来获取指定 GPIO 的拉动状态· 函数原型 int32_t ZYF_GpioGetPullSelection(Enum_PinName pinName);· 参数 pinName:参考 1.1 GPIO 引脚枚举· 返回值 这是非负整数的拉取选择。 如果成功,返回一个 Enum_PinPullSel 值。否则返回 ZYF_RET_ERR_NOSUPPORTPIN,输入 GPIO 无效。 ZYF_RET_ERR_NORIGHTOPERATE,无法操作,可能是 GPIO 未初始化 ZYF_RET_ERR_NOGPIOMODE,输入的 GPIO 不是 GPIO 模式
1.3.8 ZYF_GpioUninit 此函数用来释放指定的 GPIO,释放后,GPIO 可做其它目的
· 函数原型 int32_t ZYF_GpioUninit(Enum_PinName pinName);· 参数 pinName:参考 1.1 GPIO 引脚枚举· 返回值 ZYF_RET_OK,此函数成功。 ZYF_RET_ERR_NOSUPPORTPIN,输入 GPIO 无效。 ZYF_RET_ERR_BUSSUBBUSY,未用作 GPIO 的 GPIO,由 IIC 或 SPI 使用,此功能无法释放
本章节主要介绍如何在 SDK 中使用 example_gpio.c 单独测试 GPIO 功能。 编译方法:.\examples\build\对应的.bat 文件双击执行或打开就可以编译。 生成文件:.\out\对应目录\hex\M601_example_**.pac
使用 ZYF_GpioInit()初始化需要使用到的 GPIO,配置为输出后,可使用ZYF_GpioGetLevel()获取当前电平状态,使用ZYF_GpioSetLevel()设置电平。
#include "zyf_trace.h" #include "zyf_gpio.h" #include "zyf_app.h" #include "zyf_uart.h" #include "zyf_thread.h" //fixme: //rw err: PINNAME_41_I2C_SCL static Enum_PinName gpiopin[PINNAME_MAX]; static Uart_Param_t g_uart1param; void UartWriteCallBack(void* Param) // general com { Uart_Param_t *uartparam = (Uart_Param_t *)Param; if(Param == NULL) { return; } ZYF_UartWrite(uartparam->port,(uint8_t *)"UartWrite succeed\r\n",strlen("UartWrite succeed\r\n")); ZYF_UartWriteCallbackSwitch(uartparam->port,false); } void UartReadCallBack(void* Param) // { uint32_t recvlen = 0; Uart_Param_t *uartparam = (Uart_Param_t *)Param; ZYF_LOG("Uart%d recv",uartparam->port); while(ZYF_UartRead(uartparam->port, &(uartparam->uartbuf[recvlen]), 1)) { ZYF_LOG("recv :x",uartparam->uartbuf[recvlen]); recvlen++; } ZYF_UartWrite(uartparam->port,uartparam->uartbuf,recvlen); ZYF_UartWriteCallbackSwitch(uartparam->port,true); } static void AppUartInit(void) { int32_t ret; g_uart1param.port = DEBUG_PORT; ZYF_UartRegister(g_uart1param.port, UartReadCallBack,&g_uart1param); ZYF_UartWriteCbRegister(g_uart1param.port,UartWriteCallBack,&g_uart1param); ZYF_UartOpen(g_uart1param.port, 115200, ZYF_FC_NONE); ZYF_LOG("AppUartInit"); return; } void ZYF_GpioTest(void) { int i; for (i = 0; i < PINNAME_MAX; i ++) { ZYF_GpioInit((Enum_PinName)i, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_PULLUP); ZYF_ThreadSleep(10); } uint8_t level; for (i = 0; i < PINNAME_MAX; i ++) { level = ZYF_GpioGetLevel(i); ZYF_LOG("read before GPIO:%d => %d", i, level); ZYF_ThreadSleep(200); ZYF_GpioSetLevel(i, !level); ZYF_LOG("write GPIO:%d => %d", i, !level); ZYF_ThreadSleep(200); level = ZYF_GpioGetLevel(i); ZYF_LOG("read after GPIO:%d => %d", i, level); ZYF_ThreadSleep(200); } ZYF_ThreadSleep(1000); for (i = 0; i < PINNAME_MAX; i ++) { ZYF_GpioUninit(i); } } void TimeThread_Example(void * Param) { ZYF_MsgQ_t *ptMsg; ZYF_AppMsg_t tMsg; int iRet = -1; ptMsg = ZYF_MsgQCreate(10, sizeof(ZYF_AppMsg_t)); ZYF_LOG("thread enter!"); ZYF_GpioTest(); while (1) { ZYF_LOG("in while."); iRet = ZYF_MsgQGet(ptMsg, (void *)&tMsg); if (iRet < 0) { ZYF_LOG("Failed to get msg"); ZYF_ThreadSleep(1000); } } } static void prvInvokeGlobalCtors(void) { extern void (*__init_array_start[])(); extern void (*__init_array_end[])(); size_t count = __init_array_end - __init_array_start; for (size_t i = 0; i < count; ++i) __init_array_start[i](); } int appimg_enter(void *param) { AppUartInit(); ZYF_LOG("application image enter, param 0x%x", param); prvInvokeGlobalCtors(); ZYF_ThreadCreate("UartThread_Example", TimeThread_Example, NULL, ZYF_PRIORITY_HIGH, 10*1024); return 0; } void appimg_exit(void) { OSI_LOGI(0, "application image exit"); }