1 GPIO 相关的数据结构和 API
本文介绍的数据结构和 API 可以参考 SDK 中 zyf_gpio.h 文件
1.1 GPIO 引脚枚举
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 介绍进行配置。如果用做复用功能时,请参考对应文档进行配置
1.2 GPIO 配置枚举
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 GPIO 相关 API
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 使用,此功能无法释放
2 GPIO 例程介绍
本章节主要介绍如何在 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 :%02x",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");
}