CH343PT library uses <3> GPIO settings


foreword

When we use the USB-to-serial device, we will not only use the serial communication function, but sometimes also use the GPIO function of the chip, such as setting the GPIO input and output functions. The chip models that support GPIO setting include CH9101, CH9102, CH9103, CH9104, CH347, CH344, CH348 and other models. The following will introduce how to use the functions in the CH343PT library to configure the GPIO input and output functions of the above chips.


1. Introduction to configure GPIO functions

There are two sets of GPIO setting functions, CH910x_XX function is used to set CH9101, CH9102, CH9103, CH344 and CH347, and CH348_XX function is used to set CH348.

1.1 Configure GPIO function (for CH910X, CH344, CH347)

① Configure GPIO function and I/O direction

UCHAR	WINAPI	CH910x_GpioConfig(
			HANDLE			iPortH,    
			ChipPropertyS*  iChipProperty,
			ULONG			iEnable,        
			ULONG			iFuncSet,       
			ULONG			iSetDirOut);    

The parameter IPortH is the serial port handle value;
the parameter iChipProperty chip attribute information, for specific introduction, please refer to my article; the parameter
iEnable is the bit enable: the bit corresponds to the pin number, bit 0 corresponds to GPIO0, bit 1 corresponds to GPIO1; a certain bit is 1, Indicates that the corresponding bit of iGpioFunc and iSetDirOut is valid.
The parameter iFuncSet is the function setting: a certain bit value is 0, indicating that the corresponding pin is used by the default function of the chip; it is 1, indicating that the corresponding pin is used as a GPIO function; the parameter
iSetDirOut is the GPIO pin direction setting: a certain A bit of 0 means that the direction of the corresponding pin is input; a bit of 1 means that the direction of the corresponding pin is output.

②Get GPIO pin configuration: pin function, direction, level

UCHAR	WINAPI	CH910x_GetGpioConfig(
			HANDLE			iPortH, 
			ChipPropertyS   *iChipProperty, 
			PULONG			FuncSet,        
			PULONG			SetDirOut,      
			PULONG       SetDataOut);  

The parameter IPortH is the serial port handle value;
the parameter iChipProperty chip attribute information, which can be NULL, and the specific introduction can refer to my article; the
parameter FuncSet is the function setting: a certain bit value is 0, indicating that the corresponding pin is used by the default function of the chip; if it is 1, Indicates that the corresponding pin is used as a GPIO function;
the parameter SetDirOut is the direction setting of the GPIO pin: a certain bit is 0, indicating that the corresponding pin direction is input; a certain bit is 1, indicating that the corresponding pin direction is output; the
parameter SetDataOut is the GPIO pin level value: 1 means high level; 0 means low level.

③Set the GPIO pin level status
Use this function to set the GPIO pin to output high level or output low level.

UCHAR	WINAPI	CH910x_GpioSet(  
			HANDLE			iPortH,       
			ChipPropertyS*  iChipProperty,
			ULONG			iEnable,        
			ULONG			iSetDataOut );

The parameter IPortH is the serial port handle value;
the parameter iChipProperty chip attribute information;
the parameter iEnable is the data valid flag, the bit number corresponds to the GPIOx number, the bit value is 1 means that the corresponding bit data of iSetDataOut is valid, and 0 means the data is invalid; the parameter iSetDataOut IO
output Data, if the GPIO direction is output, then when a certain bit is cleared to 0, the corresponding pin outputs a low level, and when a certain bit is set to 1, the corresponding pin outputs a high level

④ Read the GPIO pin level status

UCHAR	WINAPI	CH910x_GpioGet(   
			HANDLE			iPortH,    
			ChipPropertyS*   iChipProperty,
			PULONG			iStatus );   

The parameter iPortH is the serial port handle value;
the parameter iChipProperty chip attribute information;
the parameter iStatus is the pin status, and its GPIOx serial number corresponds to the data bit number. For example, GPIO1 corresponds to bit1 in the iStatus value, and the value can be obtained by using the CH910x_GPIO_xx bit mask.

1.2 Configure GPIO function (adapt to CH348)

① Get GPIO configuration: function and I/O direction, output pin default value

UCHAR	WINAPI	CH348_GetGpioConfig(
			HANDLE		    	iPortH,         // 串口句柄值
			ChipPropertyS       *ChipProperty,  // 芯片属性值
			ULONGLONG			*FuncSet,       // 功能设置:某位值为0,表示对应引脚为芯片默认功能使用;为1,表示对应引脚作为GPIO功能使用;
			ULONGLONG			*SetDirOut,     // GPIO脚方向设置:某位为0表示对应引脚方向为输入;某位为1表示对应引脚方向为输出	
			ULONGLONG           *SetDataOut);   // IO输出数据,如果GPIO方向为输出,那么某位清0时对应引脚输出低电平,某位置1时对应引脚输出高电平

② Configure GPIO function and I/O direction

//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时对应引脚输出高电平

③Set the level status of a certain GPIO pin, and the corresponding pin needs to enable the GPIO function

UCHAR	WINAPI	CH348_GpioSet(  
			HANDLE			iPortH,         // 串口句柄值
			ChipPropertyS*   iChipProperty,  // 芯片属性值
			UCHAR	        iGpioIndex,     // GPIO脚序号,0-63
			UCHAR		    iGpioLevel );   // GPIO电平,1为高电平;1:低电平

④Set the level status of multiple GPIO pins, and the corresponding pins need to enable the GPIO function

UCHAR	WINAPI	CH348_GpioMSet(  
			HANDLE			iPortH,          // 串口句柄值
			ChipPropertyS*   iChipProperty,   // 芯片属性值
			ULONGLONG        iGpioMIndex,     // GPIO序号掩码,位0-63
			ULONGLONG		iGpioMLevel);     // GPIO电平掩码,与上iGpioMIndex位置对应。1:高电平,0:低电平

⑤ To get the level status of a certain GPIO pin, the corresponding pin needs to enable the GPIO function

UCHAR	WINAPI	CH348_GpioGet(  
			HANDLE			iPortH,         // 串口句柄值
			ChipPropertyS*   iChipProperty,  // 芯片属性值
			UCHAR	        iGpioIndex,     // GPIO脚序号 0-63
			PUCHAR		    GpioLevel );     // GPIO电平,1为高电平;1:低电平

2. GPIO Configuration Demo

2.1 Use CH910x_XX function to configure GPIO

The steps to configure the GPIO of the USB-to-serial device are as follows:
①Open the serial port;
②Call the CH343PT_GetChipProperty function to obtain the chip function information, such as the chip model, the chip model string, and the number of GPIOs that the chip can configure (for details, please refer to this article);
③ To read GPIO default configuration, use function CH910x_GetGpioConfig;
④Configure GPIO function and IO direction (IO direction is divided into input and output), use function CH910x_GpioConfig;
⑤Set level state (high level and low level), use function CH910x_GpioSet, IO direction is Use this function for output;
⑥Get the GPIO pin level status, use the function CH910x_GpioGet;
⑦Close the serial port.

2.2 Use CH348_XX function to configure GPIO

The steps to configure the GPIO of the USB-to-serial device are as follows:
①Open the serial port;
②Call the CH343PT_GetChipProperty function to obtain chip function information, such as chip model, chip model string, chip configurable GPIO quantity and other information; ③Read the
GPIO default configuration, use the function CH348_GetGpioConfig ;
④ GPIO function and IO direction configuration (IO direction is divided into input and output), use the function CH348_GpioConfig
; Set the GPIO status of multiple pins), use this function when the IO direction is output;
⑥Get the GPIO pin level status, use the function CH348_GpioGet or CH348_GpioMGet;
⑦Close the serial port.


3. Software implementation

Use VC6++ to create a new dialog box, the interface is as follows.
insert image description here

⑴Insert CH9102F, open the serial port, the interface is as follows:
insert image description here
As can be seen from the figure, the chip model is CH9102F, and there are 5 GPIOs in total.

⑵Choose to configure the GPIO3 pin as an output function, set the pin to low level (interface settings: need to check the pin function, IO direction, and IO status to uncheck), then click the configure chip GPIO button, and then click after the setting is successful. Set the GPIO level button. After the setting is successful, you can use a multimeter to measure whether GPIO3 is ground level (TTL level). If it is low level, the setting is successful, otherwise the setting fails.
insert image description here
If the GPIO level is set to be high, check the IO status check box and repeat the above steps.

(3) Set GPIO3 as the input function, check the default function and IO status check boxes, and uncheck the IO direction check box. Next, click the Configure chip GPIO button. After the setting is successful, click the Get GPIO Level button to get the level status of the GPIO3 pin. If the GPIO pin is grounded, click the Get GPIO Level button, and the IO Status check box is unchecked. Similarly, the GPIO level is high level, click the Get GPIO level button, and the IO status check box will be checked.
insert image description here

(4) Pay attention to the GPIO settings of CH9102X and CH9101U models. CH9101U does not have GPIO5 and needs to be filtered, while CH9102X does not have GPIO4 and needs to be filtered. The interface of inserting CH9102X is as follows:
insert image description here
From the figure, we can see that CH9102X does not have GPIO4, a total of 6 GPIOs. You need to use the structure ChipPropertyS to judge whether the opened device is CH9102X or CH910U, and then filter the corresponding GPIO to avoid setting errors.

(5) To set the GPIO output and input functions of CH348, use the same method as above to set.
insert image description here

4. Code implementation

//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;
}

Summarize

This article mainly introduces how to use the GPIO setting function in the CH343PT library to set the IO direction of GPIO: input or output, set the GPIO level status (this status can be set when the IO direction is output), and obtain GPIO level status and other GPIO operations .

Guess you like

Origin blog.csdn.net/WCH_TechGroup/article/details/127519948