IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> CH343PT库使用<三> GPIO设置 -> 正文阅读

[嵌入式]CH343PT库使用<三> GPIO设置


前言

我们在使用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

代码如下(示例):

data = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())

配置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,固件版本1.4,共有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, 固件版本: %s, 共有%d个GPIO可配置", ChipPro.ChipTypeStr, ChipPro.FwVerStr, 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操作。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:14:20  更:2022-10-31 12:18:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 16:19:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码