Windows利用WinIO/WinRing0控制蜂鸣器发声(主板的Speaker发声)

本文介绍了在Windows系统下,由于现代操作系统安全考虑,beep函数无法通过主板Speaker发声。为了解决这个问题,文章详细展示了如何通过动态调用WinIO和WinRing0库来直接操作端口,实现主板Speaker的控制,从而在没有喇叭的嵌入式电脑上发出蜂鸣声。并提供了具体的代码示例,包括WinIO和WinRing0的初始化、读写端口以开启和关闭蜂鸣器的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

公司要做一个项目,需要用到蜂鸣器,然后我调用windows的API中的beep函数,发现竟然没有作用???之后查阅资料发现过去的beep是用主板的Speaker发声,直接操作硬件端口。现在的Windows可能出于安全考虑,beep已经不用主板的Speaker了,改用声卡输出。但是项目用的嵌入式电脑,根本没有喇叭,只能用主板的Speaker发声。

二、使用WinIO控制主板Speaker发声

WinIO动态调用

//初始化函数
typedef bool(__stdcall *InitializeWinIoType)();

//读取端口的数值  
typedef bool(__stdcall *GetPortValType)(unsigned short PortAddr, unsigned long* pPortVal, unsigned short Size);

//写入端口的数值 
typedef bool(__stdcall *SetPortValType)(unsigned short PortAddr, unsigned long PortVal, unsigned short Size);

bool Apq_LoadDll::LoadDll()
{
	if (!g_bIs_X64)
	{
		winio_lib.setFileName("WinIo32.dll");
	}
	else
	{
		winio_lib.setFileName("WinIo64.dll");
	}

	if (winio_lib.load())
		return true;
	else
		return false;
}

bool Apq_LoadDll::InitializeWinIoType()
{
	if (!winio_lib.isLoaded())
		return false;

	InitializeWinIoType pFunc = (InitializeWinIoType)winio_lib.resolve("InitializeWinIo");
	if (pFunc != NULL)
	{
		bool Result = pFunc();
		return Result;
	}

	return false;
}

//读取端口的数值
bool Apq_LoadDll::GetPortValType(unsigned short portAddr, unsigned long* portVal)
{
	if (!winio_lib.isLoaded())
		return false;

	GetPortValType GetPortVal = (GetPortValType)winio_lib.resolve("GetPortVal");

	if (GetPortVal != nullptr)
	{
		bool Result = GetPortVal(portAddr, portVal, 1);
		return Result;
	}

	return false;
}

//写入端口的数值
bool Apq_LoadDll::SetPortValType(unsigned short portAddr, unsigned long portVal)
{
	if (!winio_lib.isLoaded())
		return false;

	SetPortValType SetPortVal = (SetPortValType)winio_lib.resolve("SetPortVal");

	if (SetPortVal != nullptr)
	{
		bool Result = SetPortVal(portAddr, portVal, 1);
		return Result;
	}

	return false;
}

调用WinIO实现Speaker发声

void Widget::on_pushButton_clicked()
{
	Apq_LoadDll winio_lib;
	if (!winio_lib.LoadDll())
		return;

	if (!winio_lib.InitializeWinIoType())
		return;

	//开启蜂鸣器
	DWORD data = 0; 
	winio_lib.GetPortValType(0x61, &data);
	data |= 0x03;
	winio_lib.SetPortValType(0x61, data);
	Sleep(60);

	//关闭蜂鸣器
	winio_lib.GetPortValType(0x61, &data);
	data &= 0xFC;
	winio_lib.SetPortValType(0x61, data);
}

三、使用WinRing0控制主板Speaker发声

void Widget::on_pushButton_clicked()
{
	if (!InitializeOls())
		return;
			
	//开启蜂鸣器
	unsigned short data = 0;
	ReadIoPortWordEx(0x61, &data);
	data |= 0x03;
	WriteIoPortWordEx(0x61, data);
	Sleep(60);

	//关闭蜂鸣器
	ReadIoPortWordEx(0x61, &data);
	data &= 0xFC;
	WriteIoPortWordEx(0x61, data);
}

四、结语

亲测好用!!!WinIO和WinRing0是动态库,网上百度一下就出来了,这里因为我找的WinIO只有库没得头文件,所以用的动态调用。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值