828eco基于GD32H7mcu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

660 lines
20 KiB

5 months ago
/*!
\file gd32h75e_cmp.c
\brief CMP driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_cmp.h"
/*!
\brief CMP deinit
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_deinit(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS &= ((uint32_t)0x00000000U);
CMP_IFC &= ((uint32_t)0xFFFEFFFFU);
CMP_STAT &= ((uint32_t)0xFFFEFFFEU);
CMP_SR &= ((uint32_t)0x00000000U);
}else if(CMP1 == cmp_periph){
CMP1_CS &= ((uint32_t)0x00000000U);
CMP_IFC &= ((uint32_t)0xFFFDFFFFU);
CMP_STAT &= ((uint32_t)0xFFFDFFFDU);
CMP_SR &= ((uint32_t)0x00000000U);
}else{
}
}
/*!
\brief CMP mode init
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] operating_mode
\arg CMP_MODE_HIGHSPEED: high speed mode
\arg CMP_MODE_MIDDLESPEED: medium speed mode
\arg CMP_MODE_VERYLOWSPEED: very-low speed mode
\param[in] inverting_input
\arg CMP_INVERTING_INPUT_1_4VREFINT: VREFINT *1/4 input
\arg CMP_INVERTING_INPUT_1_2VREFINT: VREFINT *1/2 input
\arg CMP_INVERTING_INPUT_3_4VREFINT: VREFINT *3/4 input
\arg CMP_INVERTING_INPUT_VREFINT: VREFINT input
\arg CMP_INVERTING_INPUT_DAC0_OUT0: CMP inverting input DAC0_OUT0
\arg CMP_INVERTING_INPUT_DAC0_OUT1: CMP inverting input DAC0_OUT1
\arg CMP_INVERTING_INPUT_PB1_PE10: PB1 for CMP0 or PE10 for CMP1 as inverting input
\arg CMP_INVERTING_INPUT_PC4_PE7: PC4 for CMP0 or PE7 for CMP1 as inverting input
\param[in] hysteresis
\arg CMP_HYSTERESIS_NO: output no hysteresis
\arg CMP_HYSTERESIS_LOW: output low hysteresis
\arg CMP_HYSTERESIS_MIDDLE: output middle hysteresis
\arg CMP_HYSTERESIS_HIGH: output high hysteresis
\param[out] none
\retval none
*/
void cmp_mode_init(cmp_enum cmp_periph, uint32_t operating_mode, uint32_t inverting_input, uint32_t output_hysteresis)
{
uint32_t temp = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_OPERATING_MODE(operating_mode)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
}else if(NOT_CMP_INVERTING_INPUT(inverting_input)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
}else if(NOT_CMP_OUTPUT_HYSTERESIS(output_hysteresis)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
/* initialize comparator 0 mode */
temp = CMP0_CS;
temp &= ~(uint32_t)(CMP_CS_CMPXM | CMP_CS_CMPXMISEL | CMP_CS_CMPXHST);
temp |= (uint32_t)(operating_mode | inverting_input | output_hysteresis);
CMP0_CS = temp;
}else if(CMP1 == cmp_periph){
/* initialize comparator 1 mode */
temp = CMP1_CS;
temp &= ~(uint32_t)(CMP_CS_CMPXM | CMP_CS_CMPXMISEL | CMP_CS_CMPXHST);
temp |= (uint32_t)(operating_mode | inverting_input | output_hysteresis);
CMP1_CS = temp;
}else{
}
}
}
/*!
\brief CMP noninverting input select
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] noninverting_input
\arg CMP_NONINVERTING_INPUT_PB0_PE9: CMP noninverting input PB0 for CMP0 or PE9 for CMP1
\arg CMP_NONINVERTING_INPUT_PB2_PE11: CMP noninverting input PB2 for CMP0 or PE12 for CMP1
\param[out] none
\retval none
*/
void cmp_noninverting_input_select(cmp_enum cmp_periph, uint32_t noninverting_input)
{
uint32_t temp = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_NONINVERTING_INPUT(noninverting_input)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
temp = CMP0_CS;
temp &= ~(uint32_t)CMP_CS_CMPXPSEL;
temp |= (uint32_t)noninverting_input;
CMP0_CS = temp;
}else if(CMP1 == cmp_periph){
temp = CMP1_CS;
temp &= ~(uint32_t)CMP_CS_CMPXPSEL;
temp |= (uint32_t)noninverting_input;
CMP1_CS = temp;
}else{
}
}
}
/*!
\brief CMP output init
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] output_polarity
\arg CMP_OUTPUT_POLARITY_INVERTED: output is inverted
\arg CMP_OUTPUT_POLARITY_NONINVERTED: output is not inverted
\param[out] none
\retval none
*/
void cmp_output_init(cmp_enum cmp_periph, uint32_t output_polarity)
{
uint32_t temp = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_OUTPUT_POLARITY(output_polarity)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
/* initialize comparator 0 output */
temp = CMP0_CS;
/* output polarity */
if(CMP_OUTPUT_POLARITY_INVERTED == output_polarity){
temp |= (uint32_t)CMP_CS_CMPXPL;
}else{
temp &= ~(uint32_t)CMP_CS_CMPXPL;
}
CMP0_CS = temp;
}else if(CMP1 == cmp_periph){
/* initialize comparator 1 output */
temp = CMP1_CS;
/* output polarity */
if(CMP_OUTPUT_POLARITY_INVERTED == output_polarity){
temp |= (uint32_t)CMP_CS_CMPXPL;
}else{
temp &= ~(uint32_t)CMP_CS_CMPXPL;
}
CMP1_CS = temp;
}else{
}
}
}
/*!
\brief config comparator output port
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] cmp_output_sel
\arg CMP_AFSE_GPIO_PA6: CMP alternate GPIO PA6
\arg CMP_AFSE_GPIO_PA8: CMP alternate GPIO PA8
\arg CMP_AFSE_GPIO_PB12: CMP alternate GPIO PB12
\arg CMP_AFSE_GPIO_PE6: CMP alternate GPIO PE6
\arg CMP_AFSE_GPIO_PE15: CMP alternate GPIO PE15
\arg CMP_AFSE_GPIO_PG2: CMP alternate GPIO PG2
\arg CMP_AFSE_GPIO_PG3: CMP alternate GPIO PG3
\arg CMP_AFSE_GPIO_PG4: CMP alternate GPIO PG4
\arg CMP_AFSE_GPIO_PK0: CMP alternate GPIO PK0
\arg CMP_AFSE_GPIO_PK1: CMP alternate GPIO PK1
\arg CMP_AFSE_GPIO_PK2: CMP alternate GPIO PK2
\param[out] none
\retval none
*/
void cmp_output_mux_config(cmp_enum cmp_periph, uint32_t cmp_output_sel)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_AFSE_GPIO_PIN(cmp_output_sel)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0005U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
CMP_SR &= ~(uint32_t)cmp_output_sel;
}else if(CMP1 == cmp_periph){
CMP_SR |= cmp_output_sel;
}else{
}
}
}
/*!
\brief CMP output blanking function init
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] blanking_source_selection
\arg CMP_BLANKING_NONE: CMP no blanking source
\arg CMP_BLANKING_TIMER0_OC0: CMP TIMER0_CH0 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER1_OC2: CMP TIMER1_CH2 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER2_OC2: CMP TIMER2_CH2 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER2_OC3: CMP TIMER2_CH3 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER7_OC0: CMP TIMER7_CH0 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER14_OC0: CMP TIMER14_CH0 output compare signal selected as blanking source
\param[out] none
\retval none
*/
void cmp_blanking_init(cmp_enum cmp_periph, uint32_t blanking_source_selection)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_BLK_SOURCE_SEL(blanking_source_selection)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp = 0U;
if(CMP0 == cmp_periph){
temp = CMP0_CS;
temp &= ~(uint32_t)CMP_CS_CMPXBLK;
temp |= (uint32_t)blanking_source_selection;
CMP0_CS = temp;
}else if(CMP1 == cmp_periph){
temp = CMP1_CS;
temp &= ~(uint32_t)CMP_CS_CMPXBLK;
temp |= (uint32_t)blanking_source_selection;
CMP1_CS = temp;
}else{
}
}
}
/*!
\brief enable CMP
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_enable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS |= (uint32_t)CMP_CS_CMPXEN;
}else if(CMP1 == cmp_periph){
CMP1_CS |= (uint32_t)CMP_CS_CMPXEN;
}else{
}
}
/*!
\brief disable CMP
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_disable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS &= ~(uint32_t)CMP_CS_CMPXEN;
}else if(CMP1 == cmp_periph){
CMP1_CS &= ~(uint32_t)CMP_CS_CMPXEN;
}else{
}
}
/*!
\brief enable the window mode
\param[in] none
\param[out] none
\retval none
*/
void cmp_window_enable(void)
{
CMP1_CS |= (uint32_t)CMP_CS_WNDEN;
}
/*!
\brief disable the window mode
\param[in] none
\param[out] none
\retval none
*/
void cmp_window_disable(void)
{
CMP1_CS &= ~(uint32_t)CMP_CS_WNDEN;
}
/*!
\brief lock the comparator
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_lock_enable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
/* lock CMP0 */
CMP0_CS |= (uint32_t)CMP_CS_CMPXLK;
}else if(CMP1 == cmp_periph){
/* lock CMP1 */
CMP1_CS |= (uint32_t)CMP_CS_CMPXLK;
}else{
}
}
/*!
\brief enable the voltage scaler
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_voltage_scaler_enable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS |= (uint32_t)CMP_CS_CMPXSEN;
}else if(CMP1 == cmp_periph){
CMP1_CS |= (uint32_t)CMP_CS_CMPXSEN;
}else{
}
}
/*!
\brief disable the voltage scaler
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_voltage_scaler_disable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS &= ~(uint32_t)CMP_CS_CMPXSEN;
}else if(CMP1 == cmp_periph){
CMP1_CS &= ~(uint32_t)CMP_CS_CMPXSEN;
}else{
}
}
/*!
\brief enable the scaler bridge
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_scaler_bridge_enable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS |= (uint32_t)CMP_CS_CMPXBEN;
}else if(CMP1 == cmp_periph){
CMP1_CS |= (uint32_t)CMP_CS_CMPXBEN;
}else{
}
}
/*!
\brief disable the scaler bridge
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_scaler_bridge_disable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS &= ~(uint32_t)CMP_CS_CMPXBEN;
}else if(CMP1 == cmp_periph){
CMP1_CS &= ~(uint32_t)CMP_CS_CMPXBEN;
}else{
}
}
/*!
\brief get output level
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval the output level
*/
uint32_t cmp_output_level_get(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
/* get output level of CMP0 */
if((uint32_t)RESET != (CMP_STAT & CMP_STAT_CMP0O)) {
return CMP_OUTPUTLEVEL_HIGH;
}else{
return CMP_OUTPUTLEVEL_LOW;
}
}else{
/* get output level of CMP1 */
if((uint32_t)RESET != (CMP_STAT & CMP_STAT_CMP1O)) {
return CMP_OUTPUTLEVEL_HIGH;
}else{
return CMP_OUTPUTLEVEL_LOW;
}
}
}
/*!
\brief get CMP flag
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] flag: CMP flags
\arg CMP_FLAG_COMPARE: CMP compare flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus cmp_flag_get(cmp_enum cmp_periph, uint32_t flag)
{
FlagStatus reval = RESET;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0011U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
if(CMP_FLAG_COMPARE == flag){
if(0U != (CMP_STAT & CMP_STAT_CMP0IF)){
reval = SET;
}
}
}else if(CMP1 == cmp_periph){
if(CMP_FLAG_COMPARE == flag){
if(0U != (CMP_STAT & CMP_STAT_CMP1IF)){
reval = SET;
}
}
}else{
}
}
return reval;
}
/*!
\brief clear CMP flag
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] flag: CMP flags
\arg CMP_FLAG_COMPARE: CMP compare flag
\param[out] none
\retval none
*/
void cmp_flag_clear(cmp_enum cmp_periph, uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
if(CMP_FLAG_COMPARE == flag){
CMP_IFC |= (uint32_t)CMP_IFC_CMP0IC;
}
}else if(CMP1 == cmp_periph){
if(CMP_FLAG_COMPARE == flag){
CMP_IFC |= (uint32_t)CMP_IFC_CMP1IC;
}
}else{
}
}
}
/*!
\brief enable CMP interrupt
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] interrupt: CMP interrupt enable source
only one parameter can be selected which is shown as below:
\arg CMP_INT_COMPARE: CMP compare interrupt
\param[out] none
\retval none
*/
void cmp_interrupt_enable(cmp_enum cmp_periph, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_INTERRUPT(interrupt)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
/* enable CMP0 interrupt */
CMP0_CS |= (uint32_t)interrupt;
}else if(CMP1 == cmp_periph){
/* enable CMP1 interrupt */
CMP1_CS |= (uint32_t)interrupt;
}else{
}
}
}
/*!
\brief disable CMP interrupt
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] interrupt: CMP interrupt enable source
only one parameter can be selected which is shown as below:
\arg CMP_INT_COMPARE: CMP compare interrupt
\param[out] none
\retval none
*/
void cmp_interrupt_disable(cmp_enum cmp_periph, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_INTERRUPT(interrupt)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0014U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
/* disable CMP0 interrupt */
CMP0_CS &= ~(uint32_t)interrupt;
}else if(CMP1 == cmp_periph){
/* disable CMP1 interrupt */
CMP1_CS &= ~(uint32_t)interrupt;
}else{
}
}
}
/*!
\brief get CMP interrupt flag
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] flag: CMP interrupt flags
\arg CMP_INT_FLAG_COMPARE: CMP compare interrupt flag
\param[out] none
\retval none
*/
FlagStatus cmp_interrupt_flag_get(cmp_enum cmp_periph, uint32_t flag)
{
uint32_t intstatus = 0U, flagstatus = 0U;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_INTERRUPT_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
if(CMP_INT_FLAG_COMPARE == flag){
/* get the corresponding flag bit status */
flagstatus = CMP_STAT & CMP_STAT_CMP0IF;
/* get the interrupt enable bit status */
intstatus = CMP0_CS & CMP_CS_CMPXINTEN;
}
}else if(CMP1 == cmp_periph){
if(CMP_INT_FLAG_COMPARE == flag){
/* get the corresponding flag bit status */
flagstatus = CMP_STAT & CMP_STAT_CMP1IF;
/* get the interrupt enable bit status */
intstatus = CMP1_CS & CMP_CS_CMPXINTEN;
}
}else{
}
}
if((0U != flagstatus) && (0U != intstatus)){
return SET;
}else{
return RESET;
}
}
/*!
\brief clear CMP interrupt flag
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] flag: CMP interrupt flags
\arg CMP_INT_FLAG_COMPARE: CMP compare interrupt flag
\param[out] none
\retval none
*/
void cmp_interrupt_flag_clear(cmp_enum cmp_periph, uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_INTERRUPT_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0016U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* clear CMP interrupt flag */
if(CMP0 == cmp_periph){
if(CMP_INT_FLAG_COMPARE == flag){
CMP_IFC |= (uint32_t)CMP_IFC_CMP0IC;
}
}else if(CMP1 == cmp_periph){
if(CMP_INT_FLAG_COMPARE == flag){
CMP_IFC |= (uint32_t)CMP_IFC_CMP1IC;
}
}else{
}
}
}