23.#pragma使用分析

#pragma简介

#pragma用于指示编译器完成一些特定的动作

#pragma所定义的很多指示字是编译器特有的

#pragma在不同的编译器间是不可移植的

预处理器将忽略它不认识的#pragma指令

不同的编译器可能以不同的方式解释同一条#pragma指令

一般用法:

#pragma parameter

注:不同的parameter参数语法和意义各不相同

message用于条件编译中可提示代码的版本信息

#if defined(ANDROID40)

#pragma message("Compile Android SDK 4.0...")

#define VERSION "Android 4.0"

#endif

#pragma once

#pragma once 用于保证头文件只被编译一次

#pragma once 是编译器相关的,不一定被支持

 

#pragma once 与 #ifndef 的区别

#pragma once 效率更高, 单不一定被支持

如何保持编译效率高,又都被支持了

可以使用如下方法实现

#ifndef G_LOBLE_

#def G_LOBLE_

#pragma once

// 代码片段

#endif

 

#pragma once #include <windows.h> #include <iostream> #define COMNAME "\\\\.\\COM5" //或许需要更改 #define MOUSE_LEFT 0 #define MOUSE_RIGHT 1 #define MOUSE_MID 2 #define CHKEY_A 0x04 #define CHKEY_B 0x05 #define CHKEY_C 0x06 #define CHKEY_D 0x07 #define CHKEY_E 0x08 #define CHKEY_F 0x09 #define CHKEY_G 0x0a #define CHKEY_H 0x0b #define CHKEY_I 0x0c #define CHKEY_J 0x0d #define CHKEY_K 0x0e #define CHKEY_L 0x0f #define CHKEY_M 0x10 #define CHKEY_N 0x11 #define CHKEY_O 0x12 #define CHKEY_P 0x13 #define CHKEY_Q 0x14 #define CHKEY_R 0x15 #define CHKEY_S 0x16 #define CHKEY_T 0x17 #define CHKEY_U 0x18 #define CHKEY_V 0x19 #define CHKEY_W 0x1a #define CHKEY_X 0x1b #define CHKEY_Y 0x1c #define CHKEY_Z 0x1d #define CHKEY_0 0x27 #define CHKEY_1 0x1e #define CHKEY_2 0x1f #define CHKEY_3 0x20 #define CHKEY_4 0x21 #define CHKEY_5 0x22 #define CHKEY_6 0x23 #define CHKEY_7 0x24 #define CHKEY_8 0x25 #define CHKEY_9 0x26 //大写需要|0x80 这些按键基本够用了不够自己封装 typedef struct buffer{ int len; char data[70]; }BUFFER; typedef struct keyevent{ uint8_t press; uint8_t code; }KEYEVENT; typedef struct uart_fmt{ uint8_t HEAD[2]; // 帧头:占 2 个字节,固定为 0x57、0xAB uint8_t ADDR; // 地址码:占 1 个字节,默认为 0x00,可接收任意地址码的命令包,如果芯片地址设置成 0x01---0xFE,则只能接收对应地址码或地址码为 0xFF 的命令包。0xFF 为广播包,芯片不需 要进行应答; uint8_t CMD; // 命令码:占 1 个字节,外围串口设备发起的帧的命令码有效范围为:0x01---0x3F,CH9329 芯片发送正常应答包时的命令码为:原命令码 | 0x80;CH9329 芯片发送异常应答包时的命 令码为:原命令码 | 0xC0; uint8_t LEN; // 后续数据长度:占 1 个字节,主要用于记录该包实际后续数据的长度,仅包含后续数据部分,不包括帧头字节、地址码、命令码和累加和字节; uint8_t DATA[64]; // 后续数据:占 N 个字节,N 有效范围为 0---64。typedef uint8_t SUM; // 累加和:占 1 个字节,计算方式为: SUM = HEAD+ADDR+CMD+LEN+DATA }UART_FMT; typedef struct ch9329cmd{ uint8_t GET_INFO; //获取芯片版本等信息 通过该命令向芯片获取版本号、 USB 枚举状态、键盘大小写指示灯 状态等信息 uint8_t SEND_KB_GENERAL_DATA; //发送 USB 键盘普通数据 通过该命令向芯片发送普通键盘 数据包,模拟普通按键按下或释放 动作 uint8_t SEND_KB_MEDIA_DATA; //发送 USB 键盘多媒体数据 通过该命令向芯片发送多媒体键 盘数据包,模拟多媒体按键按下或 释放动作 uint8_t SEND_MS_ABS_DATA; //发送 USB 绝对鼠标数据 通过该命令向芯片发送绝对鼠标 数据包,模拟绝对鼠标相关动作 uint8_t SEND_MS_REL_DATA; //发送
最新发布
03-24
<think>好的,我现在需要帮助用户了解如何实现基于CH9329芯片的USB键盘和鼠标的UART通信协议,特别是在Windows环境下使用C++。首先,我得回忆一下CH9329芯片的基本信息。CH9329是沁恒微电子的一款USB转串口芯片,支持模拟键盘和鼠标的HID设备,用户可以通过串口发送特定指令来控制键盘和鼠标的输入。 接下来,我需要查阅相关资料,确保信息的准确性。根据用户提供的引用内容,特别是引用[3]提到串口通信通常使用8位数据位加起始位和停止位,数据范围是0-255,所以传输更大的数据需要拆分处理。而引用[5]提到UART的全双工通信和FIFO缓冲,这可能对数据发送的稳定性有帮助。 首先,CH9329的通信协议结构可能包括数据头、命令字、数据长度、实际数据、校验和等部分。比如,数据头可能是固定的0x57和0xAB,命令字区分键盘或鼠标操作,数据长度指明后续数据的字节数,接着是具体的数据内容,最后是校验和,如累加和或者CRC。需要确认具体的协议格式,可能需要查阅CH9329的官方文档或用户手册,但用户没有提供,所以需要基于常见实现进行推断。 然后是C++在Windows下的串口通信实现。通常可以使用Windows API中的CreateFile打开串口,SetCommState配置波特率、数据位、停止位等参数,ReadFile和WriteFile进行读写操作。引用[2]提到正点原子的UART实验,可能涉及类似的操作流程。需要确保配置参数与CH9329的要求一致,比如波特率可能为9600或115200,数据位8位,无奇偶校验,停止位1位。 接着,数据包的封装示例。例如,发送键盘数据可能需要构造包含按键码和状态的数据包。假设命令字0x02代表键盘输入,数据部分包括按键的按下和释放状态,校验和为前面所有字节的和取低8位。类似地,鼠标数据可能包括移动坐标和按键状态。需要注意数据的大小端和排列顺序。 在代码实现部分,需要先初始化串口,然后构建数据包,计算校验和,最后发送。例如,使用CreateFile打开COM3,设置DCB结构体,配置波特率,然后构建数据包,计算校验和,通过WriteFile发送。同时,要注意串口的错误处理和超时设置,确保通信的可靠性。 此外,引用[3]提到传输超过255的数据需要拆分,因此如果需要发送更大的数据,可能需要设计通信协议来分片,并在接收端重组。但根据CH9329的功能,可能只需要发送单个字节的控制指令,所以需要确认具体协议是否支持多字节传输。 最后,测试和调试是关键。建议用户使用串口调试工具先验证数据包的正确性,再逐步集成到C++代码中。同时,参考引用[4]中提到的实时数据显示功能,可以添加日志记录或显示发送和接收的数据,方便调试。 总结步骤:了解协议结构、配置串口、构造数据包、实现通信、测试验证。需要确保每一步都符合CH9329的具体要求,可能需要查阅其数据手册获取精确的协议格式和命令字定义。</think>### CH9329 UART通信协议实现方法 CH9329芯片通过UART协议接收特定格式的指令数据,模拟USB键盘/鼠标行为。其核心实现分为协议解析、数据封装、串口通信三部分[^3]。 --- #### 一、协议结构分析 1. **数据包格式** 典型数据包结构: ``` | 数据头(2字节) | 命令字(1字节) | 数据长度(1字节) | 数据(N字节) | 校验和(1字节) | ``` - 数据头:固定为`0x57 0xAB` - 命令字:区分功能(如`0x02`为键盘输入,`0x03`为鼠标输入) - 数据长度:后续数据字段的字节数 - 校验和:累加和取低8位[^5] 2. **键盘数据示例** ```plaintext 0x57 0xAB 0x02 0x06 0x00 0x04 0x00 0x00 0x00 0x00 0x0D ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ 头 头 命令 长度 按键1 按键2 修饰符 X/Y保留 校验和 ``` 对应按键`0x04`为字符`a`(需参考HID键码表)。 --- #### 二、C++实现步骤 1. **串口初始化(Windows API)** ```cpp HANDLE hCom = CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); DCB dcb = {0}; dcb.DCBlength = sizeof(DCB); GetCommState(hCom, &dcb); dcb.BaudRate = CBR_9600; // 波特率需与CH9329配置一致 dcb.ByteSize = 8; // 数据位 dcb.Parity = NOPARITY; // 无校验 dcb.StopBits = ONESTOPBIT; // 停止位 SetCommState(hCom, &dcb); ``` 2. **数据包封装** ```cpp // 构造键盘按下'a'的数据包 BYTE data[] = {0x57, 0xAB, 0x02, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}; BYTE checksum = 0; for (int i = 0; i < 10; i++) checksum += data[i]; data[10] = checksum; // 校验和 ``` 3. **发送数据** ```cpp DWORD bytesWritten; WriteFile(hCom, data, sizeof(data), &bytesWritten, NULL); ``` --- #### 三、关键注意事项 1. **校验和计算** 必须严格按协议计算,否则CH9329会丢弃数据包。 2. **释放按键** 发送按键释放指令(数据字段全零)以避免长按状态。 3. **波特率匹配** 需与CH9329初始化时的波特率一致(默认通常为9600)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值