# PWM
## Overview
Pulse width modulation (PWM) is a technology that digitally encodes analog signal levels and converts them into pulses. It can be used for motor control and backlight brightness adjustment.
The PWM APIs provide a set of functions for operating a PWM device, including those for:
- Opening or closing a PWM device handle
- Setting the PWM period, signal ON-state time, and polarity
- Enabling and disabling a PWM device
- Obtaining and setting PWM parameters
### PwmConfig Structure
**Table 1** PwmConfig structure
| Parameter| Description|
| -------- | -------- |
| duty | Time that a signal is in the ON state, in ns.|
| period | Time for a signal to complete an on-and-off cycle, in ns.|
| number | Number of square waves to generate.
- Positive value: indicates the number of square waves to generate.
- **0**: indicates that square waves are generated continuously.|
| polarity | PWM signal polarity, which can be positive or reverse.|
| status | PWM device status, which can be enabled or disabled.|
## Available APIs
**Table 2** PWM driver APIs
| Category| Description|
| -------- | -------- |
| Operating PWM handles| - **PwmOpen**: opens the device handle of a PWM device.
- **PwmClose**: closes the device handle of a PWM device.|
| Enabling or disabling PWM| - **PwmEnable**: enables a PWM device.
- **PwmDisable**: disables a PWM device.|
| Setting PWM| - **PwmSetPeriod**: sets the PWM period.
- **PwmSetDuty**: sets the signal ON-state time.
- **PwmSetPolarity**: sets the PWM signal polarity.|
| Setting or obtaining PWM configuration| - **PwmSetConfig**: sets PWM device parameters.
- **PwmGetConfig**: obtains PWM device parameters.|
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> All APIs described in this document can be called only in the kernel space.
## Usage Guidelines
### How to Use
The figure below shows the general process of using the PWM.
**Figure 1** Process of using the PWM module
![](figures/process-of-using-PWM.png)
### Opening a PWM Device Handle
Before performing operations on a PWM device, call **PwmOpen** to open the device handle.
```
DevHandle PwmOpen(uint32_t num);
```
**Table 3** Description of PwmOpen
| **Parameter**| **Description**|
| -------- | -------- |
| num | PWM device number. |
| **Return Value** | **Description** |
| handle | Handle of the PWM device obtained.|
| NULL | The operation fails. |
Example: Open the device handle of PWM device 0.
```
uint32_t num = 0; /* PWM device number. */
DevHandle handle = NULL;
/* Obtain the PWM device handle. */
handle = PwmOpen(num);
if (handle == NULL) {
/* Error handling. */
}
```
### Closing a PWM Device Handle
Call **PwmClose()** to close a PWM device handle to release resources.
```
voidPwmClose(DevHandle handle);
```
**Table 4** Description of PwmClose
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle to close. |
```
/* Close a PWM device handle. */
PwmClose(handle);
```
### Enabling a PWM Device
Call **PwmEnable()** to enable a PWM device.
```
int32_t PwmEnable(DevHandle handle);
```
**Table 5** Description of PwmEnable
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle. |
| **Return Value** | **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
```
int32_t ret;
/* Enable a PWM device. */
ret = PwmEnable(handle);
if (ret != 0) {
/* Error handling. */
}
```
### Disabling a PWM Device
Call **PwmDisable()** to disable a PWM device.
```
int32_t PwmDisable(DevHandle handle);
```
**Table 6** Description of PwmDisable
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle. |
| **Return Value** | **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
```
int32_t ret;
/* Disable a PWM device. */
ret = PwmDisable(handle);
if (ret != 0) {
/* Error handling. */
}
```
### Setting the PWM Period
Call **PwmSetPeriod()** to set the PWM period.
```
int32_t PwmSetPeriod(DevHandle handle, uint32_t period);
```
**Table 7** Description of PwmSetPeriod
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle. |
| period | PWM period to set, in ns.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
```
int32_t ret;
/* Set the PWM period to 50000000 ns.*/
ret = PwmSetPeriod(handle, 50000000);
if (ret != 0) {
/* Error handling. */
}
```
### Setting the PWM Signal ON-State Time
Call **PwmSetDuty()** to set the time that the PWM signal is in the ON state.
```
int32_t PwmSetDuty(DevHandle handle, uint32_t duty);
```
**Table 8** Description of PwmSetDuty
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle. |
| duty | Time that the signal is in the ON state, in ns.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
```
int32_t ret;
/* Set the signal ON-state time to 25000000 ns. */
ret = PwmSetDuty(handle, 25000000);
if (ret != 0) {
/* Error handling. */
}
```
### Setting the PWM Signal Polarity
Call **PwmSetPolarity()** to set the signal polarity for a PWM device.
```
int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity);
```
**Table 9** Description of PwmSetPolarity
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle. |
| polarity | Polarity to set, which can be **PWM\_NORMAL\_POLARITY** or **PWM\_INVERTED\_POLARITY**.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
```
int32_t ret;
/* Set the PWM polarity to PWM_INVERTED_POLARITY. */
ret = PwmSetPolarity(handle, PWM_INVERTED_POLARITY);
if (ret != 0) {
/* Error handling. */
}
```
### Setting PWM Device Parameters
Call **PwmSetConfig()** to set PWM device parameters.
```
int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config);
```
**Table 10** Description of PwmSetConfig
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle to close. |
| \*config | Pointer to PWM parameters. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
```
int32_t ret;
struct PwmConfig pcfg;
pcfg.duty = 25000000; /* Set the signal ON-state time to 25000000 ns. */
pcfg.period = 50000000; /* Set the PWM period to 50000000 ns. */
pcfg.number = 0; /* Generate square waves repeatedly. */
pcfg.polarity = PWM_INVERTED_POLARITY; /* Set the PWM polarity to PWM_INVERTED_POLARITY. */
pcfg.status = PWM_ENABLE_STATUS; /* Set the running status to Enabled. */
/* Set PWM device parameters. */
ret = PwmSetConfig(handle, &pcfg);
if (ret != 0) {
/* Error handling. */
}
```
### Obtaining PWM Device Parameters
Call **PwmGetConfig()** to obtain PWM device parameters.
```
int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config);
```
**Table 11** Description of PwmGetConfig
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle to close. |
| \*config | Pointer to PWM parameters. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
```
int32_t ret;
struct PwmConfig pcfg;
/* Obtain PWM device parameters. */
ret = PwmGetConfig(handle, &pcfg);
if (ret != 0) {
/* Error handling. */
}
```
## Development Example
The following example shows how to use the APIs to implement a PWM driver and manage the PWM device.
```
void PwmTestSample(void)
{
int32_t ret;
uint32_t num;
DevHandle handle = NULL;
struct PwmConfig pcfg;
pcfg.duty = 20000000; /* Set the signal ON-state time to 20000000 ns. */
pcfg.period = 40000000; /* Set the PWM period to 40000000 ns. */
pcfg.number = 100; /* Generate 100 square waves. */
pcfg.polarity = PWM_NORMAL_POLARITY; /* Set the polarity to PWM_NORMAL_POLARITY. */
pcfg.status = PWM_ENABLE_STATUS; /* Set the running status to Enabled. */
/* Enter the PWM device number. */
num = 1;
/* Open the PWM device handle. */
handle = PwmOpen(num);
if (handle == NULL) {
HDF_LOGE("PwmOpen: failed!\n");
return;
}
/* Set the PWM period to 50000000 ns.*/
ret = PwmSetPeriod(handle, 50000000);
if (ret != 0) {
HDF_LOGE("PwmSetPeriod: failed, ret %d\n", ret);
goto _ERR;
}
/* Set the signal ON-state time to 25000000 ns. */
ret = PwmSetDuty(handle, 25000000);
if (ret != 0) {
HDF_LOGE("PwmSetDuty: failed, ret %d\n", ret);
goto _ERR;
}
/* Set the PWM polarity to PWM_INVERTED_POLARITY. */
ret = PwmSetPolarity(handle, PWM_INVERTED_POLARITY);
if (ret != 0) {
HDF_LOGE("PwmSetPolarity: failed, ret %d\n", ret);
goto _ERR;
}
/* Obtain PWM device parameters. */
ret = PwmGetConfig(handle, &pcfg);
if (ret != 0) {
HDF_LOGE("PwmGetConfig: failed, ret %d\n", ret);
goto _ERR;
}
/* Enable the PWM device. */
ret = PwmEnable(handle);
if (ret != 0) {
HDF_LOGE("PwmEnable: failed, ret %d\n", ret);
goto _ERR;
}
/* Set PWM device parameters. */
ret = PwmSetConfig(handle, &pcfg);
if (ret != 0) {
HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret);
goto _ERR;
}
/* Disable the PWM device. */
ret = PwmDisable(handle);
if (ret != 0) {
HDF_LOGE("PwmDisable: failed, ret %d\n", ret);
goto _ERR;
}
_ERR:
/* Close the PWM device handle. */
PwmClose(handle);
}
```