Anemoia-ESP32 串口手柄代码

利用电脑串口进行控制

cpp 复制代码
// UartStickDlg.cpp: 实现文件
//

#include "stdafx.h"
#include "UartStick.h"
#include "UartStickDlg.h"
#include "afxdialogex.h"




// CUartStickDlg 对话框



CUartStickDlg::CUartStickDlg(CWnd* pParent /*=nullptr*/)
	: CDialog(IDD_UARTSTICK_DIALOG, pParent)
	, m_strComPort(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CUartStickDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, m_strComPort);
}

BEGIN_MESSAGE_MAP(CUartStickDlg, CDialog)

	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	ON_BN_CLICKED(IDC_B_UP, &CUartStickDlg::OnBnClickedBUp)
	ON_BN_CLICKED(IDC_B_DN, &CUartStickDlg::OnBnClickedBDn)
	ON_BN_CLICKED(IDC_B_LEFT, &CUartStickDlg::OnBnClickedBLeft)
	ON_BN_CLICKED(IDC_B_RIGHT, &CUartStickDlg::OnBnClickedBRight)
	ON_BN_CLICKED(IDC_B_B, &CUartStickDlg::OnBnClickedBB)
	ON_BN_CLICKED(IDC_B_A, &CUartStickDlg::OnBnClickedBA)
	ON_BN_CLICKED(IDC_B_OPEN, &CUartStickDlg::OnBnClickedBOpen)
	ON_BN_CLICKED(IDC_B_SELECT, &CUartStickDlg::OnBnClickedBSelect)
	ON_BN_CLICKED(IDC_B_START, &CUartStickDlg::OnBnClickedBStart)
END_MESSAGE_MAP()


// CUartStickDlg 消息处理程序

BOOL CUartStickDlg::OnInitDialog()
{

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}



void CUartStickDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	DoKeyDownOrUp(nChar, TRUE);
}


void CUartStickDlg::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	DoKeyDownOrUp(nChar, FALSE);
}

BOOL CUartStickDlg::PreTranslateMessage(MSG * pMsg)
{
	bool bFilter = false;
	if (pMsg->message == WM_KEYDOWN)
	{
		switch (pMsg->wParam)
		{
		case 'W':
		case 'A':
		case 'S':
		case 'D':
		case 'J':
		case 'K':
		case 'G':
		case 'H':
			bFilter = TRUE;
			DoKeyDownOrUp(pMsg->wParam, TRUE);
		}
		if (bFilter)
			return TRUE;
	}
	else if (pMsg->message == WM_KEYUP)// 处理WM_KEYUP消息
	{
		switch (pMsg->wParam)
		{
		case 'W':
		case 'A':
		case 'S':
		case 'D':
		case 'J':
		case 'K':
		case 'G':
		case 'H':
			bFilter = TRUE;
			DoKeyDownOrUp(pMsg->wParam, FALSE);
		}
		if (bFilter)
			return TRUE;
	}
	return FALSE;
}

void CUartStickDlg::OnBnClickedBUp()
{
	UINT n = 'W';
	DoKeyDownOrUp(n, TRUE);
	::Sleep(100);
	DoKeyDownOrUp(n, FALSE);
}


void CUartStickDlg::OnBnClickedBDn()
{
	UINT n = 'S';
	DoKeyDownOrUp(n, TRUE);
	::Sleep(100);
	DoKeyDownOrUp(n, FALSE);
}


void CUartStickDlg::OnBnClickedBLeft()
{
	UINT n = 'A';
	DoKeyDownOrUp(n, TRUE);
	::Sleep(100);
	DoKeyDownOrUp(n, FALSE);
}


void CUartStickDlg::OnBnClickedBRight()
{
	UINT n = 'D';
	DoKeyDownOrUp(n, TRUE);
	::Sleep(100);
	DoKeyDownOrUp(n, FALSE);
}


void CUartStickDlg::OnBnClickedBB()
{
	UINT n = 'J';
	DoKeyDownOrUp(n, TRUE);
	::Sleep(100);
	DoKeyDownOrUp(n, FALSE);
}


void CUartStickDlg::OnBnClickedBA()
{
	UINT n = 'K';
	DoKeyDownOrUp(n, TRUE);
	::Sleep(100);
	DoKeyDownOrUp(n, FALSE);
}



void CUartStickDlg::OnBnClickedBSelect()
{
	UINT n = 'G';
	DoKeyDownOrUp(n, TRUE);
	::Sleep(100);
	DoKeyDownOrUp(n, FALSE);
}


void CUartStickDlg::OnBnClickedBStart()
{
	UINT n = 'H';
	DoKeyDownOrUp(n, TRUE);
	::Sleep(100);
	DoKeyDownOrUp(n, FALSE);
}

DWORD __stdcall CUartStickDlg::__RecvThread(void * lpp)
{
	CUartStickDlg* pThis = (CUartStickDlg*)lpp;
	if (pThis)
	{
		pThis->RecvThread();
	}
	return 0;
}

void CUartStickDlg::RecvThread()
{

	char buffer[12560] = {};
	DWORD bytesRead;

	OVERLAPPED ovlp = {};
	ovlp.hEvent = CreateEvent(0, TRUE, FALSE, NULL);

	while (true) {
		if (m_hSerial != INVALID_HANDLE_VALUE /*&& WaitCommEvent(m_hSerial, NULL, NULL)*/) {
			//与发送之间进行锁定
			//CAutoLock lock(&m_lockRW);

			BOOL bRead = ReadFile(m_hSerial, buffer, sizeof(buffer) - 1, &bytesRead, &ovlp);
			if (!bRead && GetLastError() == ERROR_IO_PENDING) {
				// 等待读取完成
				WaitForSingleObject(ovlp.hEvent, INFINITE);
				GetOverlappedResult(m_hSerial, &ovlp, &bytesRead, FALSE);
				bRead = TRUE;
			}

			if (bRead && bytesRead > 0) {
				buffer[bytesRead] = '\0';
				// 打印ESP32发送的调试信息
				printf("\n[ESP32]%s", buffer);
			}
			ResetEvent(ovlp.hEvent);
		}
		Sleep(10);
	}
}


void CUartStickDlg::SendThread()
{
	OVERLAPPED ovlp = {};
	ovlp.hEvent = CreateEvent(0, TRUE, FALSE, NULL);

	while (true) {
		uint8_t currentState = (uint8_t)m_Kstate;

		// 只在状态变化时发送,如果方向键按下也需发送

		if (currentState/* || currentState != previousState || direct_key_down(currentState)*/) {
			previousState = currentState;

			// 构建数据包
			uint8_t packet[] = { START_BYTE, currentState, currentState };

			DWORD bytesWritten;
			if (m_hSerial != INVALID_HANDLE_VALUE)
			{
				//与发送之间进行锁定
				//CAutoLock lock(&m_lockRW);
				BOOL bWr=WriteFile(m_hSerial, packet, sizeof(packet), &bytesWritten, &ovlp);
				if (!bWr && GetLastError() == ERROR_IO_PENDING) {
					// 等待读取完成
					WaitForSingleObject(ovlp.hEvent, INFINITE);
					GetOverlappedResult(m_hSerial, &ovlp, &bytesWritten, FALSE);
					bWr = TRUE;
				}
				ResetEvent(ovlp.hEvent);
			}
		}
		Sleep(25); // 控制发送频率 40次/s
	}
}

DWORD __stdcall CUartStickDlg::__SendThread(void * lpp)
{
	CUartStickDlg* pThis = (CUartStickDlg*)lpp;
	if (pThis)
	{
		pThis->SendThread();
	}
	return 0;
}

bool direct_key_down(uint8_t st)
{
	if (st&(uint8_t)CONTROLLER::Up ||
		st & (uint8_t)CONTROLLER::Down ||
		st & (uint8_t)CONTROLLER::Left ||
		st & (uint8_t)CONTROLLER::Right
		)
	{
		return true;
	}
	return false;
}



// 打开串口
bool CUartStickDlg::OpenSerialPort(CString portName, int baudRate) {
	CString Full = L"\\\\.\\" + portName;
	m_hSerial = CreateFileW(Full,
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED,
		NULL);

	if (m_hSerial == INVALID_HANDLE_VALUE) {
		return false;
	}

	DCB dcbSerialParams = { 0 };
	dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

	if (!GetCommState(m_hSerial, &dcbSerialParams)) {
		CloseHandle(m_hSerial);
		m_hSerial = INVALID_HANDLE_VALUE;
		return false;
	}

	dcbSerialParams.BaudRate = baudRate;
	dcbSerialParams.ByteSize = 8;
	dcbSerialParams.StopBits = ONESTOPBIT;
	dcbSerialParams.Parity = NOPARITY;

	if (!SetCommState(m_hSerial, &dcbSerialParams)) {
		CloseHandle(m_hSerial);
		m_hSerial = INVALID_HANDLE_VALUE;
		return false;
	}

	COMMTIMEOUTS timeouts = { 0 };
	timeouts.ReadIntervalTimeout = 50;
	timeouts.ReadTotalTimeoutConstant = 50;
	timeouts.ReadTotalTimeoutMultiplier = 10;
	timeouts.WriteTotalTimeoutConstant = 50;
	timeouts.WriteTotalTimeoutMultiplier = 10;

	if (!SetCommTimeouts(m_hSerial, &timeouts)) {
		CloseHandle(m_hSerial);
		m_hSerial = INVALID_HANDLE_VALUE;
		return false;
	}

	return true;
}


void CUartStickDlg::OnBnClickedBOpen()
{
	if (m_hRecv)
		return;
	//打开串口
	UpdateData(TRUE);

	//打开串口
redo:
	DWORD dwTick = GetTickCount();
	if (!OpenSerialPort(m_strComPort, 115200))
	{
		if (GetTickCount() - dwTick < 10000)
		{
			Sleep(1);
			goto redo;
		}
		MessageBox(L"错误: 无法打开串口");
		return;
	}

	if (!AllocConsole()) {
		AfxMessageBox(L"控制台窗口创建失败!");
		return;
	}
	// 2. 重定向标准输入输出
	FILE* pFile = nullptr;
	freopen_s(&pFile, "CONOUT$", "w", stdout);
	freopen_s(&pFile, "CONOUT$", "w", stderr);
	freopen_s(&pFile, "CONIN$", "r", stdin);
	// 3. 设置控制台标题
	SetConsoleTitle(L"UartStick对话框控制台输出");
	printf("使用printf输出测试\n");


	//收发线程
	m_hRecv = CreateThread(0, 0, __RecvThread, this, 0, 0);
	m_hSend = CreateThread(0, 0, __SendThread, this, 0, 0);
}


__declspec(noinline) CONTROLLER _key_down_up(CONTROLLER kstate, CONTROLLER flagm, bool bDownOrUp)
{
	if (bDownOrUp)
		kstate = (CONTROLLER)((uint8_t)kstate | (uint8_t)flagm);
	else
		kstate = (CONTROLLER)((uint8_t)kstate &(~(uint8_t)flagm));
	return kstate;
}

void CUartStickDlg::DoKeyDownOrUp(UINT nChar, BOOL bDownOrUp)
{
	switch (nChar)
	{
	case 'W':
		m_Kstate = _key_down_up(m_Kstate, CONTROLLER::Up, bDownOrUp);
		break;
	case 'S':
		m_Kstate = _key_down_up(m_Kstate, CONTROLLER::Down, bDownOrUp);
		break;
	case 'A':
		m_Kstate = _key_down_up(m_Kstate, CONTROLLER::Left, bDownOrUp);
		break;
	case 'D':
		m_Kstate = _key_down_up(m_Kstate, CONTROLLER::Right, bDownOrUp);
		break;
	case 'J':
		m_Kstate = _key_down_up(m_Kstate, CONTROLLER::B, bDownOrUp);
		break;
	case 'K':
		m_Kstate = _key_down_up(m_Kstate, CONTROLLER::A, bDownOrUp);
		break;
	case 'G':
		m_Kstate = _key_down_up(m_Kstate, CONTROLLER::Select, bDownOrUp);
		break;
	case 'H':
		m_Kstate = _key_down_up(m_Kstate, CONTROLLER::Start, bDownOrUp);
		break;

	default:
		break;
	}

	//发送状态
	CString strKeyStl;
	strKeyStl.Format(L"[KeySt]=0x%02X\n", m_Kstate);
	OutputDebugStringW(strKeyStl);
}
相关推荐
乐鑫科技 Espressif3 天前
ESP-Claw 全面升级,打造可共享、可复用的设备端 AI Skills 生态
人工智能·esp32·乐鑫科技
Starry-sky(jing)15 天前
Win11 装 ESP32 Arduino 库卡 3 小时?我把官方 3.3.10 全平台 522MB 搬到了蓝奏云,解压即用
运维·windows·esp32·arduino·离线安装
π同学16 天前
ESP-IDF+vscode开发ESP32第十七讲——USB设备栈
vscode·esp32·usb
欢乐熊嵌入式编程1 个月前
选型避坑:ESP32 vs STM32+模组 vs NB-IoT,不同场景怎么选
stm32·单片机·嵌入式硬件·物联网·esp32·嵌入式iot
欢乐熊嵌入式编程1 个月前
WIFI通信协议全解析18: ESP32 作为 AP 热点:打造自己的“微型路由器”(附完整实战代码)
物联网·wifi·esp32·蓝牙·wifi协议·ap热点
sanzk1 个月前
修改blink让灯闪烁
esp32
乐鑫科技 Espressif1 个月前
ESP32-E22 获 Wi-Fi 6E 认证,开源 Linux 驱动同步发布
esp32·wi-fi·乐鑫科技·esp32-e22·wi-fi 6e
Mr_Tony1 个月前
ESP32开发板环境安装
esp32
星越华夏1 个月前
ESP32-CAM图像传输项目说明文档
java·后端·struts·esp32