307 lines
9.1 KiB
C
307 lines
9.1 KiB
C
|
/*
|
|||
|
******************************************************************************
|
|||
|
* @file driver_pwm.c
|
|||
|
* @author FreqChip Firmware Team
|
|||
|
* @version V1.0.0
|
|||
|
* @date 2021
|
|||
|
* @brief SPI module driver.
|
|||
|
* This file provides firmware functions to manage the
|
|||
|
* Pulse-Width Modulatio (PWM) peripheral
|
|||
|
******************************************************************************
|
|||
|
* @attention
|
|||
|
*
|
|||
|
* Copyright (c) 2021 FreqChip.
|
|||
|
* All rights reserved.
|
|||
|
******************************************************************************
|
|||
|
*/
|
|||
|
#include "fr30xx.h"
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_config
|
|||
|
*
|
|||
|
* @brief PWM mode. Config channel paramter.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fu16_channel: Select output channel.(1bit ~ 1channel)
|
|||
|
* fstr_Config: Config paramter.
|
|||
|
*/
|
|||
|
void pwm_config(struct_PWM_t *PWMx, uint16_t fu16_channel, struct_PWM_Config_t fstr_Config)
|
|||
|
{
|
|||
|
uint32_t lu32_Position = 0;
|
|||
|
uint32_t lu32_Current_Channel;
|
|||
|
|
|||
|
PWMx->OutputSelect &= ~fu16_channel;
|
|||
|
|
|||
|
/* Configure Select channel */
|
|||
|
while (fu16_channel >> lu32_Position != 0)
|
|||
|
{
|
|||
|
/* Get current pin position */
|
|||
|
lu32_Current_Channel = fu16_channel & (1uL << lu32_Position);
|
|||
|
|
|||
|
if (lu32_Current_Channel)
|
|||
|
{
|
|||
|
/* stop sync update */
|
|||
|
PWMx->Update.PWM_Update &= ~lu32_Current_Channel;
|
|||
|
|
|||
|
PWMx->Edge[lu32_Position].Posedge = fstr_Config.Posedge;
|
|||
|
PWMx->Edge[lu32_Position].Negedeg = fstr_Config.Negedge;
|
|||
|
|
|||
|
PWMx->Frequency[lu32_Position].Prescale = fstr_Config.Prescale - 1;
|
|||
|
PWMx->Frequency[lu32_Position].Period = fstr_Config.Period - 1;
|
|||
|
}
|
|||
|
|
|||
|
lu32_Position++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_complementary_config
|
|||
|
*
|
|||
|
* @brief Complementary outputs with dead-time insertion
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fu16_MainChannel: Select main output channel.(1bit ~ 1channel)
|
|||
|
* @param ComplementaryChannel: Select complementary output channel.(1bit ~ 1channel)
|
|||
|
* fstr_Config: Config paramter.
|
|||
|
*/
|
|||
|
bool pwm_complementary_config(struct_PWM_t *PWMx, uint16_t fu16_MainChannel, uint16_t ComplementaryChannel, struct_PWM_Complementary_Config_t fstr_Config)
|
|||
|
{
|
|||
|
struct_PWM_Config_t PWM_Config;
|
|||
|
|
|||
|
PWM_Config.Prescale = fstr_Config.Prescale;
|
|||
|
PWM_Config.Period = fstr_Config.Period;
|
|||
|
|
|||
|
if (fstr_Config.MianDeadTime != 0)
|
|||
|
{
|
|||
|
if (fstr_Config.MianDeadTime - 1 >= PWM_Config.Period - 1 - fstr_Config.DutyCycle - fstr_Config.MianDeadTime)
|
|||
|
return false;
|
|||
|
|
|||
|
PWM_Config.Posedge = fstr_Config.MianDeadTime - 1;
|
|||
|
PWM_Config.Negedge = PWM_Config.Period - 1 - fstr_Config.DutyCycle - fstr_Config.MianDeadTime;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* Error check */
|
|||
|
if (fstr_Config.DutyCycle >= PWM_Config.Period)
|
|||
|
return false;
|
|||
|
if (fstr_Config.DutyCycle == 0)
|
|||
|
return false;
|
|||
|
|
|||
|
PWM_Config.Posedge = PWM_Config.Period - 1;
|
|||
|
PWM_Config.Negedge = PWM_Config.Period - 1 - fstr_Config.DutyCycle;
|
|||
|
}
|
|||
|
|
|||
|
pwm_config(PWMx, fu16_MainChannel, PWM_Config);
|
|||
|
|
|||
|
if (fstr_Config.CompDeadTime != 0)
|
|||
|
{
|
|||
|
if (PWM_Config.Period - 1 - fstr_Config.DutyCycle + fstr_Config.MianDeadTime >= PWM_Config.Period - 1 - fstr_Config.CompDeadTime)
|
|||
|
return false;
|
|||
|
|
|||
|
PWM_Config.Posedge = PWM_Config.Period - 1 - fstr_Config.DutyCycle + fstr_Config.MianDeadTime;
|
|||
|
PWM_Config.Negedge = PWM_Config.Period - 1 - fstr_Config.CompDeadTime;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* Error check */
|
|||
|
if (fstr_Config.DutyCycle >= PWM_Config.Period)
|
|||
|
return false;
|
|||
|
if (fstr_Config.DutyCycle == 0)
|
|||
|
return false;
|
|||
|
|
|||
|
PWM_Config.Posedge = PWM_Config.Period - 1 - fstr_Config.DutyCycle;
|
|||
|
PWM_Config.Negedge = PWM_Config.Period - 1;
|
|||
|
}
|
|||
|
|
|||
|
pwm_config(PWMx, ComplementaryChannel, PWM_Config);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_output_enable
|
|||
|
*
|
|||
|
* @brief PWM_DAC mode. output enable.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fu16_channel: Select output channel.(1bit ~ 1channel)
|
|||
|
*/
|
|||
|
void pwm_output_enable(struct_PWM_t *PWMx, uint16_t fu16_channel)
|
|||
|
{
|
|||
|
PWMx->Update.PWM_Update |= fu16_channel;
|
|||
|
|
|||
|
PWMx->CNT_EN |= fu16_channel;
|
|||
|
PWMx->ChannelEN |= fu16_channel;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_output_disable
|
|||
|
*
|
|||
|
* @brief PWM_DAC mode. output disable.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fu8_channel: Select output channel.(1bit ~ 1channel)
|
|||
|
*/
|
|||
|
void pwm_output_disable(struct_PWM_t *PWMx, uint16_t fu16_channel)
|
|||
|
{
|
|||
|
/* stop sync update */
|
|||
|
PWMx->Update.PWM_Update &= ~fu16_channel;
|
|||
|
|
|||
|
PWMx->ChannelEN &= ~fu16_channel;
|
|||
|
PWMx->CNT_EN &= ~fu16_channel;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_output_status
|
|||
|
*
|
|||
|
* @brief PWM_DAC mode. output inverter disable.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fe_channel: Select output channel.(1bit ~ 1channel)
|
|||
|
*
|
|||
|
* @return true : PWM runing.
|
|||
|
* false: PWM stop.
|
|||
|
*/
|
|||
|
bool pwm_output_status(struct_PWM_t *PWMx, enum_PWMChannel_t fe_channel)
|
|||
|
{
|
|||
|
if (PWMx->Update.PWM_Status & fe_channel)
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_output_updata
|
|||
|
*
|
|||
|
* @brief channel Posedge/Negedeg/Prescale/Period updata
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fu16_channel: Select output channel.(1bit ~ 1channel)
|
|||
|
*/
|
|||
|
void pwm_output_updata(struct_PWM_t *PWMx, uint16_t fu16_channel)
|
|||
|
{
|
|||
|
/* start sync update */
|
|||
|
PWMx->Update.PWM_Update |= fu16_channel;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_capture_config
|
|||
|
*
|
|||
|
* @brief Capture mode. Config channel paramter.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fu16_channel: Select capture channel(1bit ~ 1channel).
|
|||
|
* fstr_Config: Config paramter.
|
|||
|
*/
|
|||
|
void pwm_capture_config(struct_PWM_t *PWMx, uint16_t fu16_channel, struct_Capture_Config_t fstr_Config)
|
|||
|
{
|
|||
|
uint32_t lu32_Position = 0;
|
|||
|
uint32_t lu32_Current_Channel;
|
|||
|
|
|||
|
/* Set Capture Prescale */
|
|||
|
PWMx->CapturePrescale = 0x10 | fstr_Config.CapturePrescale;
|
|||
|
|
|||
|
/* Configure Select channel */
|
|||
|
while (fu16_channel >> lu32_Position != 0)
|
|||
|
{
|
|||
|
/* Get current pin position */
|
|||
|
lu32_Current_Channel = fu16_channel & (1uL << lu32_Position);
|
|||
|
|
|||
|
if (lu32_Current_Channel)
|
|||
|
{
|
|||
|
/* Set Capture mode */
|
|||
|
if (fstr_Config.CaptureMode == MODE_LOOP)
|
|||
|
{
|
|||
|
PWMx->CaptureCtrl.Capture_Mode &= ~lu32_Current_Channel;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
PWMx->CaptureCtrl.Capture_Mode |= lu32_Current_Channel;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
lu32_Position++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_capture_enable
|
|||
|
*
|
|||
|
* @brief capture enable.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fu16_channel: Select capture channel.(1bit ~ 1channel)
|
|||
|
*/
|
|||
|
void pwm_capture_enable(struct_PWM_t *PWMx, uint16_t fu16_channel)
|
|||
|
{
|
|||
|
PWMx->CaptureCtrl.Capture_EN |= fu16_channel;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_capture_disable
|
|||
|
*
|
|||
|
* @brief pwm_capture_disable.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fu16_channel: Select capture channel.(1bit ~ 1channel)
|
|||
|
*/
|
|||
|
void pwm_capture_disable(struct_PWM_t *PWMx, uint16_t fu16_channel)
|
|||
|
{
|
|||
|
PWMx->CaptureCtrl.Capture_EN &= ~fu16_channel;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_capture_status
|
|||
|
*
|
|||
|
* @brief get pwm_capture_status.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fe_channel: Select capture channel.(1bit ~ 1channel)
|
|||
|
* @return true : capture result value ready.
|
|||
|
* false: capture result value not ready.
|
|||
|
*/
|
|||
|
bool pwm_capture_status(struct_PWM_t *PWMx, enum_PWMChannel_t fe_channel)
|
|||
|
{
|
|||
|
return (PWMx->CaptureStatus & fe_channel) ? true : false;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_capture_status_clear
|
|||
|
*
|
|||
|
* @brief capture status claear.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fe_channel: Select capture channel.(1bit ~ 1channel)
|
|||
|
*/
|
|||
|
void pwm_capture_status_clear(struct_PWM_t *PWMx,enum_PWMChannel_t fe_channel)
|
|||
|
{
|
|||
|
PWMx->CaptureStatus |= fe_channel;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************
|
|||
|
* @fn pwm_capture_value
|
|||
|
*
|
|||
|
* @brief get pwm_capture_value.
|
|||
|
*
|
|||
|
* @param PWMx: PWM0<EFBFBD><EFBFBD>PWM1.
|
|||
|
* fe_channel: Select capture channel.(1bit ~ 1channel)
|
|||
|
*/
|
|||
|
uint32_t pwm_capture_value(struct_PWM_t *PWMx, enum_PWMChannel_t fe_channel)
|
|||
|
{
|
|||
|
uint8_t i;
|
|||
|
|
|||
|
for (i = 0; i < 16; i++)
|
|||
|
{
|
|||
|
if (fe_channel & 1 << i)
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return PWMx->CaptureValue[i];
|
|||
|
}
|
|||
|
|