Files
stair56e_uart/component/xc6xx_drivers/Drivers/test_case/PWM/pwm.c
T
2024-07-12 15:19:46 +08:00

469 lines
15 KiB
C

/*!
* \file pwm.c
*
* \brief Target pwm implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*------------------------------------------------------------------------------------
INCLUDE HEADE FILES
--------------------------------------------------------------------------------------*/
#include "pwm.h"
#include "xc6xxx_hal_pwm.h"
#include "xc6xxx_hal_adc.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief pwm_test_demo
* @details
* @param void
* @retval void
*/
void pwm_output_demo()
{
DEBUG("PWM_OUTPUT_DEMO\r");
// PWM0 and PWM1 can be mapped to other pins, PWM0 and PWM1 have inverted output.
// PWM(HZ) = PWMCLK(16000000)/(DutyCycleAcc*(period+1))/2
PWM_InitTypeDef PWM_InitStruct;
PWM_InitStruct.DutyCycleAcc = 256;
PWM_InitStruct.DutyCycle = 100;
PWM_InitStruct.Period = 0;
PWM_InitStruct.InvertDelay = 0x17;
PWM_InitStruct.InvertEnable = true;
PWM_InitStruct.OutputInvertPin = GPIO_2;
PWM_InitStruct.OutputPin = GPIO_3;
PWM_InitStruct.SrcClk = PWM_CLK_SRC_32M_DIV;
PWM_InitStruct.SrcEnable = PWM_EN_SEL_ALL;
PWM_Init(XC_PWM0, &PWM_InitStruct);
PWM_InitStruct.OutputInvertPin = GPIO_7;
PWM_InitStruct.OutputPin = GPIO_8;
PWM_Init(XC_PWM1, &PWM_InitStruct);
PWM_InitStruct.InvertEnable = false;
PWM_InitStruct.OutputPin = GPIO_0;
PWM_Init(XC_PWM2, &PWM_InitStruct);
PWM_InitStruct.OutputPin = GPIO_1;
PWM_Init(XC_PWM3, &PWM_InitStruct);
PWM_InitStruct.OutputPin = GPIO_12;
PWM_Init(XC_PWM4, &PWM_InitStruct);
PWM_InitStruct.OutputPin = GPIO_13;
PWM_Init(XC_PWM5, &PWM_InitStruct);
PWM_Start_All();
// Delay_Ms(1000);
//
// PWM_InitStruct.DutyCycleAcc = 7000;
// PWM_InitStruct.DutyCycle = 6000;
// PWM_DutyCycle_Set(XC_PWM0,PWM_InitStruct.DutyCycleAcc , PWM_InitStruct.DutyCycle);
//
// PWM_InitStruct.DutyCycleAcc = 7000;
// PWM_InitStruct.DutyCycle = 6000;
// PWM_DutyCycle_Set(XC_PWM1,PWM_InitStruct.DutyCycleAcc , PWM_InitStruct.DutyCycle);
//
// PWM_InitStruct.DutyCycleAcc = 7000;
// PWM_InitStruct.DutyCycle = 6000;
// PWM_DutyCycle_Set(XC_PWM2,PWM_InitStruct.DutyCycleAcc , PWM_InitStruct.DutyCycle);
// PWM_InitStruct.DutyCycleAcc = 7000;
// PWM_InitStruct.DutyCycle = 6000;
// PWM_DutyCycle_Set(XC_PWM3,PWM_InitStruct.DutyCycleAcc , PWM_InitStruct.DutyCycle);
//
// PWM_InitStruct.DutyCycleAcc = 7000;
// PWM_InitStruct.DutyCycle = 6000;
// PWM_DutyCycle_Set(XC_PWM4,PWM_InitStruct.DutyCycleAcc , PWM_InitStruct.DutyCycle);
//
// PWM_InitStruct.DutyCycleAcc = 7000;
// PWM_InitStruct.DutyCycle = 6000;
// PWM_DutyCycle_Set(XC_PWM5,PWM_InitStruct.DutyCycleAcc , PWM_InitStruct.DutyCycle);
}
void pwm_brake_demo()
{
DEBUG("PWM_BRAKE_DEMO\r");
// PWM0 and PWM1 can be mapped to other pins, PWM0 and PWM1 have inverted output.
// PWM(HZ) = PWMCLK(16000000)/(DutyCycleAcc*(period+1))/2
PWM_InitTypeDef PWM_InitStruct;
PWM_InitStruct.DutyCycleAcc = 60000;
PWM_InitStruct.DutyCycle = 30000;
PWM_InitStruct.Period = 99;
PWM_InitStruct.InvertDelay = 0;
PWM_InitStruct.InvertEnable = false;
PWM_InitStruct.OutputInvertPin = GPIO_2;
PWM_InitStruct.OutputPin = GPIO_1;
PWM_InitStruct.SrcClk = PWM_CLK_SRC_32M_DIV;
PWM_InitStruct.SrcEnable = PWM_EN_SEL_SELF;
PWM_Init(XC_PWM0, &PWM_InitStruct);
PWM_Start(XC_PWM0);
GPIO_FunSel(PWM_SIGNAL_BRK0_GPIO4,GPIO_Dx);
GPIO_MuxCtl(PWM_SIGNAL_BRK0_GPIO4,GPIO_Mux1);
GPIO_PullConfig(PWM_SIGNAL_BRK0_GPIO4,GPIO_PULLUP);
GPIO_FunSel(PWM_SIGNAL_BRK1_GPIO5,GPIO_Dx);
GPIO_MuxCtl(PWM_SIGNAL_BRK1_GPIO5,GPIO_Mux1);
GPIO_PullConfig(PWM_SIGNAL_BRK1_GPIO5,GPIO_PULLUP);
GPIO_FunSel(PWM_SIGNAL_BRK2_GPIO6,GPIO_Dx);
GPIO_MuxCtl(PWM_SIGNAL_BRK2_GPIO6,GPIO_Mux1);
XC_CPR->OPA_CTRL_REG &= ~(1<<12);
GPIO_PullConfig(PWM_SIGNAL_BRK2_GPIO6,GPIO_PULLUP);
PWM_Brake_Enable(XC_PWM0);
PWM_BrakeSignal_Mask_Config(XC_PWM0,PWM_BRK0_MASK_DISABLE | PWM_BRK1_MASK_DISABLE | PWM_BRK2_MASK_DISABLE);
PWM_BrakeSignal_Invert_Config(XC_PWM0,PWM_BRK0_LOW_LEVEL | PWM_BRK1_LOW_LEVEL | PWM_BRK2_LOW_LEVEL);
PWM_BrakeRecoveryMode_Config(XC_PWM0,PWM_BRK_MODE_HARDWARE);
PWM_BrakeDebounce_Config(XC_PWM0,PWM_BRK_DBC_EN_ENABLE,PWM_BRK_DBC_STEP2);
while(1)
{
if( XC_PWM0->PWM_BREAK_CTL & PWM_BRK_MODE_SOFTWARE )
{
if((XC_PWM0->PWM_BREAK_CTL & PWM_BRK_SYNC_INVALID) == 0)
{
XC_PWM0->PWM_BREAK_CTL |= 0x01;
}
}
}
}
void pwm_capture_demo()
{
DEBUG("PWM_CAPTURE_DEMO\r");
// PWM0 and PWM1 can be mapped to other pins, PWM0 and PWM1 have inverted output.
// DutyCycleAccLevel 为2时,为中心对齐模式
// PWM(HZ) = PWMCLK(16000000)/(DutyCycleAcc*(period+1))/2
PWM_InitTypeDef PWM_InitStruct;
PWM_InitStruct.DutyCycleAcc = 60000;
PWM_InitStruct.DutyCycle = 30000;
PWM_InitStruct.Period = 99;
PWM_InitStruct.InvertDelay = 0;
PWM_InitStruct.InvertEnable = false;
PWM_InitStruct.OutputInvertPin = GPIO_2;
PWM_InitStruct.OutputPin = GPIO_1;
PWM_InitStruct.SrcClk = PWM_CLK_SRC_32M_DIV;
PWM_InitStruct.SrcEnable = PWM_EN_SEL_SELF;
PWM_Init(XC_PWM0, &PWM_InitStruct);
PWM_Start(XC_PWM0);
GPIO_FunSel(PWM_SIGNAL_BRK0_GPIO4,GPIO_Dx);
GPIO_MuxCtl(PWM_SIGNAL_BRK0_GPIO4,GPIO_Mux1);
GPIO_PullConfig(PWM_SIGNAL_BRK0_GPIO4,GPIO_PULLDOWN);
GPIO_FunSel(PWM_SIGNAL_CAPTURE0_GPIO3,GPIO_Dx);
GPIO_MuxCtl(PWM_SIGNAL_CAPTURE0_GPIO3,GPIO_Mux1);
GPIO_FunSel(PWM_SIGNAL_CAPTURE1_GPIO8,GPIO_Dx);
GPIO_MuxCtl(PWM_SIGNAL_CAPTURE1_GPIO8,GPIO_Mux1);
GPIO_FunSel(PWM_SIGNAL_CAPTURE2_GPIO9,GPIO_Dx);
GPIO_MuxCtl(PWM_SIGNAL_CAPTURE2_GPIO9,GPIO_Mux1);
PWM_CaptureCounter_Enable(PWM_IC_CH0);
PWM_CapturePsc_Config(PWM_IC_CH0, PWM_CAPTURE_PSC_1);
PWM_CaptureEdge_Config(PWM_IC_CH0,PWM_CAPTURE_MODE_RISE);
PWM_CaptureDebounce_Enable(PWM_IC_CH0,PWM_CAPTURE_DBC_STEP1);
PWM_Capture_Signal_Config(PWM_IC_CH0,PWM_ICSIG_CAPTURE0);
PWM_Capture_Enable_IT(PWM_IC_CH0);
PWM_Capture_Enable(PWM_IC_CH0);
PWM_CaptureCounter_Enable(PWM_IC_CH1);
PWM_CapturePsc_Config(PWM_IC_CH1, PWM_CAPTURE_PSC_1);
PWM_CaptureEdge_Config(PWM_IC_CH1,PWM_CAPTURE_MODE_RISE);
PWM_CaptureDebounce_Enable(PWM_IC_CH1,PWM_CAPTURE_DBC_STEP1);
PWM_Capture_Signal_Config(PWM_IC_CH1,PWM_ICSIG_CAPTURE1);
PWM_Capture_Enable_IT(PWM_IC_CH1);
PWM_Capture_Enable(PWM_IC_CH1);
PWM_CaptureCounter_Enable(PWM_IC_CH2);
PWM_CapturePsc_Config(PWM_IC_CH2, PWM_CAPTURE_PSC_1);
PWM_CaptureEdge_Config(PWM_IC_CH2,PWM_CAPTURE_MODE_RISE);
PWM_CaptureDebounce_Enable(PWM_IC_CH2,PWM_CAPTURE_DBC_STEP1);
PWM_Capture_Signal_Config(PWM_IC_CH2,PWM_ICSIG_CAPTURE2);
PWM_Capture_Enable_IT(PWM_IC_CH2);
PWM_Capture_Enable(PWM_IC_CH2);
NVIC_EnableIRQ(PWM_IRQn);
}
void pwm_enable_adc_demo(void)
{
DEBUG("PWM_ENABLE_ADC_DEMO\r");
adc_cfg adc_cfg ;
uint16_t adc_val,integer,decimal;
// pwm 使能后触发 adc中断
// PWM0 and PWM1 can be mapped to other pins, PWM0 and PWM1 have inverted output.
// DutyCycleAccLevel 为2时,为中心对齐模式
// PWM(HZ) = PWMCLK(16000000)/(DutyCycleAcc*(period+1))/2
PWM_InitTypeDef PWM_InitStruct;
PWM_InitStruct.DutyCycleAcc = 60000;
PWM_InitStruct.DutyCycle = 30000;
PWM_InitStruct.Period = 99;
PWM_InitStruct.InvertDelay = 0;
PWM_InitStruct.InvertEnable = false;
PWM_InitStruct.OutputInvertPin = GPIO_2;
PWM_InitStruct.OutputPin = GPIO_1;
PWM_InitStruct.SrcClk = PWM_CLK_SRC_32M_DIV;
PWM_InitStruct.SrcEnable = PWM_EN_SEL_SELF;
PWM_Init(XC_PWM0, &PWM_InitStruct);
PWM_Start(XC_PWM0);
adc_cfg.Freq = ADC_FREQ_1M;
adc_cfg.RefVol = ADC_REF_VOL_3_3V;
adc_cfg.SampEdge = ADC_SAMPEDGE_FALL;
adc_cfg.ExtDataMode = ADC_DATA_MODE_32BIT;
adc_cfg.ExtEdgeSel = ADC_EXT_EDGE_SEL_EXTERN_RISE;
adc_cfg.ExtSampleNum = ADC_SAMPLE_NUM_8;
adc_cfg.ExtTriggerSel = ADC_TRIGGER_SEL_PWM0;
ADC_Init(XC_ADC, &adc_cfg);
__ADC_ChannelSet(XC_ADC, ADC_CHANNEL7_PIN5);
__ADC_FIFO_ReqIntLenthSet(XC_ADC);
__ADC_FIFO_Flush(XC_ADC);
__ADC_Clear_IT_Flag(XC_ADC);
ADC_Enable_IT(XC_ADC, ADC_INT_EN_READ_REQ_EN_ENABLE | ADC_INT_EN_FIFO_ERROR_EN_ENABLE);
__ADC_Enable(XC_ADC);
NVIC_EnableIRQ(GADC_IRQn);
while(1)
{
adc_val = ADC_IT_CollectVal_Get();
if(adc_cfg.RefVol == ADC_REF_VOL_3_3V)
{
integer = ((adc_val)*3.3*100)/(1.0*4096)/100;
decimal = ((uint32_t)((adc_val*3.3*100)/4096)%100);
DEBUG("3.3v ref adc_vol=%d.%d ,adc_val=%d\n", integer, decimal,adc_val);
}
else if(adc_cfg.RefVol == ADC_REFVOL_2_33V)
{
integer = ((adc_val)*2.33*100)/(1.0*4096)/100;
decimal = ((uint32_t)((adc_val*2.33*100)/4096)%100);
DEBUG("2.33v ref adc_vol=%d.%d ,adc_val=%d\n", integer, decimal,adc_val);
}
Delay_Ms(1000);
}
}
void pwm_lowpower_demo(void)
{
DEBUG("PWM_LOWPOWER_DEMO\r");
// PWM0 and PWM1 can be mapped to other pins, PWM0 and PWM1 have inverted output.
// DutyCycleAccLevel 为2时,为中心对齐模式
// PWM(HZ) = PWMCLK(16000000)/(DutyCycleAcc*(period+1))/2
PWM_InitTypeDef PWM_InitStruct;
PWM_InitStruct.DutyCycleAcc = 10000;
PWM_InitStruct.DutyCycle = 5000;
PWM_InitStruct.Period = 99;
PWM_InitStruct.InvertDelay = 0;
PWM_InitStruct.InvertEnable = false;
PWM_InitStruct.OutputInvertPin = GPIO_2;
PWM_InitStruct.OutputPin = GPIO_1;
PWM_InitStruct.SrcClk = PWM_CLK_SRC_32M_DIV;
PWM_InitStruct.SrcEnable = PWM_EN_SEL_SELF;
PWM_Init(XC_PWM0, &PWM_InitStruct);
PWM_Start(XC_PWM0);
PWM_LowPower_Enable(XC_PWM0);
PWM_LowPower_CountDirection_Set(XC_PWM0,PWM_SLEEP_COUNT_DIRECTION_UP);
PWR_InitTypeDef PWR_InitStruct = {0};
PWR_InitStruct.PWR_WakeITSrc = GPIO_IRQn_WAKE | RTC_IRQn_WAKE ;
PWR_InitStruct.PWR_SleepMode = LIGHT_SLEEP_MODE;//LIGHT_SLEEP_MODE;//DEEP_SLEEP_MODE;
FMC_SPI_Init( );
PWR_GPIO_SleepConfig(PWR_InitStruct.PWR_SleepMode);
if(PWR_InitStruct.PWR_SleepMode == LIGHT_SLEEP_MODE)
{
PWR_GPIO_LightSleepWakeConfig(GPIO_4, RIS_EDGE_INT);
PWR_GPIO_LightSleepWakeConfig(GPIO_5, FAIL_EDGE_INT);
}
else if(PWR_InitStruct.PWR_SleepMode == DEEP_SLEEP_MODE)
{
// PWRKEY Initialization is required after deep sleep wakeup
PWR_PWRKEY_Init();
PWR_PWRKEY_DeepSleepWakeConfig(GPIO_4, DEEP_SLEEP_GPIO_WAKE_HIGH_LEVEL);
PWR_PWRKEY_DeepSleepWakeConfig(GPIO_5, DEEP_SLEEP_GPIO_WAKE_LOW_LEVEL);
}
PWR_SleepInit(&PWR_InitStruct);
while(1)
{
// DEBUG("opa %x\n", *((volatile unsigned *)(0x40000000 + 0x1bc)) ); //OPA
// DEBUG("CMP %x\n", *((volatile unsigned *)(0x40000000 + 0x260)) ); //CMP
Delay_Ms(100);
PWR_CPU_SleepEnter( );
DEBUG("wakeup\n");
}
}
uint8_t CaptureCh0_Callback(void)
{
PWM_CaptureVal_Get(PWM_IC_CH0);
return 0;
}
uint8_t CaptureCh1_Callback(void)
{
PWM_CaptureVal_Get(PWM_IC_CH1);
return 0;
}
uint8_t CaptureCh2_Callback(void)
{
PWM_CaptureVal_Get(PWM_IC_CH2);
return 0;
}
/*
*-----------------------------------------------------------------------------------------------
* PWM Timer
*-----------------------------------------------------------------------------------------------
*/
void pwm_timer_demo(void)
{
DEBUG("PWM_TIMER_DEMO\r");
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Mux = GPIO_Mux1;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Int = NOT_INT;
GPIO_InitStruct.FunSel = GPIO_Dx;
GPIO_InitStruct.Dir = GPIO_DIR_OUTPUT;
GPIO_InitStruct.Pin = GPIO_29;
GPIO_Init( &GPIO_InitStruct );
GPIO_InitStruct.Pin = GPIO_30;
GPIO_Init( &GPIO_InitStruct );
// GPIO_InitStruct.Pin = GPIO_35;
// GPIO_Init( &GPIO_InitStruct );
GPIO_MuxCtl(GPIO_35, GPIO_Mux1);
GPIO_MuxCtl(GPIO_36, GPIO_Mux1);
GPIO_MuxCtl(GPIO_37, GPIO_Mux1);
GPIO_MuxCtl(GPIO_38, GPIO_Mux1);
PWM_Timer_Ctl_Cfg T_Ctrl_Cfg;
T_Ctrl_Cfg.Src_Clk = PWM_CLK_SRC_32M_DIV;
T_Ctrl_Cfg.Clk_Div = PWM_CLK_DIV0;
T_Ctrl_Cfg.Timer_Num = PWM_ALL_TIMER; //PWM_TIMER_1 | PWM_TIMER_2 | PWM_TIMER_3;
T_Ctrl_Cfg.Timer_Mode = 0x01;
T_Ctrl_Cfg.Timer_Int_Mask_En = DISABLE;
T_Ctrl_Cfg.Timer_PWM_En = ENABLE;
T_Ctrl_Cfg.Timer_0N100_PWM_En = ENABLE;
PWM_Timer_Init(XC_PWM_TIMER, &T_Ctrl_Cfg);
PWM_Timer_Load_Cnt T_Load;
T_Load.Timer_Num = PWM_ALL_TIMER; //PWM_TIMER_1 | PWM_TIMER_2 | PWM_TIMER_3;
T_Load.Load_Cnt = 0x2ff;
T_Load.Load_Cnt2 = 0xd00;
PWM_Timer_SetLoad_Cnt(XC_PWM_TIMER, &T_Load);
PWM_Timer_Start(XC_PWM_TIMER, T_Load.Timer_Num);
}
#define PWM_TIMER_DEMO 1
#define PWM_OUTPUT_DEMO 0
#define PWM_CAPTURE_DEMO 0
#define PWM_BRAKE_DEMO 0
#define PWM_ENABLE_ADC_DEMO 0
#define PWM_LOWPOWER_DEMO 0
void pwm_demo()
{
#if PWM_TIMER_DEMO
pwm_timer_demo();
#endif
#if PWM_OUTPUT_DEMO
pwm_output_demo();
#endif
#if PWM_CAPTURE_DEMO
pwm_capture_demo();
#endif
#if PWM_BRAKE_DEMO
pwm_brake_demo();
#endif
#if PWM_ENABLE_ADC_DEMO
pwm_enable_adc_demo();
#endif
#if PWM_LOWPOWER_DEMO
pwm_lowpower_demo();
#endif
}