文章目录
前言
我们在使用USB转串口设备时候不仅会使用串口通讯功能,有时候还会用到芯片的GPIO功能,如设置GPIO输入、输出功能。支持GPIO设置的芯片型号有CH9101、CH9102、CH9103、CH9104、CH347、CH344、CH348等型号。下面将介绍如何使用CH343PT库中函数去配置上述芯片的GPIO输入、输出功能。
一、配置GPIO功能函数简介
有两套设置GPIO函数,设置CH9101、CH9102、CH9103、CH344和CH347使用CH910x_XX函数,设置CH348使用CH348_XX函数。
1.1 配置GPIO函数(适应CH910X、CH344、CH347)
①配置GPIO的功能和I/O方向
UCHAR WINAPI CH910x_GpioConfig(
HANDLE iPortH,
ChipPropertyS* iChipProperty,
ULONG iEnable,
ULONG iFuncSet,
ULONG iSetDirOut);
参数IPortH为串口句柄值;
参数iChipProperty芯片属性信息,具体介绍可参考我的文章;
参数iEnable为位使能:以位对应引脚号,位0对应GPIO0,位1对应GPIO1;某位为1,表示iGpioFunc,iSetDirOut对应位有效
参数iFuncSet为功能设置:某位值为0,表示对应引脚为芯片默认功能使用;为1,表示对应引脚作为GPIO功能使用;
参数iSetDirOut为GPIO脚方向设置:某位为0表示对应引脚方向为输入;某位为1表示对应引脚方向为输出。
②获取GPIO引脚配置:引脚功能、方向、电平
UCHAR WINAPI CH910x_GetGpioConfig(
HANDLE iPortH,
ChipPropertyS *iChipProperty,
PULONG FuncSet,
PULONG SetDirOut,
PULONG SetDataOut);
参数IPortH为串口句柄值;
参数iChipProperty芯片属性信息,可为NULL,具体介绍可参考我的文章;
参数FuncSet为功能设置:某位值为0,表示对应引脚为芯片默认功能使用;为1,表示对应引脚作为GPIO功能使用;
参数SetDirOut为GPIO脚方向设置:某位为0表示对应引脚方向为输入;某位为1表示对应引脚方向为输出;
参数SetDataOut为GPIO脚电平值:1表示高电平;0表示低电平。
③设置GPIO引脚电平状态
使用该函数可以设置GPIO引脚为输出高电平或输出低电平功能。
UCHAR WINAPI CH910x_GpioSet(
HANDLE iPortH,
ChipPropertyS* iChipProperty,
ULONG iEnable,
ULONG iSetDataOut );
参数IPortH为串口句柄值;
参数iChipProperty芯片属性信息;
参数iEnable为数据有效标志,位序号与GPIOx的序号对应,位值为1表示iSetDataOut的对应位数据有效,为0表示数据无效;
参数iSetDataOut IO输出数据,如果GPIO方向为输出,那么某位清0时对应引脚输出低电平,某位置1时对应引脚输出高电平
④读取GPIO引脚电平状态
UCHAR WINAPI CH910x_GpioGet(
HANDLE iPortH,
ChipPropertyS* iChipProperty,
PULONG iStatus );
参数iPortH为串口句柄值;
参数iChipProperty芯片属性信息;
参数iStatus为引脚状态,其GPIOx序号对应数据位号。如GPIO1,对应iStatus值中的bit1,可用CH910x_GPIO_xx位掩码取值。
1.2 配置GPIO函数(适应CH348)
①获取GPIO配置:功能和I/O方向,输出脚默认值
UCHAR WINAPI CH348_GetGpioConfig(
HANDLE iPortH, // 串口句柄值
ChipPropertyS *ChipProperty, // 芯片属性值
ULONGLONG *FuncSet, // 功能设置:某位值为0,表示对应引脚为芯片默认功能使用;为1,表示对应引脚作为GPIO功能使用;
ULONGLONG *SetDirOut, // GPIO脚方向设置:某位为0表示对应引脚方向为输入;某位为1表示对应引脚方向为输出
ULONGLONG *SetDataOut); // IO输出数据,如果GPIO方向为输出,那么某位清0时对应引脚输出低电平,某位置1时对应引脚输出高电平
②配置GPIO的功能和I/O方向
//iEnable,iFuncSet,iSetDirOut为64位变量,位序号与GPIO引脚号对应。
//建议使用前先调用CH348_GetGpioConfig获取iFuncSet,iSetDirOut初值后再进行设置
UCHAR WINAPI CH348_GpioConfig(
HANDLE iPortH, // 串口句柄值
ChipPropertyS* iChipProperty, // 芯片属性值
ULONGLONG iEnable, // 位使能:以位对应引脚号,位0对应GPIO0,位1对应GPIO1;某位为1,表示iGpioFunc,iSetDirOut对应位有效
ULONGLONG iFuncSet, // 功能设置:某位值为0,表示对应引脚为芯片默认功能使用;为1,表示对应引脚作为GPIO功能使用;
ULONGLONG iSetDirOut, // GPIO脚方向设置:某位为0表示对应引脚方向为输入;某位为1表示对应引脚方向为输出
ULONGLONG iSetDataOut); // IO输出数据,如果GPIO方向为输出,那么某位清0时对应引脚输出低电平,某位置1时对应引脚输出高电平
③设置某个GPIO引脚电平状态,相应引脚需开启GPIO功能
UCHAR WINAPI CH348_GpioSet(
HANDLE iPortH, // 串口句柄值
ChipPropertyS* iChipProperty, // 芯片属性值
UCHAR iGpioIndex, // GPIO脚序号,0-63
UCHAR iGpioLevel ); // GPIO电平,1为高电平;1:低电平
④设置多个GPIO引脚电平状态,相应引脚需开启GPIO功能
UCHAR WINAPI CH348_GpioMSet(
HANDLE iPortH, // 串口句柄值
ChipPropertyS* iChipProperty, // 芯片属性值
ULONGLONG iGpioMIndex, // GPIO序号掩码,位0-63
ULONGLONG iGpioMLevel); // GPIO电平掩码,与上iGpioMIndex位置对应。1:高电平,0:低电平
⑤获取某个GPIO引脚电平状态,相应引脚需开启GPIO功能
UCHAR WINAPI CH348_GpioGet(
HANDLE iPortH, // 串口句柄值
ChipPropertyS* iChipProperty, // 芯片属性值
UCHAR iGpioIndex, // GPIO脚序号 0-63
PUCHAR GpioLevel ); // GPIO电平,1为高电平;1:低电平
二、GPIO配置Demo
2.1 使用CH910x_XX函数配置GPIO
配置USB转串口设备的GPIO步骤如下:
①打开串口;
②调用CH343PT_GetChipProperty函数获取芯片功能信息,如芯片型号,芯片型号字符串,芯片可配置的GPIO数量等信息(具体可以参考该篇文章);
③读GPIO默认配置,使用函数CH910x_GetGpioConfig;
④GPIO功能和IO方向配置(IO方向分为输入和输出),使用函数CH910x_GpioConfig;
⑤设置电平状态(高电平和低电平),使用函数CH910x_GpioSet,IO方向为输出时使用该函数;
⑥获取GPIO引脚电平状态,使用函数CH910x_GpioGet;
⑦关闭串口。
2.2 使用CH348_XX函数配置GPIO
配置USB转串口设备的GPIO步骤如下:
①打开串口;
②调用CH343PT_GetChipProperty函数获取芯片功能信息,如芯片型号,芯片型号字符串,芯片可配置的GPIO数量等信息;
③读GPIO默认配置,使用函数CH348_GetGpioConfig;
④GPIO功能和IO方向配置(IO方向分为输入和输出),使用函数CH348_GpioConfig;
⑤设置电平状态(高电平和低电平),使用函数CH348_GpioSet(设置某个GPIO电平状态)或者CH348_GpioMSet(设置多个引脚GPIO状态),IO方向为输出时使用该函数;
⑥获取GPIO引脚电平状态,使用函数CH348_GpioGet或者CH348_GpioMGet;
⑦关闭串口。
三、软件实现
使用VC6++新建一个对话框,界面如下。
⑴插入CH9102F,打开串口,界面如下:
从图中可知,芯片型号为CH9102F,共有5个GPIO。
⑵选择配置GPIO3引脚为输出功能,设置引脚为低电平(界面设置:需勾选引脚功能、IO方向、IO状态取消勾选),然后点击配置芯片GPIO按钮,设置成功后再点击设置GPIO电平按钮,设置成功后可以用万用表量一下GPIO3是否为地电平(TTL电平),如果为低电平则设置成功,否则设置失败。
如果设置GPIO电平位高电平,勾选IO状态复选框,重复上述步骤即可。
⑶设置GPIO3为输入功能,勾选默认功能和IO状态复选框,IO方向复选框取消勾选。接下来点击配置芯片GPIO按钮,设置成功后点击获取GPIO电平按钮,获取GPIO3引脚电平状态。如果GPIO引脚接地,点击获取GPIO电平按钮,此时IO状态复选框被取消勾选。同理GPIO电平是高电平,点击获取GPIO电平按钮,IO状态复选框会被勾选上。
⑷需注意CH9102X和CH9101U型号的GPIO设置,CH9101U没有GPIO5需过滤,CH9102X没有GPIO4需过滤。插入CH9102X界面如下:
从图上可以看到CH9102X没有GPIO4共6个GPIO,需要使用结构体ChipPropertyS去判断打开的设备是否为CH9102X或者是CH910U,然后过滤相应的GPIO,以免设置错误。
⑸设置CH348的GPIO输出和输入功能,也是用上述同样的方法去设置。
四、代码实现
//main.cpp
#include "stdafx.h"
#include "resource.h"
#include <stdio.h>
#include <string>
#include "CH343PT.H"
#pragma comment (lib,"CH343PT")
HWND AfxMainHwnd; //主窗体句柄
ChipPropertyS ChipPro = {0};
HANDLE hCom; //串口句柄
UCHAR ChipType;
UCHAR TempGpioCount; //储存GPIO数
ULONG GpioEnable,GpioDir,GpioSta; //CH910x
ULONGLONG CH348FuncSet=0,CH348SetDirOut=0,CH348SetDataOut=0;
//获取串口友好名称friendlyName
VOID GetComFriendlyName()
{
INT wImageIdx = 0;
SHORT wItem = 0;
CHAR szBuf[MAX_PATH] = { 0 };
TCHAR szComName[MAX_PATH] = { 0 };
SendDlgItemMessage(AfxMainHwnd,IDC_Com,CB_RESETCONTENT,0,0); //清除组合框列表
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); //构建系统存在的所有设备列表
if (hDevInfo == INVALID_HANDLE_VALUE)
{
return;
};
SP_DEVINFO_DATA SpDevInfoData = { 0 };
SpDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &SpDevInfoData); i++)
{
if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &SpDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, sizeof(szBuf), 0))
{
continue;
}
else
{
if (strcmp(szBuf, "Ports") != 0) //过滤端口,只取COM
{
continue;
}
}
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &SpDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szComName, sizeof(szComName), 0))
{
ComCounts++;
SendDlgItemMessage(AfxMainHwnd,IDC_AllCom,CB_ADDSTRING,0,(LPARAM)szComName); //向组合框中添加获取的设备友好名称
}
}
SendDlgItemMessage(AfxMainHwnd,IDC_AllCom,CB_SETCURSEL,0,0);
if(hDevInfo)
SetupDiDestroyDeviceInfoList(hDevInfo); //释放资源
}
//打开串口
BOOL OpenCom()
{
CHAR TempBuf[64] = {0};
INT i,BegainSer,EndSer,Len;
std::string strTemp,strComName;
CHAR ComName[16] = "";
CHAR tempBuf[256] = "";
CHAR buf[256] = "";
BOOL Retval;
//提取设备友好名称中的COM号
GetDlgItemText(AfxMainHwnd,IDC_Com,tempBuf,sizeof(tempBuf));
Len =strlen(tempBuf);
strTemp = tempBuf;
BegainSer = strTemp.find('(');
EndSer = strTemp.find(')');
for(i=0; i<EndSer-BegainSer-1; i++)
{
ComName[i] = tempBuf[BegainSer+1+i];
}
strComName += "\\\\.\\";
strComName += ComName;
hCom = CreateFile((LPCTSTR)strComName.c_str(),GENERIC_READ|GENERIC_WRITE,
0,NULL,OPEN_EXISTING,
NULL,
NULL);
if(hCom == INVALID_HANDLE_VALUE)
{
DbgPrint("打开串口失败!");
return FALSE;
}
ChipType = CH343PT_GetChipProperty(hCom,&ChipPro); //获取串口芯片信息
Retval = (ChipType!=0xFF);
if(!Retval)
{
DbgPrint("芯片信息获取失败!");
CloseHandle(hCom);
hCom= INVALID_HANDLE_VALUE;
return FALSE;
}
if((ChipPro.ChipType == USER_TYPE_CH9101U) || (ChipPro.ChipType == USER_TYPE_CH9102X))
TempGpioCount = ChipPro.GpioCount + 1; //CH9101U没有GPIO5,CH9102X没有GPIO4,界面需禁用对应的GPIO选项
else
TempGpioCount = ChipPro.GpioCount;
return TRUE;
}
//关闭串口
BOOL CloseCom()
{
if (INVALID_HANDLE_VALUE != hCom)
{
CloseHandle(hCom);
hCom = INVALID_HANDLE_VALUE;
}
return TRUE;
}
//获取芯片属性信息
VOID GetChipInfo()
{
CHAR ChipTypeInfo[512] = "";
CHAR TempStr[64] = "";
if(ChipType != 0xFF)
{
sprintf(ChipTypeInfo,"芯片型号: %s, 共有%d个GPIO可配置", ChipPro.ChipTypeStr, ChipPro.GpioCount);
sprintf(TempStr,"%s GPIO(%d)设置",ChipPro.ChipTypeStr, ChipPro.GpioCount);
SetDlgItemText(AfxMainHwnd,IDC_DevInfo,ChipTypeInfo);
SetDlgItemText(AfxMainHwnd,1300,TempStr);
}
}
//添加GPIO
VOID InsertGPIO()
{
int i;
CHAR tempBuf[64] = "";
if(ChipPro.GpioCount)
{
for(i = 0; i < TempGpioCount; i++)
{
memset(tempBuf,0,sizeof(tempBuf));
if(ChipPro.ChipType == USER_TYPE_CH9101U && i==5)
continue;
if(ChipPro.ChipType == USER_TYPE_CH9102X && i==4)
continue;
sprintf(tempBuf,"GPIO%d",i);
SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_ADDSTRING,0, (LPARAM)tempBuf);
}
}
SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_SETCURSEL,0,0);
}
//读GPIO配置值
BOOL CH910xReadGpioConfig()
{
UCHAR RetVal;
int GpioIndex;
//获取GPIO配置,方向,电平大小
RetVal = CH910x_GetGpioConfig(hCom,&ChipPro,&GpioEnable,&GpioDir,&GpioSta);
if( RetVal != CH910x_SUCCESS )
{
DbgPrint("CH910x_GetGpioConfig配置失败!");
return FALSE;
}
DbgPrint("CH910x_GetGpioConfig配置成功!");
GpioIndex = SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_GETCURSEL,0,0); //获取GPIO下标
if(ChipPro.ChipType == USER_TYPE_CH9101U && GpioIndex == 5) //CH9101U没有GPIO5需过滤
GpioIndex += 1;
if(ChipPro.ChipType == USER_TYPE_CH9102X && GpioIndex >= 4) //CH9102X没有GPIO4需过滤
GpioIndex += 1;
CheckDlgButton(AfxMainHwnd,IDC_EnableGpio,(GpioEnable & (1<<GpioIndex))?BST_CHECKED:BST_UNCHECKED);
CheckDlgButton(AfxMainHwnd,IDC_GpioDir,(GpioDir & (1<<GpioIndex))?BST_CHECKED:BST_UNCHECKED);
CheckDlgButton(AfxMainHwnd,IDC_GpioLevel,(GpioSta & (1<<GpioIndex))?BST_CHECKED:BST_UNCHECKED);
return TRUE;
}
VOID CH348ReadGpioConfig()
{
UCHAR RetVal = 0;
int GpioIndex;
RetVal = CH348_GetGpioConfig(hCom,&ChipPro,&CH348FuncSet,&CH348SetDirOut,&CH348SetDataOut);
if(RetVal!=CH910x_SUCCESS)
{
DbgPrint("CH348_GetGpioConfig设置成功!");
return;
}
DbgPrint("CH348_GetGpioConfig设置成功!");
GpioIndex = SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_GETCURSEL,0,0);
CheckDlgButton(AfxMainHwnd,IDC_EnableGpio,(CH348FuncSet & (1<<GpioIndex))?BST_CHECKED:BST_UNCHECKED);
CheckDlgButton(AfxMainHwnd,IDC_GpioDir,(CH348SetDirOut & (1<<GpioIndex))?BST_CHECKED:BST_UNCHECKED);
CheckDlgButton(AfxMainHwnd,IDC_GpioLevel,(CH348SetDataOut & (1<<GpioIndex))?BST_CHECKED:BST_UNCHECKED);
return;
}
//GPIO功能和IO方向配置
BOOL CH910xGpioConfig()
{
int GpioIndex;
UCHAR RetVal = 0;
ULONG tempGpioEnable = 0, tempGpioDir = 0, tempFuncSet = 0;
if(INVALID_HANDLE_VALUE == hCom)
{
DbgPrint("配置前需打开串口");
return FALSE;
}
//从界面获取GPIO设置
GpioIndex = SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_GETCURSEL,0,0); //获取将设置的GPIO引脚
if(ChipPro.ChipType == USER_TYPE_CH9101U && GpioIndex == 5) //CH9101U没有GPIO5需过滤
GpioIndex += 1;
if(ChipPro.ChipType == USER_TYPE_CH9102X && GpioIndex >= 4) //CH9102X没有GPIO4需过滤
GpioIndex += 1;
tempGpioEnable = 1<<GpioIndex;
if(IsDlgButtonChecked(AfxMainHwnd,IDC_EnableGpio) == BST_CHECKED)
tempFuncSet = GpioEnable | (1<<GpioIndex);
else
tempFuncSet = GpioEnable & (~(1<<GpioIndex));
if(IsDlgButtonChecked(AfxMainHwnd,IDC_GpioDir) == BST_CHECKED)
tempGpioDir = GpioDir | (1<<GpioIndex);
else
tempGpioDir = GpioDir & (~(1<<GpioIndex));
//设置GPIO功能和方向
RetVal = CH910x_GpioConfig(hCom,&ChipPro,tempGpioEnable,tempFuncSet,tempGpioDir);
if(RetVal==CH910x_SUCCESS) //设置成功
{
GpioEnable = tempFuncSet; //保存状态
GpioDir = tempGpioDir;
DbgPrint("CH910x_GpioConfig功能和方向已设置成功");
}
else //设置失败
{
DbgPrint("CH910x_GpioConfig设置失败!");
return FALSE;
}
return TRUE;
}
VOID CH348GpioConfig()
{
ULONG GpioIndex;
ULONG RetVal;
ULONGLONG iFuncSet = 0; // 功能设置:某位值为0,表示对应引脚为芯片默认功能使用;为1,表示对应引脚作为GPIO功能使用;
ULONGLONG iSetDirOut = 0; // GPIO脚方向设置:某位为0表示对应引脚方向为输入;某位为1表示对应引脚方向为输出
ULONGLONG iSetDataOut = 0; // IO输出数据,如果GPIO方向为输出,那么某位清0时对应引脚输出低电平,某位置1时对应引脚输出高电平
ULONGLONG iEnable = 0; // 位使能:以位对应引脚号,位0对应GPIO0,位1对应GPIO1;某位为1,表示iGpioFunc,iSetDirOut对应位有效
GpioIndex = SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_GETCURSEL,0,0); //获取将设置的GPIO引脚
iEnable |= (__int64)1<<GpioIndex;
if(IsDlgButtonChecked(AfxMainHwnd,IDC_EnableGpio) == BST_CHECKED) //GPIO使能
iFuncSet = iEnable | (1<<GpioIndex);
else
iFuncSet = iEnable & (~(1<<GpioIndex));
if(IsDlgButtonChecked(AfxMainHwnd,IDC_GpioDir) == BST_CHECKED) //获取GPIO输入输出方向
iSetDirOut = iEnable | (1<<GpioIndex);
else
iSetDirOut = iEnable & (~(1<<GpioIndex));
if(IsDlgButtonChecked(AfxMainHwnd,IDC_GpioLevel) == BST_CHECKED) //获取GPIO输出电平
iSetDataOut = iEnable | (1<<GpioIndex);
else
iSetDataOut = iEnable & (~(1<<GpioIndex));
RetVal = CH348_GpioConfig(hCom,&ChipPro,iEnable,iFuncSet,iSetDirOut,iSetDataOut);
if(RetVal==CH910x_SUCCESS)//更新GPIO状态
{
DbgPrint("CH348_GpioConfig功能和方向已设置成功!");
//SendDlgItemMessage(AfxWndHwnd,IDC_348ReadGPIOCfg,BM_CLICK,0,0);
}
else
DbgPrint("CH348_GpioConfig功能和方向已设置失败!");
return;
}
//设置GPIO电平
BOOL CH910xSetGpioLevel()
{
int GpioIndex;
ULONG iEnable = 0,iSetDataOut = 0;
UCHAR RetVal;
//从界面获取GPIO设置
GpioIndex = SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_GETCURSEL,0,0); //获取将设置的GPIO引脚
if(ChipPro.ChipType == USER_TYPE_CH9101U && GpioIndex == 5) //CH9101U没有GPIO5需过滤
GpioIndex += 1;
if(ChipPro.ChipType == USER_TYPE_CH9102X && GpioIndex >= 4) //CH9102X没有GPIO4需过滤
GpioIndex += 1;
if(IsDlgButtonChecked(AfxMainHwnd,IDC_GpioDir) == BST_CHECKED)
{//设置GPIO为输出功能
iEnable = 1<<GpioIndex;
if(IsDlgButtonChecked(AfxMainHwnd,IDC_GpioLevel) == BST_CHECKED)
iSetDataOut = GpioSta | (1<<GpioIndex);
else
iSetDataOut = GpioSta & (~(1<<GpioIndex));
}
//设置GPIO为输出功能的GPIO状态,1位高电平,0位低电平
RetVal = CH910x_GpioSet(hCom,&ChipPro,iEnable,iSetDataOut);
if(RetVal == CH910x_SUCCESS)
{
DbgPrint("CH910x_GpioSet 设置成功!");
}
else
{
DbgPrint("CH910x_GpioSet设置失败!");
}
return RetVal;
}
VOID CH348SetGpioLevel()
{
UCHAR GpioIndex = 0; // GPIO序号掩码,位0-63
UCHAR GpioLevel = 0; // GPIO电平掩码,与上iGpioMIndex位置对应。1:高电平,0:低电平 ULONG i;
UCHAR RetVal;
GpioIndex = SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_GETCURSEL,0,0); //获取将设置的GPIO引脚
if(IsDlgButtonChecked(AfxMainHwnd,IDC_GpioDir) == BST_CHECKED) //GPIO为输出时候才能设置电平状态
{
if(IsDlgButtonChecked(AfxMainHwnd,IDC_GpioLevel) == BST_CHECKED)
GpioLevel = 0x01;
else
GpioLevel = 0x00;
}
else
{
MessageBox(AfxMainHwnd,"GPIO为输出时才能设置电平状态!","CH34xGpioCfg",MB_ICONERROR);
DbgPrint("ERROR: GPIO为输出时候才能设置电平状态");
return;
}
RetVal = CH348_GpioSet(hCom,&ChipPro,GpioIndex,GpioLevel); //设置某个GPIO的电平状态
if(RetVal==CH910x_SUCCESS)//更新GPIO状态
{
DbgPrint("CH348_GpioSet电平设置成功!");
SendDlgItemMessage(AfxMainHwnd,IDC_GetGpioLevel,BM_CLICK,0,0);
//SendDlgItemMessage(AfxMainHwnd,IDC_GetChipCfg,BM_CLICK,0,0);
}
return;
}
//获取GPIO电平状态
VOID CH348GetGPIO()
{
int GpioIndex;
UCHAR iGpioIndex; // GPIO引脚序号,0-63
UCHAR GpioLevel = 0x00; //对应引脚电平
UCHAR RetVal;
GpioIndex = SendDlgItemMessage(AfxMainHwnd,IDC_Gpio,CB_GETCURSEL,0,0); //获取将设置的GPIO引脚
iGpioIndex = GpioIndex; //获取GPIO引脚的序号0-63
RetVal = CH348_GpioGet(hCom,&ChipPro,iGpioIndex,&GpioLevel); //获取某个GPIO引脚的电平状态
if(RetVal==CH910x_SUCCESS)//更新GPIO状态
{
DbgPrint("CH348_GpioSet获取电平状态成功!");
if(GpioLevel)
CheckDlgButton(AfxMainHwnd,IDC_GpioLevel,BST_CHECKED);
else
CheckDlgButton(AfxMainHwnd,IDC_GpioLevel,BST_UNCHECKED);
}
else
{
DbgPrint("CH348_GpioSet获取电平状态失败!");
}
return;
}
//应用程序入口
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
return DialogBox(hInstance, (LPCTSTR)IDD_MainWnd, 0, (DLGPROC)WndProc);
}
//主窗体进程
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_INITDIALOG:
{
AfxMainHwnd = hWnd;
//串口初始化
GetComFriendlyName();
{//添加alt+tab切换时显示的图标
HICON hicon;
hicon = (HICON)LoadIcon(AfxMainIns,(LPCTSTR)IDI_Main);
PostMessage(AfxMainHwnd,WM_SETICON,ICON_BIG,(LPARAM)(HICON)hicon);
PostMessage(AfxMainHwnd,WM_SETICON,ICON_SMALL,(LPARAM)(HICON)hicon);
}
SendDlgItemMessage(hWnd,IDC_ShowMessage,EM_LIMITTEXT,0xFFFFFFFF,0);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case IDC_Refresh:
{
//刷新串口
SendDlgItemMessage(hWnd,IDC_AllCom,CB_RESETCONTENT,0,0); //清除组合框列表
GetComFriendlyName();
}
break;
case IDC_OpenCloseUART:
{
CHAR TempBuf[64] = "";
//打开串口
GetDlgItemText(hWnd,IDC_OpenCloseUART,TempBuf,sizeof(TempBuf));
if(!strcmp("打开串口",TempBuf))
{
if(!OpenCom())
{
EnableWindow(GetDlgItem(hWnd,IDC_Refresh),TRUE);
return TRUE;
}
SetDlgItemText(hWnd,IDC_OpenCloseUART,"关闭串口");
EnableWindow(GetDlgItem(hWnd,IDC_Refresh),FALSE);
GetChipInfo();
InsertGPIO();
if(ChipPro.ChipType == USER_TYPE_CH348L || ChipPro.ChipType == USER_TYPE_CH348Q)
CH348ReadGpioConfig();
else
CH910xReadGpioConfig();
}
else
{
CloseCom();
SetDlgItemText(hWnd,IDC_OpenCloseUART,"打开串口");
EnableWindow(GetDlgItem(hWnd,IDC_Refresh),TRUE);
SetDlgItemText(hWnd,IDC_DevInfo,"");
SetDlgItemText(AfxMainHwnd,1300,"GPIO设置");
SendDlgItemMessage(hWnd,IDC_Gpio,CB_RESETCONTENT,0,0);
}
}
break;
case IDC_GetChipCfg:
{//读取GPIO配置
if(ChipPro.ChipType == USER_TYPE_CH348L || ChipPro.ChipType == USER_TYPE_CH348Q)
CH348ReadGpioConfig();
else
CH910xReadGpioConfig();
}
break;
case IDC_SetChipGpio:
{//设置GPIO状态输入或输出
if(ChipPro.ChipType == USER_TYPE_CH348L || ChipPro.ChipType == USER_TYPE_CH348Q)
CH348GpioConfig();
else
CH910xGpioConfig();
}
break;
case IDC_SetGpioLevel:
{//设置GPIO电平
if(ChipPro.ChipType == USER_TYPE_CH348L || ChipPro.ChipType == USER_TYPE_CH348Q)
CH348SetGpioLevel();
else
CH910xSetGpioLevel();
}
break;
case IDC_GetGpioLevel:
{//获取GPIO电平
if(ChipPro.ChipType == USER_TYPE_CH348L || ChipPro.ChipType == USER_TYPE_CH348Q)
CH348GetGPIO();
else
SendDlgItemMessage(hWnd,IDC_GetChipCfg,BM_CLICK,0,0);
}
break;
case IDC_ClearInfo:
//清除输出信息
SetDlgItemText(hWnd,IDC_ShowMessage,"");
break;
case WM_DESTROY:
if(INVALID_HANDLE_VALUE != hCom)
{
CloseHandle(hCom);
hCom = INVALID_HANDLE_VALUE;
}
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return 0;
}
总结
本文主要介绍如何使用CH343PT库中的GPIO设置函数,去设置GPIO的IO方向:输入或输出,设置GPIO电平状态(IO方向为输出时候可以设置该状态),以及获取GPIO电平状态等GPIO操作。