若要提供脈衝寬度調變 (PWM) 控制器的存取權,該控制器屬於 SoC 的一部分,並記憶體對應至 SoC 位址空間,您必須撰寫核心模式驅動程式。 驅動程式必須註冊 PWM 控制器的裝置類別介面,讓 UWP 應用程式可以透過 Windows.Devices.Pwm 命名空間中定義的 PWM WinRT API 來存取系統公開的 PWM 裝置。
備註
如果您有透過 I2C、SPI 或 UART 控制器的附加元件 PWM 模組,您可以使用 Windows.Devices.Pwm 和 Windows.Devices.Pwm.Provider 命名空間中定義的 API,從 UWP 應用程式存取模組。
PWM 裝置抽象化為單一控制器和一或多個引腳。 控制控制器或針腳是透過 PWM 定義的 IOCTL 命令來完成。 例如,LCD 顯示驅動程式會將這類要求傳送至 PWM 驅動程式,以控制 LCD 背光層級。
多控制器和多通道 PWM 訊號生成,其週期、極性和佔空比均可設定,能夠執行以下任務:
- 驅動伺服電機。
- 驅動 LED 或直流有刷馬達等負載。
- 產生類比訊號。
- 生成一個精確的時鐘。
本主題說明,
如何啟用對系統公開 PWM 裝置的 UWP 存取。
如何處理 Win32 應用程式或第三方核心模式驅動程式所傳送的 PWM IOCTL 要求。
目標受眾
- OEM 和 IHV 開發具有 SoC 上 PWM 控制器的系統。
最後更新
- 2017 年 8 月
Windows 版本
- Windows 10 版本
重要的應用程式介面
關於PWM
PWM 描述了產生具有調製脈寬的矩形脈衝波的基本技術,導致波形平均值的變化。
PWM 波形可分為 2 個參數:波形週期 (T) 和佔空比。 波形頻率 (f) 是波形週期 f=1/T 的倒數。 佔空比描述了“開啟”或“活動”時間相對於固定時間間隔或“週期”的比例;低佔空比對應於低輸出功率的平均值,因為大部分時間電源處於關閉狀態。 佔空比以百分比表示,其中 100% 完全開啟,0% 完全關閉,50% 50% 時間為「活動」。
存取系統公開的 PWM 控制器和引腳
PWM 驅動程式必須註冊
GUID_DEVINTERFACE_PWM_CONTROLLER作為裝置介面 GUID,用於公開和存取 PWM 裝置。
// {60824B4C-EED1-4C9C-B49C-1B961461A819}
DEFINE_GUID(GUID_DEVINTERFACE_PWM_CONTROLLER, 0x60824b4c, 0xeed1, 0x4c9c, 0xb4, 0x9c, 0x1b, 0x96, 0x14, 0x61, 0xa8, 0x19);
#define GUID_DEVINTERFACE_PWM_CONTROLLER_WSZ L"{60824B4C-EED1-4C9C-B49C-1B961461A819}"
若要註冊裝置介面 GUID,驅動程式必須在驅動程式的 EVT_WDF_DRIVER_DEVICE_ADD 回呼函式實作中呼叫 WdfDeviceCreateDeviceInterface。 註冊後,系統會為控制器和引腳分配一個符號鏈路。
應用程式或其他驅動程式可以透過 PWM 定義的 IOCTL 來控制控制器或針腳。 在發送 IOCTLs 之前,發送端應用程式或驅動程式必須藉由指定其符號連結,開啟控制器和接腳的檔案控制碼。 這需要驅動程式註冊檔案的建立和關閉事件。 參見(鏈接)
以下是控制器符號路徑的範例:
\??\ACPI#FSCL000E#1#{60824b4c-eed1-4c9c-b49c-1b961461a819}
同樣,引腳的格式如下:路徑的格式如下:
<DeviceInterfaceSymbolicLinkName>\<PinNumber>
其中 <PinNumber> 是要打開的引腳的以 0 為基礎的索引。
以下是引腳符號路徑的範例:
\??\ACPI#FSCL000E#1#{60824b4c-eed1-4c9c-b49c-1b961461a819}\0 ; Opens pin 0
\??\ACPI#FSCL000E#1#{60824b4c-eed1-4c9c-b49c-1b961461a819}\0001 ; Opens pin 1 with the leading 0s have no effect.
若要開啟檔案控制碼,應用程式必須呼叫 Configuration Manager API (CM_Get_Device_Interface_*) 。
開啟檔案控制碼之後,應用程式可以呼叫 DeviceIoControl 函式來傳送這些要求。 請參閱PWM部分。
驅動程式應該使用提供的 PWM 支援常式 PwmParsePinPath 來剖解析和驗證針腳路徑,並擷取針腳號碼。
設定裝置介面屬性
若要從 UWP 應用程式使用 PWM WinRT API,必須設定這些 裝置介面屬性 。
DEVPKEY_DeviceInterface_Restricted
根據目前的 UWP 裝置存取模型,必須將 [受限制的裝置介面] 屬性設定為 FALSE,才能讓 UWP 應用程式存取 PWM 裝置介面。
DEVPKEY_DeviceInterface_SchematicName (連結???)
使用 PwmController.GetDeviceSelector(FriendlyName) 工廠方法需要將原理圖名稱指派給靜態連接的 PWM 裝置的 PWM 裝置介面。 原理圖名稱是系統設計原理圖中賦予 PWM 器件的名稱,例如 (PWM0、PWM_1 等)。 假設線路圖名稱在整個系統中是唯一的,但不會強制執行。 至少,不應該有 2 個具有相同線路圖名稱的 PWM 裝置,否則 WinRT PWM PwmController.GetDeviceSelector(FriendlyName) 行為將會是不確定的。
這些屬性可以透過以下兩種方式之一來設定:
使用 PWM 驅動程式的 INF 檔案
使用 AddProperty 指示詞來設定裝置屬性。 INF 檔案應該允許在一個或子集的 PWM 裝置實例上為相同屬性設定不同的值。 以下是設定DEVPKEY_DeviceInterface_Restricted的範例。
;***************************************** ; Device interface installation ;***************************************** [PWM_Device.NT.Interfaces] AddInterface={60824B4C-EED1-4C9C-B49C-1B961461A819},,PWM_Interface [PWM_Interface] AddProperty=PWM_Interface_AddProperty ; Set DEVPKEY_DeviceInterface_Restricted property to false to allow UWP access ; to the device interface without the need to be bound with device metadata. ; If Restricted property is set to true, then only applications which are bound ; with device metadata would be allowed access to the device interface. [PWM_Interface_AddProperty] {026e516e-b814-414b-83cd-856d6fef4822},6,0x11,,0並非所有設計都有相同的原則來將 PWM 裝置公開給 UWP。 例如,原則可能是允許 UWP 存取 PWM 裝置實例的子集。 公開 PWM 裝置的子集,或將不同的屬性值指派給 PWM 裝置實例的一個或子集,需要每個 PWM 裝置實例都有不同的硬體識別碼,並根據原則選擇性地比對 INF 區段。
假設以 SoC 為基礎的設計,其中有四個名為 PWM0,...,PWM3 的相同 PWM 裝置實例 (IP 區塊),其中其 ACPI 指派的硬體識別碼 (_HID) 為FSCL00E0,其唯一識別碼 (_UID) 為 0,...,3。 將所有 PWM 裝置公開給 UWP 需要 INF 區段,以將 DEVPKEY_DeviceInterface_Restricted 設定為與硬體識別碼 ACPI\FSCL00E0 匹配。
這種設定屬性的方式不需要對驅動程式程式碼進行任何變更。 這是較簡單的選項,因為服務 INF 檔案比驅動程式二進位檔更容易。 權衡的結果是此方法需要針對每個設計專用的 INF 檔案。
在 PWM 驅動程式中程式化地
PWM 驅動程式可以在建立並發佈 PWM 裝置介面之後,呼叫 IoSetDeviceInterfacePropertyData,以在其 EVT_WDF_DRIVER_DEVICE_ADD 實作中設定裝置介面屬性。 驅動程式負責決定要指派的值和裝置屬性。 該資訊通常會儲存在 SoC 型設計的系統 ACPI 中。 每個裝置介面屬性的值都可以在每個 ACPI 裝置節點_DSD方法中指定為 [裝置屬性]。 驅動程式必須從 ACPI 查詢 the_DSD,剖析裝置屬性數據,擷取每個屬性的值,並將其指派到裝置介面。
以程式化方式設定屬性,可讓驅動程式及其 INF 檔案在不同設計和 BSP 之間移植,其中唯一的變更是定義每個 PWM 裝置節點的 ACPI DSDT。 不過,讀取和剖析 ACPI 二進位區塊是一項繁瑣的作業,而且需要大量程式碼,這些程式碼容易發生錯誤和弱點,進而造成更大的錯誤表面。
處理檔案開啟/關閉事件
PWM 驅動程式必須藉由實作 EVT_WDF_DEVICE_FILE_CREATE 和 EVT_WDF_FILE_CLEANUP/EVT_WDF_FILE_CLOSE回呼函式來註冊檔案建立和關閉事件。 在實作中,驅動程式必須執行下列工作:
判斷建立請求是否針對控制器或針腳。
如果要求針腳,驅動程式必須解析並驗證建立針腳請求的針腳路徑,並確定要求的針腳號碼在控制器範圍內。
為控制器和引腳創建請求授予或拒絕存取權。
根據定義良好的狀態機維護控制器和針腳狀態完整性。
在上述一組任務中,可以在 EVT_WDF_DEVICE_FILE_CREATE 中執行第二個驗證任務,如下所示:
如果與要求檔案物件相關聯的檔名為空值,則使用 STATUS_INVALID_DEVICE_REQUEST 完成要求。
如果與要求檔案物件相關聯的檔名是空字串,則這是控制器建立請求,否則是腳位建立請求。
如果這是一個釘選創建請求,則:
根據格式 <DecimalName> 剖解析針腳路徑,並呼叫 PwmParsePinPath 來提取針腳號碼。
如果剖析和驗證引腳路徑失敗,請返回 STATUS_NO_SUCH_FILE 以完成請求。
如果針腳號碼大於或等於控制器針腳數,請使用 STATUS_NO_SUCH_FILE 完成要求。 請注意,引腳編號是從零開始的索引。
否則,繼續處理EVT_WDF_DEVICE_FILE_CREATE。
以下是一個實作前面提到的EVT_WDF_DEVICE_FILE_CREATE處理常式驗證步驟的範例程式碼:
EVT_WDF_DEVICE_FILE_CREATE PwmEvtDeviceFileCreate;
VOID
PwmEvtDeviceFileCreate (
WDFDEVICE WdfDevice,
WDFREQUEST WdfRequest,
WDFFILEOBJECT WdfFileObject
)
{
UNICODE_STRING* filenamePtr = WdfFileObjectGetFileName(WdfFileObject);
IMXPWM_DEVICE_CONTEXT* deviceContextPtr = PwmGetDeviceContext(WdfDevice);
NTSTATUS status;
ULONG pinNumber;
//
// Parse and validate the filename associated with the file object
//
bool isPinInterface;
if (filenamePtr == nullptr) {
WdfRequestComplete(WdfRequest, STATUS_INVALID_DEVICE_REQUEST);
return;
} else if (filenamePtr->Length > 0) {
//
// A non-empty filename means to open a pin under the controller namespace
//
status = PwmParsePinPath(filenamePtr, &pinNumber);
if (!NT_SUCCESS(status)) {
WdfRequestComplete(WdfRequest, status);
return;
}
if (pinNumber >= deviceContextPtr->ControllerInfo.PinCount) {
WdfRequestComplete(WdfRequest, STATUS_NO_SUCH_FILE);
return;
}
isPinInterface = true;
} else {
//
// An empty filename means that the create is against the root controller
//
isPinInterface = false;
}
//
// Continue request processing here
//
}
控制器和引腳共享
控制器和針腳的共用模型會遵循多個讀取器、單一寫入器模式。 控制器/針腳可以開啟以供多個呼叫端讀取,但一次只有一個呼叫端可以開啟該控制器/針腳進行寫入。
開啟檔案句柄時,可以使用所需存取權和共用存取權旗標的組合來實作該模型。 DDI 共享模型選擇使用更簡單的共享語意,其中僅使用「所需的存取」規格來控制存取。 分享存取規格在分享模型中不具任何作用,如果在開啟控制器或針腳時指定,則不會被遵循。
在EVT_WDF_DEVICE_FILE_CREATE中,應根據控制器/引腳狀態來擷取並驗證創建請求的“所需存取權限”和“共用存取權限”,或者根據如下所示:
如果共用存取權不是0,則拒絕存取權,並使用STATUS_SHARING_VIOLATION完成要求。
如果所需存取權是唯讀的,請授與存取權並繼續處理EVT_WDF_DEVICE_FILE_CREATE。
如果所需存取權用於寫入,則:
如果控制器/針腳已開啟進行寫入操作,則拒絕存取,並使用 STATUS_SHARING_VIOLATION 完成要求,否則授予存取權限,將控制器或針腳標示為已開啟以供寫入,並繼續處理 EVT_WDF_DEVICE_FILE_CREATE。
以下範例顯示如何從建立請求中擷取所需存取權和共用存取權:
void
PwmCreateRequestGetAccess(
_In_ WDFREQUEST WdfRequest,
_Out_ ACCESS_MASK* DesiredAccessPtr,
_Out_ ULONG* ShareAccessPtr
)
{
NT_ASSERT(ARGUMENT_PRESENT(DesiredAccessPtr));
NT_ASSERT(ARGUMENT_PRESENT(ShareAccessPtr));
WDF_REQUEST_PARAMETERS wdfRequestParameters;
WDF_REQUEST_PARAMETERS_INIT(&wdfRequestParameters);
WdfRequestGetParameters(WdfRequest, &wdfRequestParameters);
NT_ASSERTMSG(
"Expected create request",
wdfRequestParameters.Type == WdfRequestTypeCreate);
*DesiredAccessPtr =
wdfRequestParameters.Parameters.Create.SecurityContext->DesiredAccess;
*ShareAccessPtr = wdfRequestParameters.Parameters.Create.ShareAccess;
}
控制器和引腳獨立性
控制器和引腳具有父子關係。 若要開啟引腳,您必須先開啟其父控制器。 另一種方法是將引腳視為獨立實體,其中其父控制器僅向引腳提供一項服務,該引腳為該控制器上包含的所有引腳設置全局 PWM 週期。
以下是一些範例案例:
單一進程存取:
製程 A 可以打開引腳,設置其佔空比,使用控制器默認週期啟動它,然後打開控制器並按需設置其週期。 如果應用程式的預設期間是正常的,則可能永遠不需要開啟控制器。
進程可以有多個執行緒,每個執行緒都控制相同控制器下的不同針腳。
多進程存取:
指令行公用程式可以開啟具有唯讀存取權的控制器,以便向主控台顯示資訊。 同時,背景 UWP 任務可以開啟控制器來進行寫入,並使用單一引腳控制某些 LED。
運行於核心模式的顯示驅動程式通過 Pin0 控制 LCD 背光,同時持續佔用控制器進行寫入操作並鎖定 PWM 週期。 同時,Win32 服務會使用顯示驅動程式所設定的 PWM 期間,並使用 Pin1 將某些 LED 調暗,以將某些狀態傳達給使用者。
請注意,將控制器的開啟和關閉與其針腳分開操作有一些重要的影響。 如需詳細資訊,請參閱狀態機一節。
控制器和引腳狀態機
控制器狀態定義
| 狀態特徵 | 預設值 | 說明 |
|---|---|---|
| 已開啟 -For-Write | 否 | False 表示控制器已關閉或已開啟以供讀取;True 表示已開啟寫入。 |
| Desired-Period | 最小期間 |
下列控制器狀態機僅以 Is-Opened-For-Write 狀態為中心。 所需的週期值也被省略,因為它不會影響可以在控制器上執行的操作類型。 請注意,當開啟寫入的控制器被呼叫端關閉時,控制器會重設為其預設值(包含預設所需週期)。
針腳狀態定義
| 狀態特徵 | 預設值 | 說明 |
|---|---|---|
| 已開啟-For-Write | 否 | False 表示針腳已關閉或已開啟供讀取;True 表示已開啟供寫入。 |
| 主動 -Duty-Cycle | 0 | |
| Is-Started | 否 | False 表示已停止;True 表示已啟動。 |
引腳狀態機以 2 種狀態的組合為中心:Is-Opened-For-Write 和 Is-Started。 其他引腳狀態(如極性和主動佔空工作週期)被排除在外,因為它們的值不會影響可以在引腳上執行的操作類型。 請注意,每當開啟寫入的針腳由開啟它進行寫入的呼叫端關閉時,該針腳將恢復到其預設值(停止狀態、預設極性和默認工作週期)。 請注意,狀態轉換中若Is-Started = true 時,Set-Polarity 會被省略,因為在該狀態下它無效。
針對給定狀態未提及的任何轉換都表示此類轉換無效或不可能,並且應以適當的錯誤狀態完成相應的要求。
狀態轉換的實作考量
在 EVT_WDF_DEVICE_FILE_CREATE 中,驅動程式應依據建立請求中所需的存取權,以及控制器或針腳 Is-Opened-For-Write 狀態來授與或拒絕存取權,如下所示:
如果要求具有所需的寫入存取權,且控制器/引腳已開啟以供寫入,則使用 STATUS_SHARING_VIOLATION 完成要求,否則將控制器/引腳標示為已開啟以供寫入 (Is-Opened-For-Write = true),授與存取權並繼續處理。
此範例會實作先前提及的EVT_WDF_DEVICE_FILE_CREATE處理常式存取驗證步驟,其中省略處理並行檔案建立要求的必要鎖定邏輯:
// // Verify request desired access // const bool hasWriteAccess = desiredAccess & FILE_WRITE_DATA; if (isPinInterface) { PWM_PIN_STATE* pinPtr = deviceContextPtr->Pins + pinNumber; if (hasWriteAccess) { if (pinPtr->IsOpenForReadWrite) { PWM_LOG_TRACE("Pin%lu access denied.", pinNumber); WdfRequestComplete(WdfRequest, STATUS_SHARING_VIOLATION); return; } pinPtr->IsOpenForReadWrite = true; } PWM_LOG_TRACE( "Pin%lu Opened. (IsOpenForReadWrite = %lu)", pinNumber, (pinPtr->IsOpenForReadWrite ? 1 : 0)); } else { if (hasWriteAccess) { if (deviceContextPtr->IsControllerOpenForReadWrite) { PWM_LOG_TRACE("Controller access denied."); WdfRequestComplete(WdfRequest, STATUS_SHARING_VIOLATION); return; } deviceContextPtr->IsControllerOpenForReadWrite = true; } PWM_LOG_TRACE( "Controller Opened. (IsControllerOpenForReadWrite = %lu)", (deviceContextPtr->IsControllerOpenForReadWrite ? 1 : 0)); } // // Allocate and fill a file object context // IMXPWM_FILE_OBJECT_CONTEXT* fileObjectContextPtr; { WDF_OBJECT_ATTRIBUTES wdfObjectAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &wdfObjectAttributes, IMXPWM_FILE_OBJECT_CONTEXT); void* contextPtr; NTSTATUS status = WdfObjectAllocateContext( WdfFileObject, &wdfObjectAttributes, &contextPtr); if (!NT_SUCCESS(status)) { IMXPWM_LOG_ERROR( "WdfObjectAllocateContext(...) failed. (status = %!STATUS!)", status); WdfRequestComplete(WdfRequest, status); return; } fileObjectContextPtr = static_cast<IMXPWM_FILE_OBJECT_CONTEXT*>(contextPtr); NT_ASSERT(fileObjectContextPtr != nullptr); fileObjectContextPtr->IsPinInterface = isPinInterface; fileObjectContextPtr->IsOpenForWrite = hasWriteAccess; fileObjectContextPtr->PinNumber = pinNumber; }在EVT_WDF_FILE_CLOSE/EVT_WDF_FILE_CLEANUP中,驅動程式應該維護控制器/針腳狀態完整性。
如果檔案物件屬於開啟該控制器/引腳進行寫入的控制器/引腳,則將控制器/引腳重設為預設狀態,並將該控制器/引腳標示為不再開啟以進行寫入(Is-Opened-For-Write = false)。
此範例會實作先前提及的EVT_WDF_DEVICE_FILE_CLOSE處理常式存取驗證步驟,其中省略處理並行檔案關閉要求的必要鎖定邏輯。
EVT_WDF_DEVICE_FILE_CLOSE PwmEvtFileClose; VOID PwmEvtFileClose ( WDFFILEOBJECT WdfFileObject ) { WDFDEVICE wdfDevice = WdfFileObjectGetDevice(WdfFileObject); PWM_DEVICE_CONTEXT* deviceContextPtr = PwmGetDeviceContext(wdfDevice); PWM_FILE_OBJECT_CONTEXT* fileObjectContextPtr = PwmGetFileObjectContext(WdfFileObject); if (fileObjectContextPtr->IsPinInterface) { if (fileObjectContextPtr->IsOpenForReadWrite) { const ULONG pinNumber = fileObjectContextPtr->PinNumber; NTSTATUS status = PwmResetPinDefaults(deviceContextPtr, pinNumber); if (!NT_SUCCESS(status)) { PWM_LOG_ERROR( "PwmResetPinDefaults(...) failed. " "(pinNumber = %lu, status = %!STATUS!)", pinNumber, status); // // HW Error Recovery // } NT_ASSERT(deviceContextPtr->Pins[pinNumber].IsOpenForReadWrite); deviceContextPtr->Pins[pinNumber].IsOpenForReadWrite = false; } PWM_LOG_TRACE("Pin%lu Closed.", fileObjectContextPtr->PinNumber); } else { if (fileObjectContextPtr->IsOpenForReadWrite) { NTSTATUS status = PwmResetControllerDefaults(deviceContextPtr); if (!NT_SUCCESS(status)) { IMXPWM_LOG_ERROR( "PwmResetControllerDefaults(...) failed. (status = %!STATUS!)", status); // // HW Error Recovery // } NT_ASSERT(deviceContextPtr->IsControllerOpenForReadWrite); deviceContextPtr->IsControllerOpenForReadWrite = false; } PWM_LOG_TRACE("Controller Closed."); } }
PWM IOCTL 請求
PWM IOCTL 要求由應用程式或其他驅動程式發出,目標對象是控制器或特定針腳。
控制器 IOCTL
- IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD
- IOCTL_PWM_CONTROLLER_GET_INFO
- IOCTL_PWM_CONTROLLER_SET_DESIRED_PERIOD
腳位 IOCTL
- IOCTL_PWM_PIN_GET_ACTIVE_DUTY_CYCLE_PERCENTAGE
- IOCTL_PWM_PIN_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE
- IOCTL_PWM_PIN_GET_POLARITY
- IOCTL_PWM_PIN_SET_POLARITY
- IOCTL_PWM_PIN_START
- IOCTL_PWM_PIN_STOP
- IOCTL_PWM_PIN_IS_STARTED
針對每個 IOCTL 要求,PWM 驅動程式必須驗證下列項目:
要求的作業 (IOCTL 程式代碼) 對要求相關聯的檔案物件有效。
要求輸入和輸出緩衝區,並確定它們至少為預期大小下限。
目前控制器/針腳狀態下所要求作業的有效性。
個別輸入參數的有效性。 例如:所需的週期為零是IOCTL_PWM_CONTROLLER_SET_DESIRED_PERIOD的無效參數。
IOCTL 完成狀態碼
PWM 驅動程式必須使用適當的狀態碼完成 IOCTL 要求。 以下是常見的完成狀態碼。 一般而言,對於已設定值的屬性進行設定的 IOCTL 應該總是會成功。 例如,設定與已設定相同的週期、停止已停止的引腳、設定已設定的極性等等。
STATUS_NOT_SUPPORTED
未實作或支援要求的 IOCTL 作業。 例如,某些控制器可能不支援設定輸出信號的極性。在這種情況下,應該實作 IOCTL_PWM_PIN_SET_POLARITY,但對於非預設極性,會以 STATUS_NOT_SUPPORTED 失敗。
STATUS_INVALID_DEVICE_REQUEST
IOCTL 要求已傳送至錯誤的目標。 例如,控制器的 IOCTL 請求是使用固定檔案控制代碼傳送的。
STATUS_BUFFER_TOO_SMALL
輸入或輸出緩衝區大小小於處理要求所需的緩衝區大小下限。 使用 WdfRequestRetrieveInputBuffer 或 WdfRequestRetrieveOutputBuffer 來擷取和驗證輸入和輸出緩衝區的 WDF 驅動程式可以依原樣傳回其對應的錯誤狀態。 所有已定義輸入和/或輸出緩衝區的 IOCTL 都有對應的結構,可描述該緩衝區,其中輸入和輸出結構名稱 分別具有 INPUT 和 _OUTPUT 後置詞。輸入緩衝區最小大小為 sizeof(PWMINPUT),而輸出緩衝區最小大小為 sizeof(PWM_OUTPUT)。
| IOCTL 代碼 | 說明 |
|---|---|
| IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD (輸入/輸出控制碼_PWM控制器取得實際周期) | 擷取脈衝寬度調節器 (PWM) 控制器的有效輸出訊號期間,因為它會在輸出通道上測量。 傳回PWM_CONTROLLER_GET_ACTUAL_PERIOD_OUTPUT值。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|
| IOCTL_PWM_CONTROLLER_GET_INFO | 擷取脈衝寬度調節器 (PWM) 控制器的相關信息。 初始化控制器之後,這項資訊不會變更。 呼叫端應該傳遞輸出緩衝區,其大小完全符合PWM_CONTROLLER_INFO結構的大小。 驅動程式會從要求輸出緩衝區大小推斷結構的版本。 如果緩衝區大小小於最低結構版本的大小,則會使用 IOCTL 完成狀態 STATUS_BUFFER_TOO_SMALL 來完成要求。 否則,驅動程式會假設可以符合所提供輸出緩衝區的最高結構版本,並成功完成要求。 較新的PWM_CONTROLLER_INFO版本的位元組大小大於舊版的位元組大小 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|
| IOCTL_PWM_CONTROLLER_SET_DESIRED_PERIOD(設定期望的PWM週期控制器) | 將脈衝寬度調節器 (PWM) 控制器的輸出訊號週期設定為建議的值。 PWM 控制器嘗試根據其功能設定盡可能接近請求值的週期。 IOCTL 輸出的結果為有效期間。 稍後可以使用IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD來擷取它。 所需的週期必須大於零 (0) 且在控制器支援的週期範圍內。 也就是說,它必須在 MinimumPeriod 和 MaximumPeriod(均含)的範圍內,可以使用 IOCTL_PWM_CONTROLLER_GET_INFO 來擷取。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|
| IOCTL_PWM_PIN_GET_ACTIVE_DUTY_CYCLE_PERCENTAGE | 擷取針腳或通道的目前工作週期百分比。 控制件程式代碼會以PWM_PIN_GET_ACTIVE_DUTY_CYCLE_PERCENTAGE_OUTPUT結構傳回百分比。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|
| IOCTL_PWM_PIN_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE(設定PWM引腳的啟動佔空比百分比) | 設定控制器針腳或通道所需的工作週期百分比值。 控制程式代碼會將百分比指定為 PWM_PIN_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE_INPUT 結構。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|
| IOCTL_PWM_PIN_GET_POLARITY | 擷取針腳或通道的目前訊號極性。 控件程式代碼會以PWM_PIN_GET_POLARITY_OUTPUT結構的形式取得訊號極性。 訊號極性為 Active High 或 Active Low,如PWM_POLARITY列舉中所定義。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|
| IOCTL_PWM_PIN_SET_POLARITY | 設定針腳或通道的訊號極性。 控件程式代碼會根據PWM_PIN_SET_POLARITY_INPUT結構來設定訊號極性。 訊號極性為高電平有效或低電平有效,如PWM_POLARITY枚舉中所定義。 只有在引腳停止時才允許改變極性。 您可以使用IOCTL_PWM_PIN_IS_STARTED控制碼來判斷引腳是否已停止。 如果針腳已停止,且所請求的極性與目前針腳極性不同,則請求將以 STATUS_INVALID_DEVICE_STATE 值完成。 在啟動引腳時更改極性可能會導致某些脈寬調變控制器出現毛刺。 如果要更改極性,請先停止引腳,更改極性,然後啟動引腳。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|
| IOCTL_PWM_PIN_START | 開始在針腳或通道上產生脈衝寬度調節(PWM)訊號。 若要檢查是否已啟動針腳,請使用 IOCTL_PWM_PIN_IS_STARTED。 在已啟動的接腳或通道上發出此 IOCTL 不會造成任何影響,但仍會成功。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。 >
|
| IOCTL_PWM_PIN_STOP | 停止在針腳或通道上產生脈衝寬度調節(PWM)訊號。 若要檢查是否已啟動針腳,請使用 IOCTL_PWM_PIN_IS_STARTED。 在已停止的針腳或通道上發出此 IOCTL 沒有任何作用,但會成功。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|
| IOCTL_PWM_PIN_IS_STARTED | 擷取針腳或通道的訊號產生狀態。 每個針腳的狀態皆為啟動或停止,做為PWM_PIN_IS_STARTED_OUTPUT結構。 開始狀態的布林值為 true。 停止狀態為 (false)。 根據預設,針腳會在開啟時仍處於停止狀態,並在關閉或釋放時返回停止狀態。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
|