/*! * \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 }