IoPortDirect示例讲解
文章目录
- IoPortDirect示例讲解
- 结构说明
- 代码说明
项目打开请查看【BaseFunction精讲】。
结构说明
IoPortDirect.cpp :源码
- 其余文件说明请查看【BaseFunction精讲】中的结构说明。
ps : 内核层中的数据、结构体需要一字节对齐,需要以MT方式构建
代码说明
IoPortDirect.h
:主要的功能代码
/* Copyright (c) 1996-2025 by Kithara Software GmbH. All rights reserved. */
//##############################################################################################################
//
// 文件: IoPortDirect.cpp
//
// 模块: IoPort Module
//
// 描述: 示例应用程序,用于将输出输出到IO端口
//
// 创建者: u.jes 1996-07-01
//
//##############################################################################################################
/*=====================================================================*\
| *** 免责声明 *** |
| |
| 本代码仅是示例程序,您可以随意使用,我们不承担任何法律责任! |
| |
\*=====================================================================*/
//##############################################################################################################
//
// 目的:
//
// 这个示例代码演示了如何使用应用程序空间中的函数KS_enableIoRange()、KS_inpb()和KS_outpb(),
// 通过使用可编程间隔定时器(PIT)的通道2在PC扬声器上生成用户选择的频率的声音,参见
// https://wiki.osdev.org/Programmable_Interval_Timer
// KS_enableIoRange()用于消除KS_inpb()/KS_outpb()从用户空间访问所需端口时对上下文切换的需要。
// 但是这在任何操作系统(例如x64位Windows操作系统)上都不起作用,导致KS_inpb()/KS_outpb()在后台透明地执行所需的上下文切换。
// 因此,KS_inpb()/KS_outpb()在KS_enableIoRange()失败的情况下仍然可以工作,
// 但是对于可预测的低执行时间,您应该更喜欢从内核空间使用KS_inpb()/KS_outpb()
//(通过将它们移动到位于DLL中的代码,将此DLL加载到内核空间并在那里执行代码)。
// 这将使KS_inpb()/KS_outpb()避免在应用程序空间和内核空间之间进行上下文切换!
//你会被要求设置一个频率在20到18000赫兹之间,你的电脑扬声器会播放2秒的声音。
//
//##############################################################################################################
#include "../_KitharaSmp/_KitharaSmp.h"
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// 别忘了输入你的序列号(6位客户编号),这是打开驱动程序所必需的。
//
// 如果你使用Demo版本,也可以使用“DEMO”代替。
// 如果你使用Beta版本,也可以使用“BETA”代替。
//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 如上说所,定义的客户号
const char _pCustomerNumber[] = "DEMO";
// 主程序入口
void runSample() {
outputTxt("***** Kithara example program 'IoPortDirect' *****");
KSError error;
// 错误码定义,KSError 是 Kithara API 所有函数的返回类型,通过 【KSError】 可以查询接口的返回错误信息。
KSError error;
//------------------------------------------------------------------------------------------------------------
// 打开驱动程序的第一步,所有KRTS程序必须进行的操作。
// 只要该函数调用成功后,我们可以使用其他函数。如果打开失败,则无法调用其他函数。
// 此函数接受您的客户编号作为参数,其中包含 Kithara(如果适用可以为“DEMO”或“BETA”)。
//------------------------------------------------------------------------------------------------------------
error= KS_openDriver(
_pCustomerNumber); // 客户序列号
if (error!= KS_OK) {
outputErr(error, "KS_openDriver", "Unable to open the driver!");
return;
}
//------------------------------------------------------------------------------------------------------------
// 请输入所需的噪声频率。
//------------------------------------------------------------------------------------------------------------
int freq = inputDec("Insert the frequency (20 Hz ... 18000 Hz): ", 1000);
if (freq < 20 || freq > 18000) {
outputTxt("Sorry, this frequency is not supported!");
KS_closeDriver();
return;
}
//------------------------------------------------------------------------------------------------------------
// 首先,我们尝试启用用户空间访问所需的端口。
// 这在任何系统上都是不可能的,参见https://kithara.com/en/docs/krts:api:ks_enableiorange
// 当调用KS_outp*()和KS_inp*()函数时,KS_enableIoRange()的失败不被认为是错误
// 仍然会成功,但由于需要上下文切换,速度会变慢。
// 为了避免这个问题,建议在内核级别使用KS_outp*()和KS_inp*()函数来消除
// 需要这些上下文切换。
//
// 我们需要访问以下端口:
// 0x42 (PIT Channel 2数据端口)
// 0x43 (PIT模式/命令寄存器)
// 0x61(系统控制端口)
//------------------------------------------------------------------------------------------------------------
error = KS_enableIoRange(
0x42, // I/O端口的基址范围
2, // 启用范围内的端口数
KSF_SIZE_8_BIT); // 标志,这里是访问字节
if (error != KS_OK)
outputErr(error, "KS_enableIoRange", "Error during enabling port 0x42 and 0x43.");
error = KS_enableIoRange(
0x61, // I/O端口的基址范围
1, // 启用范围内的端口数
KSF_SIZE_8_BIT); // 标志,这里是访问字节
if (error != KS_OK)
outputErr(error, "KS_enableIoRange", "Error during enabling port 0x61.");
//------------------------------------------------------------------------------------------------------------
// 启用并配置扬声器的PIT控制。
//------------------------------------------------------------------------------------------------------------
const uint speakerBits = 0x03; // 位1: 扬声器位置,位0: 连接到定时器
uint systemControlPortValue = KS_inpb(
0x61); // 系统控制端口地址
if ((systemControlPortValue & speakerBits) != speakerBits) // 检查,如果两个位已经设置,否? -> 然后打开
KS_outpb(
0x61, // 系统控制端口地址
systemControlPortValue | speakerBits); // 接通扬声器与PIT的连接
KS_outpb(
0x43, // PIT的模式控制寄存器端口地址
0xb6); // 0xb6 = 扬声器模式、定时器等设置位。
//------------------------------------------------------------------------------------------------------------
// 为扬声器设置所选频率。
//------------------------------------------------------------------------------------------------------------
uint speakerFrequency = 0x001234DD / freq; // 0x001234dd = 1,193,182 Hz (PIT频率)
KS_outpb( // 频率字节必须分两步写入
0x42, // PIT的通道2数据端口地址
speakerFrequency); // 要设置的扬声器频率的低字节
KS_outpb(
0x42, // PIT的通道2数据端口地址
speakerFrequency >> 8); // 高字节的扬声器频率设置
//------------------------------------------------------------------------------------------------------------
// 扬声器发出哔哔声 - 现在我们等待2秒。
//------------------------------------------------------------------------------------------------------------
outputDec(freq, "Beeping with ", " Hz...");
waitTime(2 * s);
//------------------------------------------------------------------------------------------------------------
// 关掉扬声器。
//------------------------------------------------------------------------------------------------------------
systemControlPortValue = KS_inpb(
0x61); // 系统控制端口地址
KS_outpb(
0x61, // 系统控制端口地址
systemControlPortValue & ~speakerBits); // 断开PIT和扬声器之间的连接
//------------------------------------------------------------------------------------------------------------
// 关闭驱动程序以释放任何分配的资源。
//------------------------------------------------------------------------------------------------------------
error = KS_closeDriver();
if (error != KS_OK)
outputErr(error, "KS_closeDriver", "Unable to close the driver!");
waitTime(500 * ms);
outputTxt(" ");
outputTxt("End of program 'IoPortDirect'.");
}