Files
mr-library/document/device/pwm/pwm_EN.md
2024-02-02 16:38:44 +08:00

7.5 KiB

PWM Device

中文

Open PWM Device

int mr_dev_open(const char *path, int flags);
Parameter Description
path Device path
flags Flag for opening device
Return Value
>=0 Device descriptor
<0 Error code
  • path: PWM device path usually is: pwmxpwm1pwm2.
  • flags: Flag for opening device, support MR_O_RDONLYMR_O_WRONLYMR_O_RDWR.

Note: When using, the PWM device should be opened separately for different tasks with the appropriate flags for management and permission control, to ensure they will not interfere with each other.

Close PWM Device

int mr_dev_close(int desc);
Parameter Description
desc Device descriptor
Return Value
=0 Close successfully
<0 Error code

Note: When closing the device, all channels will be automatically restored to the default configuration. The channels need to be reconfigured after reopening (can disable this feature).

Control PWM Device

int mr_dev_ioctl(int desc, int cmd, void *args);
Parameter Description
desc Device descriptor
cmd Command code
args Command parameter
Return Value
=0 Set successfully
<0 Error code
  • cmd: Command code, support:
    • MR_IOC_PWM_SET_CHANNEL: Set channel number.
    • MR_IOC_PWM_SET_CHANNEL_CONFIG: Set channel configuration.
    • MR_IOC_PWM_SET_FREQ: Set frequency.
    • MR_IOC_PWM_GET_CHANNEL: Get channel number.
    • MR_IOC_PWM_GET_CHANNEL_CONFIG: Get channel configuration.
    • MR_IOC_PWM_GET_FREQ: Get frequency.

Set/Get Channel Number

Channel number range: 0 ~ 31.

/* Define channel number */
#define CHANNEL_NUMBER                  1

/* Set channel number */   
mr_dev_ioctl(ds, MR_IOC_PWM_SET_CHANNEL, MR_MAKE_LOCAL(int, CHANNEL_NUMBER));

/* Get channel number */
int number;
mr_dev_ioctl(ds, MR_IOC_PWM_GET_CHANNEL, &number);

Independent of PWM interface:

/* Define channel number */
#define CHANNEL_NUMBER                  1

/* Set channel number */   
mr_dev_ioctl(ds, MR_IOC_SPOS, MR_MAKE_LOCAL(int, CHANNEL_NUMBER));

/* Get channel number */
int number;
mr_dev_ioctl(ds, MR_IOC_GPOS, &number);

Set/Get Channel Configuration

Channel configuration:

  • MR_DISABLE: Disable channel.
  • MR_ENABLE: Enable channel.
struct mr_pwm_config config = {MR_ENABLE, MR_PWM_POLARITY_NORMAL};

/* Set channel configuration */
mr_dev_ioctl(ds, MR_IOC_PWM_SET_CHANNEL_CONFIG, &config);
/* Get channel configuration */  
mr_dev_ioctl(ds, MR_IOC_PWM_GET_CHANNEL_CONFIG, &config);

Independent of PWM interface:

int config[] = {MR_ENABLE, 0};

/* Set channel configuration */
mr_dev_ioctl(ds, MR_IOC_SCFG, &config);
/* Get channel configuration */  
mr_dev_ioctl(ds, MR_IOC_GCFG, &config);

Set/Get Frequency

/* Define frequency */
#define PWM_FREQ                        1000

/* Set frequency */
mr_dev_ioctl(ds, MR_IOC_PWM_SET_FREQ, MR_MAKE_LOCAL(uint32_t, PWM_FREQ));  

/* Get frequency */
uint32_t freq;
mr_dev_ioctl(ds, MR_IOC_PWM_GET_FREQ, &freq);

Independent of PWM interface:

/* Define frequency */
#define PWM_FREQ                        1000

/* Set frequency */
mr_dev_ioctl(ds, (0x01), MR_MAKE_LOCAL(uint32_t, PWM_FREQ));  

/* Get frequency */
uint32_t freq;
mr_dev_ioctl(ds, (-(0x01)), &freq);

Read PWM Channel Duty Cycle

ssize_t mr_dev_read(int desc, void *buf, size_t count);
Parameter Description
desc Device descriptor
buf Read data buffer
count Read data size
Return Value
>=0 Size of reading data
<0 Error code
/* Read duty cycle */
uint32_t duty;
int ret = mr_dev_read(ds, &duty, sizeof(duty));
/* Check if reading succeeds */
if (ret != sizeof(duty))
{
    return ret;
}

Note: The reading data is PWM duty cycle, ranging from 0 to 1000000. The minimum unit for single reading is uint32_t, which is 4 bytes.

Write PWM Channel Duty Cycle

ssize_t mr_dev_write(int desc, const void *buf, size_t count);  
Parameter Description
desc Device descriptor
buf Write data buffer
count Write data size
Return Value
>=0 Size of writing data
<0 Error code
/* Write duty cycle */
uint32_t duty = 500000;
int ret = mr_dev_write(ds, &duty, sizeof(duty));
/* Check if writing succeeds */
if (ret != sizeof(duty))
{
    return ret;
}

Note: The writing data is PWM duty cycle, ranging from 0 to 1000000. The minimum unit for single writing is uint32_t, which is 4 bytes.

Example:

#include "include/mr_lib.h"

/* Define channel number and frequency */
#define CHANNEL_NUMBER                  1
#define FREQ                            1000

/* PWM device descriptor */  
int pwm_ds = -1;

void pwm_init(void)
{
    int ret = MR_EOK;

    /* PWM initialization */
    pwm_ds = mr_dev_open("pwm1", MR_O_RDWR);
    if (pwm_ds < 0)
    {
        mr_printf("PWM1 open failed: %s\r\n", mr_strerror(pwm_ds));
        return;
    }
    /* Print PWM descriptor */
    mr_printf("PWM1 desc: %d\r\n", pwm_ds);
    /* Set to channel 1*/ 
    mr_dev_ioctl(pwm_ds, MR_IOC_PWM_SET_CHANNEL, MR_MAKE_LOCAL(int, CHANNEL_NUMBER));
    /* Set channel enable */
    ret = mr_dev_ioctl(pwm_ds, MR_IOC_PWM_SET_CHANNEL_CONFIG, MR_MAKE_LOCAL(struct mr_pwm_config, MR_ENABLE, MR_PWM_POLARITY_NORMAL));
    if (ret < 0)
    {
        mr_printf("Channel%d enable failed: %s\r\n", CHANNEL_NUMBER, mr_strerror(ret));
        return;
    }
    ret = mr_dev_ioctl(pwm_ds, MR_IOC_PWM_SET_FREQ, MR_MAKE_LOCAL(uint32_t, FREQ));
    if (ret < 0)
    {
        mr_printf("Freq configure failed: %s\r\n", mr_strerror(ret));
    }
}
/* Export to automatic initialization (APP level) */
MR_INIT_APP_EXPORT(pwm_init);

int main(void)
{
    /* Automatically initialize (pwm_init function will be automatically called here) */
    mr_auto_init();
    
    /* Write duty cycle */
    uint32_t duty = 500000;
    int ret = mr_dev_write(pwm_ds, &duty, sizeof(duty));
    /* Check if writing succeeds */
    if (ret != sizeof(duty))
    {
        mr_printf("Write failed: %s\r\n", mr_strerror(ret));
        return ret;
    }

    while(1)
    {

    }
}

The PWM frequency is set to 1000Hz, and channel 1 outputs 50% duty cycle.