# 15.02_MCPWM-不同的IO状态配置  

## 测试步骤  
1.配置MCPWM模块以输出三路中心对称的PWM信号，TH设置为2000，实际周期为2*TH+1 => 4000。
2.配置GPIO引脚复用为MCPWM功能。
3.在主循环中，通过MCPWM_SetIOConfig()函数，设置MCPWM输出的IO状态，默认MCPWM_IO_HL_PWM。
## 实测数据  
|模式|MCPWM_CH0P占空比|MCPWM_CH0N占空比|说明|  
|-|-|-|-|  
|MCPWM_IO_DISABLE|20.01%|70.03%|不使用该通道(默认配置：上管高有效，下管高有效，正常输出PWM)|  
|MCPWM_IO_HH_PWM|20.01%|70.02%|上管高有效，下管高有效，正常输出PWM|  
|MCPWM_IO_HH_LOW|0.00%|100.00%|上管高有效，下管高有效，下管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_HH_HIGH|100.00%|0.00%|上管高有效，下管高有效，上管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_HH_HPWM|20.01%|0.00%|上管高有效，下管高有效，上管斩波|  
|MCPWM_IO_HH_LPWM|0.00%|70.03%|上管高有效，下管高有效，下管斩波|  
|MCPWM_IO_HH_OFF|0.00%|0.00%|上管高有效，下管高有效，上下管全关，和MOE不同，通过IO可以关闭任意一路pwm|  
|MCPWM_IO_HHS_PWM|70.02%|20.01%|上管高有效，下管高有效，通道交换打开，正常输出PWM|  
|MCPWM_IO_HHS_LOW|100.00%|0.00%|上管高有效，下管高有效，通道交换打开，下管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_HHS_HIGH|0.00%|100.00%|上管高有效，下管高有效，通道交换打开，上管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_HHS_HPWM|0.00%|20.01%|上管高有效，下管高有效，通道交换打开，上管斩波|  
|MCPWM_IO_HHS_LPWM|70.02%|0.00%|上管高有效，下管高有效，通道交换打开，下管斩波|  
|MCPWM_IO_HHS_OFF|0.00%|0.00%|上管高有效，下管高有效，通道交换打开，上下管全关，和MOE不同，通过IO可以关闭任意一路pwm|  
|MCPWM_IO_HL_PWM|20.02%|30.06%|上管高有效，下管低有效，正常输出PWM|  
|MCPWM_IO_HL_LOW|0.00%|0.00%|上管高有效，下管低有效，下管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_HL_HIGH|100.00%|100.00%|上管高有效，下管低有效，上管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_HL_HPWM|20.01%|100.00%|上管高有效，下管低有效，上管斩波|  
|MCPWM_IO_HL_LPWM|0.00%|30.06%|上管高有效，下管低有效，下管斩波|  
|MCPWM_IO_HL_OFF|0.00%|100.00%|上管高有效，下管低有效，上下管全关，和MOE不同，通过IO可以关闭任意一路pwm|  
|MCPWM_IO_HLS_PWM|30.06%|20.01%|上管高有效，下管低有效，通道交换打开，正常输出PWM|  
|MCPWM_IO_HLS_LOW|0.00%|0.00%|上管高有效，下管低有效，通道交换打开，下管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_HLS_HIGH|100.00%|100.00%|上管高有效，下管低有效，通道交换打开，上管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_HLS_HPWM|100.00%|20.01%|上管高有效，下管低有效，通道交换打开，上管斩波|  
|MCPWM_IO_HLS_LPWM|30.06%|0.00%|上管高有效，下管低有效，通道交换打开，下管斩波|  
|MCPWM_IO_HLS_OFF|100.00%|0.00%|上管高有效，下管低有效，通道交换打开，上下管全关，和MOE不同，通过IO可以关闭任意一路pwm|  
|MCPWM_IO_LH_PWM|80.07%|70.02%|上管低有效，下管高有效，正常输出PWM|  
|MCPWM_IO_LH_LOW|100.00%|100.00%|上管低有效，下管高有效，下管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_LH_HIGH|0.00%|0.00%|上管低有效，下管高有效，上管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_LH_HPWM|80.07%|0.00%|上管低有效，下管高有效，上管斩波|  
|MCPWM_IO_LH_LPWM|100.00%|70.03%|上管低有效，下管高有效，下管斩波|  
|MCPWM_IO_LH_OFF|100.00%|0.00%|上管低有效，下管高有效，上下管全关，和MOE不同，通过IO可以关闭任意一路pwm|  
|MCPWM_IO_LHS_PWM|70.02%|80.08%|上管低有效，下管高有效，通道交换打开，正常输出PWM|  
|MCPWM_IO_LHS_LOW|100.00%|100.00%|上管低有效，下管高有效，通道交换打开，下管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_LHS_HIGH|0.00%|0.00%|上管低有效，下管高有效，通道交换打开，上管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_LHS_HPWM|0.00%|80.07%|上管低有效，下管高有效，通道交换打开，上管斩波|  
|MCPWM_IO_LHS_LPWM|70.03%|100.00%|上管低有效，下管高有效，通道交换打开，下管斩波|  
|MCPWM_IO_LHS_OFF|0.00%|100.00%|上管低有效，下管高有效，通道交换打开，上下管全关，和MOE不同，通过IO可以关闭任意一路pwm|  
|MCPWM_IO_LL_PWM|80.08%|30.06%|上管低有效，下管低有效，正常输出PWM|  
|MCPWM_IO_LL_LOW|100.00%|0.00%|上管低有效，下管低有效，下管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_LL_HIGH|0.00%|100.00%|上管低有效，下管低有效，上管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_LL_HPWM|80.08%|100.00%|上管低有效，下管低有效，上管斩波|  
|MCPWM_IO_LL_LPWM|100.00%|30.06%|上管低有效，下管低有效，下管斩波|  
|MCPWM_IO_LL_OFF|100.00%|100.00%|上管低有效，下管低有效，上下管全关，和MOE不同，通过IO可以关闭任意一路pwm|  
|MCPWM_IO_LLS_PWM|30.06%|80.07%|上管低有效，下管低有效，通道交换打开，正常输出PWM|  
|MCPWM_IO_LLS_LOW|0.00%|100.00%|上管低有效，下管低有效，通道交换打开，下管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_LLS_HIGH|100.00%|0.00%|上管低有效，下管低有效，通道交换打开，上管恒开 此时pwm配置无效，但仍然会正常计数&触发中断|  
|MCPWM_IO_LLS_HPWM|100.00%|80.07%|上管低有效，下管低有效，通道交换打开，上管斩波|  
|MCPWM_IO_LLS_LPWM|30.06%|100.00%|上管低有效，下管低有效，通道交换打开，下管斩波|  
|MCPWM_IO_LLS_OFF  |100.00%|100.00%|上管低有效，下管低有效，通道交换打开，上下管全关，和MOE不同，通过IO可以关闭任意一路pwm|  

## 参考代码  
15.02_MCPWM_IO.c
```c
/**
 * @brief MCPWM-不同的IO状态配置
 * @details
 * 1.配置MCPWM模块以输出三路中心对称的PWM信号，TH设置为2000，实际周期为2*TH+1 => 4000。
 * 2.配置GPIO引脚复用为MCPWM功能。
 * 3.在主循环中，通过MCPWM_SetIOConfig()函数，设置MCPWM输出的IO状态，默认MCPWM_IO_HL_PWM。
 */
#include "lks32mc09x_gpio.h"
#include "lks32mc09x_mcpwm.h"
#include "lks32mc09x_user_manual.h"
volatile uint32_t setio = MCPWM_IO_HL_PWM;

/**
 * @brief 配置MCPWM输出三路中心对称的PWM，频率20kHz。
 */
void MCPWM_Config(void)
{
    MCPWM_InitTypeDef MCPWM_InitStruct;

    // 初始化MCPWM结构体
    MCPWM_StructInit(&MCPWM_InitStruct);

    // 配置MCPWM基本项
    MCPWM_InitStruct.EN = 1;                    // 使能MCPWM模块
    MCPWM_InitStruct.CLK_DIV = MCPWM_CLK_DIV_1; // 时钟1分频
    MCPWM_InitStruct.TH = 2000;                 // 计数器门限值
    MCPWM_InitStruct.TR = MCPWM_TR_T0;          // 计数器溢出时刻触发自动更新

    // 配置死区时间
    MCPWM_InitStruct.DTHP = 200; // 上管死区时间
    MCPWM_InitStruct.DTHN = 200; // 下管死区时间

    // 配置IO输出
    MCPWM_InitStruct.IO0 = MCPWM_IO_HL_PWM;  // CH0: 上管高有效，下管低有效，正常输出PWM
    MCPWM_InitStruct.IO1 = MCPWM_IO_HL_PWM;  // CH1: 上管高有效，下管低有效，正常输出PWM
    MCPWM_InitStruct.IO2 = MCPWM_IO_HL_PWM;  // CH2: 上管高有效，下管低有效，正常输出PWM
    MCPWM_InitStruct.IO3 = MCPWM_IO_DISABLE; // CH3: 不使用
    MCPWM_InitStruct.FAIL_IO = MCPWM_FAIL_IO_OFF;

    // 配置自动更新使能
    MCPWM_InitStruct.AUEN = MCPWM_AUEN_DEFAULT; // 使能TH0自动加载

    // 配置中断和DMA（本例程中不使用中断和DMA）
    MCPWM_InitStruct.IE = 0;
    MCPWM_InitStruct.EIE = 0;
    MCPWM_InitStruct.RE = 0;

    // 初始化MCPWM模块
    MCPWM_Init(MCPWM0, &MCPWM_InitStruct);

    // 设置输出状态
    MCPWM_SetOutputState(MCPWM0, 1);

    MCPWM_SetOutputVal(MCPWM0, 0, -500, 500); // CH0: 中心对齐，占空比50%
    MCPWM_SetOutputVal(MCPWM0, 1, -500, 500); // CH1: 中心对齐，占空比50%
    MCPWM_SetOutputVal(MCPWM0, 2, -500, 500); // CH2: 中心对齐，占空比50%

    // 开始计数
    MCPWM_StartCount(MCPWM0);
}
/**
 * @brief 主函数
 */
int main(void)
{
    // 配置GPIO引脚复用为MCPWM功能
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_StructInit(&GPIO_InitStruct);

    // 配置P1.4到P1.9为MCPWM功能
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIO1, &GPIO_InitStruct);

    // 配置引脚复用功能为MCPWM
    GPIO_PinAFConfig(GPIO1, GPIO_PinSource_4, GPIO_AF_MCPWM);
    GPIO_PinAFConfig(GPIO1, GPIO_PinSource_5, GPIO_AF_MCPWM);
    GPIO_PinAFConfig(GPIO1, GPIO_PinSource_6, GPIO_AF_MCPWM);
    GPIO_PinAFConfig(GPIO1, GPIO_PinSource_7, GPIO_AF_MCPWM);
    GPIO_PinAFConfig(GPIO1, GPIO_PinSource_8, GPIO_AF_MCPWM);
    GPIO_PinAFConfig(GPIO1, GPIO_PinSource_9, GPIO_AF_MCPWM);

    // 配置MCPWM输出三路中心对称的PWM，频率20kHz
    MCPWM_Config();

    // 主循环
    while (1)
    {
        MCPWM_SetIOConfig(MCPWM0, setio, setio, setio, MCPWM_IO_DISABLE);
    }
}

```

## 使用到的库函数  
库函数部分代码
```c
#define MCPWM_COUNT_START BIT31
#define MCPWM_IO_NP BIT0
#define MCPWM_IO_PN_SW BIT6
#define MCPWM_IO_PP BIT1
#define REG_RESET(reg,mask) reg &= ~(mask)
#define REG_SET(reg,mask) reg |= (mask)
#define REG_WRITE(reg,mask) reg = (mask)
#define SYS0 ((SYS_TypeDef *)(SYS_BASE))
#define SYS_MODULE_GPIO BIT11
#define SYS_MODULE_MCPWM0 BIT10
/**
 * @brief GPIO功能配置结构体句柄
 */
typedef struct GPIO_InitTypeDef {
    uint32_t GPIO_Pin;
    GPIO_Mode_TypeDef GPIO_Mode;
    GPIO_PuPd_TypeDef GPIO_PuPd;
    uint32_t GPIO_PODEna;
    uint32_t GPIO_PFLT;
};
typedef struct MCPWM_InitTypeDef {
    uint16_t EN;
    uint32_t COUNT;
    uint16_t CLK_DIV;
    uint16_t TH;
    uint16_t TR;
    int16_t TMR0;
    int16_t TMR1;
    int16_t TMR2;
    int16_t TMR3;
    uint16_t DTHP;
    uint16_t DTHN;
    uint16_t FLT_DIV;
    uint16_t IO0;
    uint16_t IO1;
    uint16_t IO2;
    uint16_t IO3;
    uint32_t AUEN;
    uint32_t IE;
    uint32_t EIE;
    uint32_t RE;
    uint32_t FAIL_IO;
    uint32_t FAIL0;
    uint32_t FAIL1;
};
/**
 * @brief 初始化GPIO
 * @param GPIOx GPIO模块指针
 * @param GPIO_InitStruct 指向包含初始化参数的GPIO_InitTypeDef结构体
 */
void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct)
{
    // 使能GPIO时钟
    SYS_ModuleClockCmd(SYS_MODULE_GPIO, ENABLE);

    // 配置引脚模式
    if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IN)
    {
        GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin;  // 打开输入使能
        GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
    }
    else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT)
    {
        GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
        GPIOx->POE |= GPIO_InitStruct->GPIO_Pin;  // 使能输出
    }
    else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IO)
    {
        GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin; // 使能输入
        GPIOx->POE |= GPIO_InitStruct->GPIO_Pin; // 使能输出
    }
    else // GPIO_Mode_ANA
    {
        GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
        GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
    }

    if (GPIO_InitStruct->GPIO_PuPd == GPIO_PuPd_UP)
    {
        GPIOx->PUE |= GPIO_InitStruct->GPIO_Pin; // 使能上拉
    }
    else
    {
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉
    }
    // 配置开漏使能
    if (GPIO_InitStruct->GPIO_PODEna)
    {
        GPIOx->PODE |= GPIO_InitStruct->GPIO_Pin;
    }
    else
    {
        GPIOx->PODE &= ~GPIO_InitStruct->GPIO_Pin;
    }

    // 配置滤波使能
    if (GPIO_InitStruct->GPIO_PFLT)
    {
        GPIOx->PFLT |= GPIO_InitStruct->GPIO_Pin;
    }
    else
    {
        GPIOx->PFLT &= ~GPIO_InitStruct->GPIO_Pin;
    }
}
/**
 * @brief 初始化GPIO结构体为默认值
 * @param GPIO_InitStruct 指向要初始化的GPIO_InitTypeDef结构体
 */
void GPIO_StructInit(GPIO_InitTypeDef *GPIO_InitStruct)
{
    for (int i = 0; i < sizeof(GPIO_InitTypeDef); i++)
    {
        ((uint8_t *)GPIO_InitStruct)[i] = 0;
    }
}
/**
 * @brief 初始化MCPWM模块
 * @param MCPWMx MCPWM模块指针
 * @param MCPWM_InitStruct 指向包含初始化参数的MCPWM_InitTypeDef结构体
 */
void MCPWM_Init(MCPWM_TypeDef *MCPWMx, MCPWM_InitTypeDef *MCPWM_InitStruct)
{
    // 复位MCPWM模块
    MCPWM_Reset(MCPWMx);
    if (MCPWM_InitStruct->EN)
    {
        // 使能MCPWM模块
        MCPWM_Enable(MCPWMx);
        // 初始化MCPWM模块
        MCPWMx->PRT = 0xdead; // mcpwm模块解锁
        if (MCPWM_InitStruct->COUNT & MCPWM_COUNT_START)
        {
            MCPWMx->TCLK = BIT6 | (MCPWM_InitStruct->CLK_DIV << 12) | BIT2;
        }
        else
        {
            if (MCPWM_InitStruct->COUNT != 0)
            {
                MCPWMx->TCLK = ((MCPWMx->TCLK & (~BIT6)) | BIT8) | (MCPWM_InitStruct->CLK_DIV << 12) | BIT2; // 关闭计数器，并打开外部触发
                MCPWMx->EVT0 = MCPWM_InitStruct->COUNT;                                                      // 设置外部触发信号
            }
            else
            {
                MCPWMx->TCLK = (MCPWM_InitStruct->CLK_DIV << 12) | BIT2;
            }
        }
        {
            uint16_t chdef = 0;
            chdef          = MCPWM_InitStruct->FAIL_IO;
            if (MCPWM_InitStruct->IO0 & MCPWM_IO_NP)
            {
                chdef ^= BIT0;
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO0 & MCPWM_IO_PP)
            {
                chdef ^= BIT1;
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO1 & MCPWM_IO_NP)
            {
                chdef ^= BIT2;
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO1 & MCPWM_IO_PP)
            {
                chdef ^= BIT3;
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO2 & MCPWM_IO_NP)
            {
                chdef ^= BIT4;
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO2 & MCPWM_IO_PP)
            {
                chdef ^= BIT5;
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO3 & MCPWM_IO_NP)
            {
                chdef ^= BIT6;
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO3 & MCPWM_IO_PP)
            {
                chdef ^= BIT7;
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO0 & MCPWM_IO_PN_SW)
            {
                // 交换chdef的bit0和bit1
                chdef = (chdef & 0xfffe) | ((chdef & 0x0001) << 1) | ((chdef & 0x0002) >> 1);
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO1 & MCPWM_IO_PN_SW)
            {
                // 交换chdef的bit2和bit3
                chdef = (chdef & 0xfffc) | ((chdef & 0x0004) << 1) | ((chdef & 0x0008) >> 1);
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO2 & MCPWM_IO_PN_SW)
            {
                // 交换chdef的bit4和bit5
                chdef = (chdef & 0xfff0) | ((chdef & 0x0010) << 1) | ((chdef & 0x0020) >> 1);
            }
            else
            {
                __NOP();
            }
            if (MCPWM_InitStruct->IO3 & MCPWM_IO_PN_SW)
            {
                // 交换chdef的bit6和bit7
                chdef = (chdef & 0xff00) | ((chdef & 0x0040) << 1) | ((chdef & 0x0080) >> 1);
            }
            else
            {
                __NOP();
            }
            MCPWMx->CH_DEF = chdef;
        }
        MCPWMx->TH00    = 0;
        MCPWMx->TH01    = 0;
        MCPWMx->TH10    = 0;
        MCPWMx->TH11    = 0;
        MCPWMx->TH20    = 0;
        MCPWMx->TH21    = 0;
        MCPWMx->TH30    = 0;
        MCPWMx->TH31    = 0;
        MCPWMx->CNT0    = -MCPWM_InitStruct->TH;
        MCPWMx->TH0     = MCPWM_InitStruct->TH;
        MCPWMx->TMR0    = MCPWM_InitStruct->TMR0;
        MCPWMx->TMR1    = MCPWM_InitStruct->TMR1;
        MCPWMx->TMR2    = MCPWM_InitStruct->TMR2;
        MCPWMx->TMR3    = MCPWM_InitStruct->TMR3;
        MCPWMx->DTH00   = MCPWM_InitStruct->DTHP;
        MCPWMx->DTH01   = MCPWM_InitStruct->DTHN;
        MCPWMx->FLT     = MCPWM_InitStruct->FLT_DIV;
        MCPWMx->IO01    = MCPWM_InitStruct->IO0 | (MCPWM_InitStruct->IO1 << 8);
        MCPWMx->IO23    = MCPWM_InitStruct->IO2 | (MCPWM_InitStruct->IO3 << 8);
        MCPWMx->CH_FAIL = MCPWM_InitStruct->FAIL0 | MCPWM_InitStruct->FAIL1;
        MCPWMx->AUEN    = MCPWM_InitStruct->AUEN;
        MCPWMx->IE0     = MCPWM_InitStruct->IE;
        MCPWMx->EIE     = MCPWM_InitStruct->EIE;
        MCPWMx->RE      = MCPWM_InitStruct->RE;
        MCPWMx->SDCFG   = MCPWM_InitStruct->TR;
        // 更新所有存在影子寄存器的寄存器
        MCPWMx->UPDATE = 0xffffffff;
        MCPWMx->IF0    = 0xffff;
        MCPWMx->EIF    = 0xffff;
        MCPWMx->PRT    = 0x0000; // mcpwm模块上锁
    }
    else
    {
        // 失能MCPWM模块
        MCPWM_Disable(MCPWMx);
    }
}
/**
 * @brief 将MCPWM_InitTypeDef结构体初始化为默认值
 * @param MCPWM_InitStruct 指向要初始化的MCPWM_InitTypeDef结构体
 */
void MCPWM_StructInit(MCPWM_InitTypeDef *MCPWM_InitStruct)
{
    for (int i = 0; i < sizeof(MCPWM_InitTypeDef); i++)
    {
        ((uint8_t *)MCPWM_InitStruct)[i] = 0;
    }
}
/**
 * @brief 开始计数
 * @param MCPWMx MCPWM模块
 * @param count 计数器初始值
 */
void MCPWM_StartCount(MCPWM_TypeDef *MCPWMx)
{
    MCPWMx->PRT = 0xdead; // mcpwm模块解锁
                          //    MCPWMx->UPDATE = BIT11;
    MCPWMx->TCLK |= BIT6;
    MCPWMx->PRT = 0x0000; // mcpwm模块上锁
}
/**
 * @brief 数字模块时钟使能
 * @param nModule 模块编号
 * @param state 使能或禁用状态
 */
void SYS_ModuleClockCmd(uint32_t nModule, uint8_t state)
{
    REG_WRITE(SYS0->PROTECT, 0x7a83);
    if (state)
    {
        REG_SET(SYS0->CLK_FEN, nModule);
    }
    else
    {
        REG_RESET(SYS0->CLK_FEN, nModule);
    }
    REG_WRITE(SYS0->PROTECT, 0);
}
/**
 * @brief 模块使能
 * @param MCPWMx MCPWM模块
 */
void MCPWM_Enable(MCPWM_TypeDef *MCPWMx)
{
    SYS_ModuleClockCmd(SYS_MODULE_MCPWM0, ENABLE);
    MCPWMx->PRT = 0xdead;
    MCPWMx->TCLK |= BIT2;
    MCPWMx->PRT = 0;
}
/**
 * @brief 模块复位
 * @param MCPWMx MCPWM模块
 */
void MCPWM_Reset(MCPWM_TypeDef *MCPWMx)
{
    SYS_SoftResetModule(SYS_MODULE_MCPWM0);
}
/**
 * @brief 模块失能
 * @param MCPWMx MCPWM模块
 */
void MCPWM_Disable(MCPWM_TypeDef *MCPWMx)
{
    MCPWMx->PRT = 0xdead;
    MCPWMx->TCLK &= ~BIT2;
    MCPWMx->PRT = 0;
    SYS_ModuleClockCmd(SYS_MODULE_MCPWM0, DISABLE);
}
/**
 * @brief 设置IO配置
 * @param MCPWMx MCPWM模块
 * @param io0 IO0配置
 * @param io1 IO1配置
 * @param io2 IO2配置
 * @param io3 IO3配置
 * @note 由于mcpwm的io0和io1是一个寄存器，io2和io3是一个寄存器，所以需要同时配置
 */
void MCPWM_SetIOConfig(MCPWM_TypeDef *MCPWMx, uint16_t io0, uint16_t io1, uint16_t io2, uint16_t io3)
{
    MCPWMx->PRT  = 0xdead; // mcpwm模块解锁
    MCPWMx->IO01 = io0 | (io1 << 8);
    MCPWMx->IO23 = io2 | (io3 << 8);
    MCPWMx->PRT  = 0x0000; // mcpwm模块上锁
}
/**
 * @brief 设置MCPWM输出值
 * @param MCPWMx MCPWM模块
 * @param chn 通道号 0-3
 * @param p 上管打开时间
 * @param n 下管打开时间
 */
void MCPWM_SetOutputVal(MCPWM_TypeDef *MCPWMx, uint8_t chn, int16_t p, int16_t n)
{
    switch (chn)
    {
        case 0:
            MCPWMx->TH00 = p;
            MCPWMx->TH01 = n;
            break;
        case 1:
            MCPWMx->TH10 = p;
            MCPWMx->TH11 = n;
            break;
        case 2:
            MCPWMx->TH20 = p;
            MCPWMx->TH21 = n;
            break;
        case 3:
            MCPWMx->TH30 = p;
            MCPWMx->TH31 = n;
            break;
        default:
            break;
    }
}
/**
 * @brief 设置MCPWM输出状态
 * @param MCPWMx MCPWM模块
 * @param state 输出状态 1打开输出 0关闭输出
 */
void MCPWM_SetOutputState(MCPWM_TypeDef *MCPWMx, uint8_t state)
{
    MCPWMx->PRT = 0xdead; // mcpwm模块解锁
    if (state)
    {
        MCPWMx->EIF = MCPWMx->EIF;
        MCPWMx->CH_FAIL |= BIT6;
    }
    else
    {
        MCPWMx->CH_FAIL &= ~BIT6;
    }
    MCPWMx->PRT = 0x0000; // mcpwm模块上锁
}
/**
 * @brief 软复位模块
 * @param nModule 模块编号
 */
void SYS_SoftResetModule(uint32_t nModule)
{
    REG_WRITE(SYS0->PROTECT, 0x7a83);
    REG_SET(SYS0->SFT_RST, nModule);
    REG_RESET(SYS0->SFT_RST, nModule); // 触发复位后需清除复位位
    REG_WRITE(SYS0->PROTECT, 0);
}
/**
 * @brief 配置GPIO引脚复用功能
 * @param GPIOx GPIO模块指针
 * @param GPIO_PinSource 引脚源
 * @param GPIO_AF 复用功能选择
 */
void GPIO_PinAFConfig(GPIO_TypeDef *GPIOx, uint32_t GPIO_PinSource, uint32_t GPIO_AF)
{
    uint8_t offset;
    uint8_t pins = GPIO_PinSource >> 2;
    offset       = ((GPIO_PinSource & 0x3) * 4);
    switch (pins)
    {
        case 0:
            GPIOx->F3210 = (GPIOx->F3210 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 1:
            GPIOx->F7654 = (GPIOx->F7654 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 2:
            GPIOx->FBA98 = (GPIOx->FBA98 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 3:
            GPIOx->FFEDC = (GPIOx->FFEDC & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        default:
            break;
    }
}
```
