Windows下QT使用WinRing0控制主板的蜂鸣器响 您所在的位置:网站首页 stm32f103c8蜂鸣器代码 Windows下QT使用WinRing0控制主板的蜂鸣器响

Windows下QT使用WinRing0控制主板的蜂鸣器响

2023-07-08 00:24| 来源: 网络整理| 查看: 265

Windows下QT使用WinRing0控制主板的蜂鸣器 一、前言二、使用WinRing0的几种方式1.静态编译方式2.动态编译方式3.使用QLibrary类动态调用方式 三、WinRing0驱动主板的蜂鸣器代码1.定义一个beep类:2.定义需要用到的函数指针:3.编写函数构造函数:4.编写析构函数5.编写beep函数(有一部分是ChatGPT写的,我具体也不是很清楚):6.主函数调用,会听见主板上的哔的一声: 四、常见问题1.使用过程中初始化失败 五、文件下载

一、前言

最近在windows10下用QT做项目,需要在用户进行某项操作时进行声音提示,扬声器的话一来增加成本,二来也受系统提示音困扰。搜索网上有两种解决办法,一个是WinIO的方式,这种处理起来比较麻烦,量产时费人费力还容易造成系统不稳定。另外一种就是WinRing0了,也就是这篇博客讲的。

二、使用WinRing0的几种方式 1.静态编译方式

使用这种方式对使用者的素养要求比较高,由于本人属于嵌入式开发范畴,不会将源代码编译成lib文件。这种方式需要使用者用与QT版本相同的编译器去编译,否则QT项目会在编译阶段报错。

2.动态编译方式

使用动态编译也需要自己编译WinRing0的源码,生成DLL文件及相关库文件。

3.使用QLibrary类动态调用方式

我目前使用的就是这种方法,手头上有个DLL文件以及sys驱动,因为水平有限,不会自己编译库。使用此种方式的原理就是QLibrary类的resolve方法会根据你传的函数名返回DLL中对应的函数指针。你再去执行此函数即可。

三、WinRing0驱动主板的蜂鸣器代码 1.定义一个beep类: #include #include class WioBeep : public QObject{ Q_OBJECT; public: WioBeep(); ~WioBeep(); void beep(uint16_t ms); private: QLibrary mylib; //声明所用到的dll文件 }; 2.定义需要用到的函数指针: #include //初始化函数 typedef bool(__stdcall *InitializeWinIoType)(); typedef void(__stdcall *DeinitializeWinIoType)(); typedef DWORD(__stdcall *GetDllStatusType)(); //读取端口的数值 typedef BYTE(__stdcall *GetPortValType)(unsigned short PortAddr); //写入端口的数值 typedef void(__stdcall *SetPortValType)(unsigned short PortAddr, unsigned long PortVal); 3.编写函数构造函数: WioBeep::WioBeep(){ mylib.setFileName("WinRing0x64.dll"); if (mylib.load()) qDebug( "WinRing0x64.dll load succuse!\n"); else qDebug( "WinRing0x64.dll load failed!\n"); InitializeWinIoType pFunc = (InitializeWinIoType)mylib.resolve("InitializeOls"); GetDllStatusType GetDllStatus = (GetDllStatusType)mylib.resolve("GetDllStatus"); if (pFunc != NULL) { bool Result = pFunc(); if (!Result) { DWORD str = GetDllStatus();//获取失败原因代码 qDebug( "Error In InitializeWinIo %d!\n",str); } } } 4.编写析构函数 WioBeep::~WioBeep(){ DeinitializeWinIoType pFunc = (DeinitializeWinIoType)mylib.resolve("DeinitializeOls"); if (pFunc != NULL) { pFunc(); } } 5.编写beep函数(有一部分是ChatGPT写的,我具体也不是很清楚): void WioBeep::beep(uint16_t ms){ if (!mylib.isLoaded()){ qDebug( "WinRing0x64.dll not load!\n"); return; } GetPortValType ReadIoPortByte = (GetPortValType)mylib.resolve("ReadIoPortByte"); SetPortValType WriteIoPortByte = (SetPortValType)mylib.resolve("WriteIoPortByte"); if (ReadIoPortByte == NULL || WriteIoPortByte == NULL) { qDebug( "WinRing0x64.dll function load faild!\n"); return; } // 设置蜂鸣器频率 unsigned int frequency = 2000; // 设置频率为400Hz unsigned short count = static_cast(1193180 / frequency); // 计算计数器的值 unsigned char lowByte = static_cast(count & 0xFF); // 取计数器的低字节 unsigned char highByte = static_cast((count >> 8) & 0xFF); // 取计数器的高字节 // 控制蜂鸣器 WriteIoPortByte(0x43, 0xB6); // 向IO端口写入字节,设置蜂鸣器工作方式 WriteIoPortByte(0x42, lowByte); // 向IO端口写入字节,设置蜂鸣器计数器的低字节 WriteIoPortByte(0x42, highByte); // 向IO端口写入字节,设置蜂鸣器计数器的高字节 //开启蜂鸣器 DWORD data = ReadIoPortByte(0x61); data |= 0x03; WriteIoPortByte(0x61, data); Sleep(ms); //关闭蜂鸣器 data = ReadIoPortByte(0x61); data &= 0xFC; WriteIoPortByte(0x61, data); } 6.主函数调用,会听见主板上的哔的一声: WioBeep *beep = new WioBeep(); beep->beep(200); 四、常见问题 1.使用过程中初始化失败

确保WinRing0x64.dll和WinRing0x64.sys和你的.exe文件在同一目录下。

程序需要以管理员权限运行,QT的pro文件需要添加如下内容:

RC_FILE=main.rc

main.rc文件放在与.pro文件同目录下,文件内容如下:

// 图标 IDI_ICON1 ICON "/icon/main.ico" 1 24 uac.manifest

uac.manifest文件放在与main.rc文件同目录下,文件内容如下:

如果你使用的是32位的编译器,请将相关代码及文件替换成WinRing0.dll和WinRing0.sys。

五、文件下载

工程源代码因为是公司项目,无法发出来,之后会发相关的DLL及sys文件。 百度云网盘链接 提取码:euf3



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有