中微CMS8S3680/69xx系列单片机

news2024/12/23 19:31:36

最近在使用中微CMS8S3680/69xx系列8位单片机来进行电源控制软件开发。

总体觉得这款单片机简单易用,特别是它的数字功能可以映射到任意脚,甚至包括程序的烧录脚,对于PCB布局特别灵活。另外它的存储器资源也是很丰富的,16K字节ROM,256字节RAM以及512字节的XRAM,对于一般的程序是绰绰有余了。编程方面它也有库函数包装好了相关的寄存器设置,无论是使用库函数还是直接设置寄存器都能快速构建应用。详细情况及资料下载可以访问其官方网站:中微半导-CMS79F11x

本次编写的一个程序也是电源控制方面的,软件没有时序要求,比较简单,功能需求大致如下(只说明了各个引脚的功能):

引脚

引脚特性

网络名

功能

功能要求

1

/

GND

2

A/D采样

12VS

检测12V输出电压

输出10.8V-12.6V为正常(2.5-2.8V)

输出>13V,4脚出高(打嗝保护)(3V保护,2.8V恢复正常)

输出<10V为异常(2.31V保护,2.5V恢复正常)

3

输出

12V_JLOFF

12V均流关断信号

12V输出正常时,输出高电平

12V输出异常时,输出低电平

 (默认出低电平,检测2脚状态)

4

输出

12V_OFF

12V关机信号

关机:输出高电平(打嗝保护,间隔时间3.5S)

开机:输出低电平,默认低电平

(默认出低电平,检测2脚、7脚)

5

A/D采样

OT2

过温保护+风扇调速

型号:TTC3A104J4193LY

过温保护点为105℃,恢复点为85℃

保护时关闭两路输出

6

A/D采样

DSCK

检测53V过流保护、过压保护

检测为高,关闭53V输出

检测为低,恢复53V输出

7

A/D采样

12V_OCP/

检测12V过流保护

检测为高,关闭12V输出;

检测为低,恢复12V输出

8

A/D采样

F_F

风扇故障检测

检测高电平,风扇故障

检测低电平,风扇解除故障

9

输出

FAN_F

风扇故障告警

检测风扇故障:出高

检测风扇正常:出低,默认出高

10

输出

FAN_PWM

风扇PWM信号

根据OT2温度进行风扇调速

11

输出

OUT_LED_R

亮红灯

12V /53V输出异常出高(电源风扇异常、输出过压、输出限流、输出短路、电源过温保护)

输出正常出低,默认出高

12

输出

OUT_LED_G

亮绿灯

输出正常,出高亮绿灯

输出异常出低,默认出低

13

A/D采样

PG_IN

检测53V输出正常

正常为高

异常为低

14

输出

53V_OFF1

53V输出关机信号

关闭输出,出高(打嗝保护,间隔时间3.5S)

恢复输出,出低

15

/

DSDA

数据

/

16

VDD

供电脚

/

单片机原理图部分如下:

源程序如下:

1、main.c:主程序,所有程序逻辑的控制基本都是在这里,以下几个函数大致说明一下:

ADC_Process():主要用于检测12V输出的电压和NTC贴片电阻进行过温检测;

Process_1MS():1毫秒任务处理,主要IO滤波和54V输出异常检测;

Process_10MS():10毫秒任务处理,用于过流/过压打嗝的定时计数;

OCP_Process():12V和54V输出过流打嗝标志位设置和清除;

Task_Manager():根据设置的标志位对输出的通断进行控制以及各个告警信号的输出控制;

Adjust_FAN_Duty():根据温度变化来设置风扇控制的PWM占空比。温度越高占空比越高,反之占空比越低;

/*******************************************************************************
* Copyright (C) 2019 China Micro Semiconductor Limited Company. All Rights Reserved.
*
* This software is owned and published by:
* CMS LLC, No 2609-10, Taurus Plaza, TaoyuanRoad, NanshanDistrict, Shenzhen, China.
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with CMS
* components. This software is licensed by CMS to be adapted only
* for use in systems utilizing CMS components. CMS shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. CMS is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/

/****************************************************************************/
/** \file main.c
**
**
**
**  History:
**
*****************************************************************************/
/****************************************************************************/
/*  include files
*****************************************************************************/
#include "cms8s6990.h"
#include "demo_timer.h"
#include "demo_adc.h"
#include "demo_epwm.h"
#include "main.h"

/****************************************************************************/
/*  Local pre-processor symbols('#define')
*****************************************************************************/

/****************************************************************************/
/*  Global variable definitions(declared in header file with 'extern')
*****************************************************************************/
volatile uint8_t cFlag_1ms = 0;   //1ms timeout flag
volatile uint8_t cDelay_10ms = 0; //10 milli-seconds overflow flag
volatile uint8_t cFlag_2ms = 0;   //2 milli-seconds timeout for ADC filtering
volatile uint8_t c2mS_Nct = 0;    //2 milli-seconds counter    
uint16_t u16FanDuty = 0;          //the duty cycle of the FAN

ALARM_STATUS AlarmStatus;

//IO check
uint8_t v54_ocp_delay = 0; //when V54 OCP occurs, we need to delay about 40 milli-second and then start the hiccup
uint8_t v54_on_time = 0;
uint8_t v12_on_time = 0;
uint16_t io_filter_cnt = 0;
uint8_t pg_in_L =0, pg_in_H =0;
uint8_t fan_fail_L =0, fan_fail_H =0;
/*===================================================================

                    Burp related variables

====================================================================*/
uint8_t cBurpOnDelay1=0;	//ON state duration in a hiccup period of 12V output
//uint8_t cDelay1On=0;
uint16_t cDelay1Burp=0;		//OFF state duration in a hiccup period
uint8_t cBurpOn1Flag=0;		//OFF time is timeout and switches to ON state

uint8_t cBurpOnDelay2=0;    //54V hiccup
uint16_t cDelay2Burp=0;
uint8_t cBurpOn2Flag=0;

/****************************************************************************/
/*  Local type definitions('typedef')
*****************************************************************************/

/****************************************************************************/
/*  Local variable  definitions('static')
*****************************************************************************/

//System clock setting
uint32_t Systemclock = 24000000;

/****************************************************************************/
/*  Local function prototypes('static')
*****************************************************************************/

/**
*@name: AD_Filter
*@description: AD filtering, mainly the 12V voltage filtering
*@params: none
*@return: none
*/
//static void AD_Filter(void)
//{
    
//}

/**
*@name: IO_Status_Check
*@description: Check all the IO status and set the flags accordingly
*@params: none
*@return: none
*/
static void IO_Status_Check(void)
{
    if(PG_IN == 1) pg_in_H++; //1: noral, 0: error
    else pg_in_L++;
    
    if(FAN_FAIL == 0) fan_fail_L++; //0: Fan works correctly
    else fan_fail_H++;

    if (io_filter_cnt >= IO_FILTER_CNT)
    {       
        if (pg_in_H >= IO_FILTER_VALID_CNT && AlarmStatus.alarm.V54_FAILED == 1)//54V status
        {
            AlarmStatus.alarm.V54_FAILED = 0;
        }
        else if (pg_in_L >= IO_FILTER_VALID_CNT && AlarmStatus.alarm.V54_FAILED == 0)
        {
            AlarmStatus.alarm.V54_FAILED = 1;
        }
        
        if (fan_fail_L >= IO_FILTER_VALID_CNT && AlarmStatus.alarm.FAN_FAILED == 1)//fan check
        {
            AlarmStatus.alarm.FAN_FAILED = 0;
        }
        else if (fan_fail_H >= IO_FILTER_VALID_CNT && AlarmStatus.alarm.FAN_FAILED == 0)
        {
            AlarmStatus.alarm.FAN_FAILED = 1;
        }

        io_filter_cnt = 0;        
        pg_in_L =0;
        pg_in_H =0;
        fan_fail_L =0;
        fan_fail_H =0;
    }
    else
    {
        io_filter_cnt++;
    }
}

/**
*@name: State_Switching_Manager
*@description: switch all the states according to the power-supply status
               e.g. if the VAC is over-voltage, we need to shut off the main output
*@params: none
*@return: none
*/
//static void State_Switching_Manager(void)
//{

//}

/**
*@name: V12V_OCP_Burp_Process
*@description: 12V OCP process
*@params: none
*@return: none
*/
static void V12_OCP_Burp_Process(void)
{
    //if(V12_OCP)//check the OCP pin,1: OCP, 0: normal ,and at the same we check the V12 output status
    if(V12_OCP || AlarmStatus.alarm.V12_OVP)
	{
        if(V12_OCP)
        {
            if(cBurpOn1Flag >= 3) cBurpOn1Flag = 3;//still OCP, 20-30 milli-seconds filtering
        }
        else //OVP occurred, set the counter without any delay
        {
            cBurpOn1Flag = 3;
        }
	}
	else
	{
		cBurpOn1Flag = 0;
	}
	
	if(cBurpOn1Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.OCP_V12 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay1 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.OCP_V12 = 1;
				AlarmStatus.alarm.OCP_BURP_V12 = 1;				
			}
		}
	}
	
    if(cDelay1Burp>=BURP_LAST_TIME)//3 seconds period
    {
        cDelay1Burp = 0;
        AlarmStatus.alarm.OCP_V12 = 0;
        AlarmStatus.alarm.OCP_BURP_V12 = 0;
    }
    
    /*
    //if(V12_OCP)//check the OCP pin,1: OCP, 0: normal ,and at the same we check the V12 output status
    if(V12_OCP || AlarmStatus.alarm.V12_OVP)
	{
		if(cBurpOn1Flag >= 3) cBurpOn1Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn1Flag = 0;
	}
	
	if(cBurpOn1Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.OCP_V12 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay1 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.OCP_V12 = 1;
				AlarmStatus.alarm.OCP_BURP_V12 = 1;				
			}
		}
	}
	
    if(cDelay1Burp>=BURP_LAST_TIME)//3 seconds period
    {
        cDelay1Burp = 0;
        AlarmStatus.alarm.OCP_V12 = 0;
        AlarmStatus.alarm.OCP_BURP_V12 = 0;
    }
    */
}

/**
*@name: V54_OCP_Burp_Process
*@description: 54V OCP process
*@params: none
*@return: none
*/
static void V54_OCP_Burp_Process(void)
{
    if(V54_OCP)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn2Flag >= 3) //filtering to make sure that the OCP really occurs
        {
            cBurpOn2Flag = 3;//still OCP, 20-30 milli-seconds filtering
            /*
            if(AlarmStatus.alarm.V54_JL_FINISHED == 0)
            {
                if(v54_ocp_delay >= V54_JL_TIMEOUT)
                {
                    AlarmStatus.alarm.V54_JL_FINISHED = 1;
                }
            }*/            
        }
	}
	else
	{
		cBurpOn2Flag = 0;
        /*
        if(v54_on_time >= V54_ON_TIME)//the OCP is dissolved completely
        {
            v54_ocp_delay = 0;
        }
        AlarmStatus.alarm.V54_JL_FINISHED = 0; //don't need any delay
        */
	}
	
	if(cBurpOn2Flag >= 3)//once OCP occurs, we need to delay some time before starting hiccup
	{
		if(AlarmStatus.alarm.OCP_V54 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay2 == 0)//decreased in the 10 milli-seconds service routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.OCP_V54 = 1;
				AlarmStatus.alarm.OCP_BURP_V54 = 1;				
			}
		}
	}
	
    if(cDelay2Burp>=BURP_LAST_TIME)//3 seconds period
    {
        cDelay2Burp = 0;
        AlarmStatus.alarm.OCP_V54 = 0;
        AlarmStatus.alarm.OCP_BURP_V54 = 0;
    }
}



/**
*@function name: GPIO_Config
*@description:
*@parameters: None
*@return: None
#define     PG_IN                      (P31)   //input, 54V output signal, 1: normal, 0:error
#define     V12_JL                     (P04)   //output, V12 JL signal, 1: if V12 is OK, else: 0
#define     V54_ON                     (P32)   //output, 54V ON/OFF control, 0: OFF, 1: ON
#define     V12_ON                     (P13)   //output, 12V ON/OFF control, 0: OFF, 1: ON
#define     FAN_OK                     (P24)   //output, FAN signal, 0: normal, 1: exception
#define     V54_OCP                    (P21)   //input, 54V OCP, 0: normal, 1: OCP
#define     V12_OCP                    (P22)   //input, 12V OCP, 0: normal, 1: OCP
#define     LED_GREEN                  (P30)   //output, LED, 1: normal, 0: exception
#define     LED_RED                    (P26)   //output, LED, 0: normal, 1: exception
#define     FAN_FAIL                   (P23)   //input, fan status, 0: normal, 1: exception
*/
static void GPIO_Config(void)
{
    //P31: PG_IN, 54V warning signal, input mode
    GPIO_SET_MUX_MODE(P31CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_INPUT(P3TRIS, GPIO_PIN_1); 
    
    //P04: 12V JL OFF, output mode
    GPIO_SET_MUX_MODE(P04CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_OUTPUT(P0TRIS, GPIO_PIN_4);
    
    //P32: V54 ON/OFF control, output mode
    GPIO_SET_MUX_MODE(P32CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_OUTPUT(P3TRIS, GPIO_PIN_2); 
    
    //P13: V12 ON/OFF control, output mode
    GPIO_SET_MUX_MODE(P13CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_OUTPUT(P1TRIS, GPIO_PIN_3);
    
    //P24: FAN_OK, output mode
    GPIO_SET_MUX_MODE(P24CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_OUTPUT(P2TRIS, GPIO_PIN_4);
    
    //P21: V54 OCP, output mode
    GPIO_SET_MUX_MODE(P21CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_INPUT(P2TRIS, GPIO_PIN_1);
    
    //P22: 12V_OCP, intput mode
    GPIO_SET_MUX_MODE(P22CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_INPUT(P2TRIS, GPIO_PIN_2);
    
    //P30: green LED, shut off by default
    GPIO_SET_MUX_MODE(P30CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_OUTPUT(P3TRIS, GPIO_PIN_0);
    
    //P26: REG LED, shut off by default
    GPIO_SET_MUX_MODE(P26CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_OUTPUT(P2TRIS, GPIO_PIN_6);
    
    //P23: fan exception, intput mode
    GPIO_SET_MUX_MODE(P23CFG, GPIO_MUX_GPIO);
    GPIO_ENABLE_INPUT(P2TRIS, GPIO_PIN_3);

    //set the default status of all output signals
    V12_JL = 0;
    LED_RED = 1;
    LED_GREEN = 0;
    FAN_OK = 1; //FAN is error by default
    V12_ON = 1;//12V is OFF
    V54_ON = 1;//54V is OFF
}

/**
*@name: Process_1MS
*@description: 1 milli-second task polling, including the I/O status check
*@params: none
*@return: none
*/
static void Process_1MS(void)
{
    if (cFlag_1ms == 0)
    {
        return;
    }
    cFlag_1ms = 0;
    IO_Status_Check();
}

/**
*@name: Process_10MS
*@description: 10 milli-seconds timeout process used to process the OCP check
*@params: none
*@return: none
*/
static void Process_10MS(void)
{
	if(cDelay_10ms >= 10)
	{
		cDelay_10ms = 0;
		if(cBurpOnDelay1!=0) cBurpOnDelay1--;
		if(cBurpOnDelay2!=0) cBurpOnDelay2--;		
		
		//once in OCP state we count-up
		if(AlarmStatus.alarm.OCP_V12 && cDelay1Burp < 1200) cDelay1Burp++;
		if(AlarmStatus.alarm.OCP_V54 && cDelay2Burp < 1200) cDelay2Burp++;
		
		if(cBurpOn1Flag < 10) ++cBurpOn1Flag;
		if(cBurpOn2Flag < 10) ++cBurpOn2Flag;
        
        if(AlarmStatus.alarm.V54_FAILED == 0 && AlarmStatus.alarm.OCP_BURP_V54 == 0)//check whether the V54 OCP is dissolved
        {
            if(++v54_on_time >= V54_ON_TIME)
            {
                v54_on_time = V54_ON_TIME;
            }
        }
        
        if(AlarmStatus.alarm.V12_FAILED == 0 && AlarmStatus.alarm.OCP_BURP_V12 == 0)//check whether the V12 OCP is dissolved
        {
            if(++v12_on_time >= V12_ON_TIME)
            {
                v12_on_time = V12_ON_TIME;
            }
        }
        
        /*
        if(cBurpOn2Flag>=3)//ONLY when 54V OCP occurs can we up-count variable v54_ocp_delay
        {
            if(++v54_ocp_delay >= V54_JL_TIMEOUT) //wait for the JL to be finished
            {
                v54_ocp_delay = V54_JL_TIMEOUT;
            }
        }
        if(AlarmStatus.alarm.V54_ON_LINE == 1 && AlarmStatus.alarm.OCP_BURP_V54 == 0)//check whether the V54 OCP is dissolved
        {
            if(++v54_on_time >= V54_ON_TIME)
            {
                v54_on_time = V54_ON_TIME;
            }
        }
        */
	}
}

/**
*@name: OCP_Process
*@description: the OCP service routine for V12 and V54
*@params: none
*@return: none
*/
static void OCP_Process(void)
{
    V12_OCP_Burp_Process();
    V54_OCP_Burp_Process();
}

/**
*@name: Task_Manager
*@description: the output control and all the warnings process
*@params: none
*@return: none
*/
static void Task_Manager(void)
{
    /*if(v12_ad_value >= V12_NORMAL_AD && AlarmStatus.alarm.V12_FAILED == 1) //12V output error check
    {
        AlarmStatus.alarm.V12_FAILED = 0;
    }
    else if(v12_ad_value <= V12_ERROR_AD && AlarmStatus.alarm.V12_FAILED == 0)
    {
        AlarmStatus.alarm.V12_FAILED = 1;
    }*/
    
    if(v12_ad_value <= V12_UVP_AD && AlarmStatus.alarm.V12_UVP == 0) //12V UVP check
    {
        AlarmStatus.alarm.V12_UVP = 1;
    }
    else if(v12_ad_value >= V12_UVP_RECOVERED_AD && AlarmStatus.alarm.V12_UVP == 1)
    {
        AlarmStatus.alarm.V12_UVP = 0;
    }
    
    if(v12_ad_value >= V12_OVP_AD && AlarmStatus.alarm.V12_OVP == 0) //12V OVP check
    {
        AlarmStatus.alarm.V12_OVP = 1;
    }
    else if(v12_ad_value <= V12_OVP_RECOVERED_AD && AlarmStatus.alarm.V12_OVP == 1)
    {
        AlarmStatus.alarm.V12_OVP = 0;
    }
    
    if(AlarmStatus.alarm.V12_UVP == 0 && AlarmStatus.alarm.V12_OVP == 0) //12V output error check
    {
        AlarmStatus.alarm.V12_FAILED = 0;
    }
    else
    {
        AlarmStatus.alarm.V12_FAILED = 1;
    }    
    
    if(otp_ad_value >= T2OTP && AlarmStatus.alarm.OTP2 == 0)  //OTP check
    {
        AlarmStatus.alarm.OTP2 = 1;
    }
    else if(otp_ad_value <= T2OTPHYS && AlarmStatus.alarm.OTP2 == 1)
    {            
        AlarmStatus.alarm.OTP2 = 0;
    }
    
    if(AlarmStatus.alarm.V12_FAILED == 0)//12V JL OFF signal, 0: 12V has error, 1: 12V works well
    {
        V12_JL = 1;
    }
    else
    {
        V12_JL = 0;
    }
    
    if(AlarmStatus.alarm.FAN_FAILED == 0)//FAN warning signal, 1: error, 0: normal
    {
        FAN_OK = 0;
    }
    else
    {
        FAN_OK = 1;
    }
    
    /*
    If there are no OCP and OTP, turn ON the output directly.
    Once OCP occurs, we turn OFF the outpuT for about 3.5 second, and then turn ON it for about 100 milli-seconds.
    Unless otherwise stated, other outputs have the same mechanism as the first channel.
    */
    if((AlarmStatus.alarm.OTP2 == 0) && (AlarmStatus.alarm.OCP_BURP_V12 == 0))
    {
        V12_ON = 0; //turn ON 12V
        cDelay1Burp = 0;
    }
    else
    {
        V12_ON = 1; //turn OFF 12V
        cBurpOnDelay1 = 10;
        v12_on_time = 0;
    }
    if((AlarmStatus.alarm.OTP2 == 0) && (AlarmStatus.alarm.OCP_BURP_V54 == 0))
    {
        V54_ON = 0; //turn ON 54V
        cDelay2Burp = 0;
    }
    else
    {
        V54_ON = 1; //turn OFF 54V
        cBurpOnDelay2 = 10;
        v54_on_time = 0;
    }
    
    //If there is any warning or exception, turn on the RED LED 
    //and turn off the GREEN LED. Turn on the green LED in other cases.
    if(((AlarmStatus.allbits & WARNING_FLAG) != 0x0000) || (v12_on_time < V12_ON_TIME) || (v54_on_time < V54_ON_TIME))
    {
        LED_GREEN = 0;
        LED_RED = 1;
    }
    else //green LED is ON
    {
        LED_GREEN = 1;
        LED_RED = 0;
    }	
}

/**
*@name: Watchdog_Manager
*@description: clear the watchdog overflowing timer
*@params: none
*@return: none
*/
static void Watchdog_Manager(void)
{
    WDT_ClearWDT();
}

/******************************************************************************
 ** \brief   WDT_Config
 ** \param [in]
 **
 ** \return  none
 ** \note
 ******************************************************************************/
static void WDT_Config(void)
{
    //(1)feed the watchdog
    WDT_ClearWDT();
    /*
    (2)set the clock and timeout
    */
    WDT_ConfigOverflowTime(WDT_CLK_67108864);   // Fsys=24Mhz -> Twdt = 67108864/24 = 2796.202ms
    /*
    (3)enable the overflow interrupt
    */
    WDT_EnableOverflowInt();

    IRQ_SET_PRIORITY(IRQ_WDT, IRQ_PRIORITY_HIGH);
    IRQ_ALL_ENABLE();
}

/******************************************************************************
 ** \brief   initialize the warning flags
 ** \param [in]
 **
 ** \return  none
 ** \note
 ******************************************************************************/
static void Init_Flags(void)
{
    AlarmStatus.alarm.V12_UVP = 1;
    AlarmStatus.alarm.V12_OVP = 1;
    AlarmStatus.alarm.V12_FAILED = 1;
    AlarmStatus.alarm.V54_FAILED = 1;
    AlarmStatus.alarm.FAN_FAILED = 1;
    AlarmStatus.alarm.OTP2 = 1;
}

/******************************************************************************
 ** \brief   adjust the duty cycle of the FAN according to the temperature
 ** \param [in] value, the duty cycle
 **
 ** \return  none
 ** \note
 ******************************************************************************/
static void Adjust_FAN_Duty(void)
{
    //set a minumum duty cycle if the temperature is less than or equal to 30 degree, 20%
    if(TMP_OUT <= 30)
    {
        u16FanDuty = 1200;
    }    
    else if(TMP_OUT >= 70)//set the maximum duty cycle, 100%
    {
        u16FanDuty = 6000;
    }
    else //2% duty cycle per step
    {
        u16FanDuty = (uint8_t)(6000- (8400-(120 * TMP_OUT)));//linear duty cycle according to the temperature
    }
    
    if(u16FanDuty > 6000)//can't exceed the maximum duty cycle
    {
        u16FanDuty = 6000;
    }
    
    if(u16FanDuty < 1200)//at least 20% duty cycle
    {
        u16FanDuty = 1200;
    }
    
    Adjust_EPWM_Duty(u16FanDuty);
}

/****************************************************************************/
/*  Function implementation - global ('extern') and local('static')
*****************************************************************************/

/*****************************************************************************
 ** \brief   main
 **
 ** \param [in]  none
 **
 ** \return 0
 *****************************************************************************/

int main(void)
{
    GPIO_Config();
    ADC_Config();
    EPWM_Config();
    TMR1_Config();
    Init_Flags();
    WDT_Config();
    SYS_EnableWDTReset();
    while (1)
    {
        ADC_Process();
        Process_1MS();
        Process_10MS();
        OCP_Process();
        Task_Manager();
        Adjust_FAN_Duty();
        Watchdog_Manager();
    }

    //return 0;//unreachable
}

2、main.h:头文件

/**
 * @file main.h
 * @author Nations Solution Team
 * @version v1.0.0
 *
 * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
 */
#ifndef __MAIN_H__
#define __MAIN_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "cms8s6990.h"

#define     BURP_LAST_TIME          350         //turn off the 54V and 12V for about 3.5 seconds once OCP
#define     V54_ON_TIME             50          //If the 54V output works normally about 500 milli-seconds, then we think that the OCP is dissolved.
#define     V12_ON_TIME             50          //If the 12V output works normally about 500 milli-seconds, then we think that the OCP is dissolved.
#define     V54_JL_TIMEOUT          4           //delay 40 milli-seconds once V54 OCP occurs         
#define     BURP_PS_ON_TIME         100         //turn on the 54V and 12V output for about 100 milli-seconds
#define     IO_FILTER_CNT           20          //IO filter count
#define     IO_FILTER_VALID_CNT     20          //IO valid count of filter
#define     WARNING_FLAG            0x00FF      //warning bits to be examined

/*
==========================================================================================================================

                    IO Pin Macros

==========================================================================================================================
*/
#define     PG_IN                               (P31)   //input, 54V output signal, 1: normal, 0:error
#define     V12_JL                              (P04)   //output, V12 JL signal, 1: if V12 is OK, else: 0
#define     V54_ON                              (P32)   //output, 54V ON/OFF control, 0: OFF, 1: ON
#define     V12_ON                              (P13)   //output, 12V ON/OFF control, 0: OFF, 1: ON
#define     FAN_OK                              (P24)   //output, FAN signal, 0: normal, 1: exception
#define     V54_OCP                             (P21)   //input, 54V OCP, 0: normal, 1: OCP
#define     V12_OCP                             (P22)   //input, 12V OCP, 0: normal, 1: OCP
#define     LED_GREEN                           (P30)   //output, LED, 1: normal, 0: exception
#define     LED_RED                             (P26)   //output, LED, 0: normal, 1: exception
#define     FAN_FAIL                            (P23)   //input, fan status, 0: normal, 1: exception

extern volatile uint8_t cFlag_1ms;
extern volatile uint8_t cDelay_10ms;
extern volatile uint8_t cFlag_2ms;
extern volatile uint8_t c2mS_Nct;

struct ALARM 
{
    unsigned    V12_FAILED                      : 1;    //12V status
    unsigned    V54_FAILED                      : 1;    //54V status
    unsigned    FAN_FAILED                      : 1;    //FAN status
    unsigned    OTP2                            : 1;    //OTP
    unsigned    OCP_V12                         : 1;    //12V OCP
    unsigned    OCP_V54                         : 1;    //54V OCP
    unsigned    OCP_BURP_V12                    : 1;
    unsigned    OCP_BURP_V54                    : 1;


    unsigned    V12_UVP                         : 1;
    unsigned    V12_OVP                         : 1;
    unsigned                                    : 1;
    unsigned                                    : 1;
    unsigned                                    : 1;
    unsigned                                    : 1;
    unsigned                                    : 1;
    unsigned                                    : 1;
};

union ALARM_STATUS_UNION {
    struct ALARM    alarm;
    uint16_t    allbits;
};

typedef union ALARM_STATUS_UNION ALARM_STATUS;

typedef enum
{
    FAILED = 0,
    PASSED = !FAILED
} Status;

extern ALARM_STATUS AlarmStatus;

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H__ */
/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */

3、demo_timer.c:定时器1的1毫秒定时设置

/*******************************************************************************
* Copyright (C) 2019 China Micro Semiconductor Limited Company. All Rights Reserved.
*
* This software is owned and published by:
* CMS LLC, No 2609-10, Taurus Plaza, TaoyuanRoad, NanshanDistrict, Shenzhen, China.
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with CMS
* components. This software is licensed by CMS to be adapted only
* for use in systems utilizing CMS components. CMS shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. CMS is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/

/****************************************************************************/
/** \file demo_timer.c
**
**
**
**  History:
**
*****************************************************************************/
/****************************************************************************/
/*  include files
*****************************************************************************/
#include "demo_timer.h"
#include "main.h"

/****************************************************************************/
/*  Local pre-processor symbols('#define')
****************************************************************************/
#define TIMER_1MS   2000

/****************************************************************************/
/*  Global variable definitions(declared in header file with 'extern')
****************************************************************************/

/****************************************************************************/
/*  Local type definitions('typedef')
****************************************************************************/

/****************************************************************************/
/*  Local variable  definitions('static')
****************************************************************************/

/****************************************************************************/
/*  Local function prototypes('static')
****************************************************************************/

/****************************************************************************/
/*  Function implementation - global ('extern') and local('static')
****************************************************************************/
/******************************************************************************
** \brief    TMR1_Config
** \param [in]
**
** \return  none
** \note
******************************************************************************/
void TMR1_Config(void)
{
    //(1)设置Timer的运行模式
    TMR_ConfigRunMode(TMR1, TMR_MODE_TIMING, TMR_TIM_16BIT);

    //(2)设置Timer 运行时钟
    TMR_ConfigTimerClk(TMR1, TMR_CLK_DIV_12);//Fsys = 24Mhz,Ftimer = 2Mhz,Ttmr=0.5us

    //(3)设置Timer周期
    TMR_ConfigTimerPeriod(TMR1, (65536 - TIMER_1MS) >> 8, 65536 - TIMER_1MS); // 2000*0.5us = 1000us,递增计数

    //(4)开启中断
    TMR_EnableOverflowInt(TMR1);

    //(5)设置Timer中断优先级
    IRQ_SET_PRIORITY(IRQ_TMR1, IRQ_PRIORITY_LOW);
    IRQ_ALL_ENABLE();

    //(6)开启Timer
    TMR_Start(TMR1);
}

4、demo_adc.c:主要是ADC检测及NTC贴片电阻不同阻值下对应的AD值表,然后程序根据AD值表获取相应的温度信息。AD取样每两毫秒进行一次,12V输出电压共检测16次,温度值检测共8次,然后取平均值。

/*******************************************************************************
* Copyright (C) 2019 China Micro Semiconductor Limited Company. All Rights Reserved.
*
* This software is owned and published by:
* CMS LLC, No 2609-10, Taurus Plaza, TaoyuanRoad, NanshanDistrict, Shenzhen, China.
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with CMS
* components. This software is licensed by CMS to be adapted only
* for use in systems utilizing CMS components. CMS shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. CMS is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/

/****************************************************************************/
/** \file demo_adc.c
**
**
**
**  History:
**
*****************************************************************************/
/****************************************************************************/
/*  include files
*****************************************************************************/
#include "demo_adc.h"
#include <math.h>

/****************************************************************************/
/*  Local pre-processor symbols('#define')
****************************************************************************/

/****************************************************************************/
/*  Global variable definitions(declared in header file with 'extern')
****************************************************************************/
extern volatile uint8_t cFlag_2ms;

#define     SAMPLE_COUNT        15      //sample count

uint16_t    sample_cnt = 0; //sampled count
uint8_t     channel = 0; //current ADC channel

//===================================================================================
//Unless stated otherwise, the following variables are similar to those that ACS uses
//===================================================================================
uint32_t    sample_ad_sum  = 0;
uint16_t    v12_ad_value = 0;
uint16_t    otp_ad_value = 0;
signed int  TMP_OUT = 0; //the actual temperature needed in fan duty cycle adjust

xdata uint16_t ARP_CWF4200[136] = {0x29,
0x2C,
0x2E,
0x31,
0x34,
0x38,
0x3B,
0x3F,
0x42,
0x47,
0x4B,
0x4F,
0x54,
0x59,
0x5E,
0x64,
0x6A,
0x70,
0x76,
0x7D,
0x84,
0x8B,
0x93,
0x9B,
0xA4,
0xAC,
0xB6,
0xBF,
0xC9,
0xD4,
0xDF,
0xEA,
0xF6,
0x103,
0x110,
0x11D,
0x12B,
0x13A,
0x149,
0x158,
0x169,
0x179,
0x18B,
0x19C,
0x1AF,
0x1C2,
0x1D6,
0x1EB,
0x1FF,
0x215,
0x22B,
0x243,
0x25A,
0x272,
0x28B,
0x2A5,
0x2BF,
0x2DA,
0x2F6,
0x312,
0x32F,
0x34C,
0x36A,
0x389,
0x3A8,
0x3C8,
0x3E9,
0x40A,
0x42B,
0x44D,
0x46F,
0x492,
0x4B6,
0x4D9,
0x4FE,
0x522,
0x547,
0x56C,
0x591,
0x5B7,
0x5DD,
0x603,
0x629,
0x64F,
0x675,
0x69C,
0x6C2,
0x6E8,
0x70E,
0x735,
0x75A,
0x780,
0x7A6,
0x7CC,
0x7F1,
0x816,
0x83A,
0x85F,
0x883,
0x8A7,
0x8CB,
0x8ED,
0x910,
0x932,
0x954,
0x975,
0x995,
0x9B6,
0x9D6,
0x9F5,
0xA14,
0xA32,
0xA50,
0xA6D,
0xA89,
0xAA6,
0xAC0,
0xADB,
0xAF5,
0xB0E,
0xB27,
0xB40,
0xB58,
0xB70,
0xB87,
0xB9E,
0xBB5,
0xBCB,
0xBE1,
0xBF6,
0xC0B,
0xC1F,
0xC33,
0xC47,
0xC5A,
0xC6D
};
/****************************************************************************/
/*  Local type definitions('typedef')
****************************************************************************/

/****************************************************************************/
/*  Local variable  definitions('static')
****************************************************************************/

/****************************************************************************/
/*  Local function prototypes('static')
****************************************************************************/

/****************************************************************************/
/*  Function implementation - global ('extern') and local('static')
****************************************************************************/
/******************************************************************************
 ** \brief   ADC_Config
 ** \param [in]
 **
 ** \return  none
 ** \note
 ******************************************************************************/
void ADC_Config(void)
{
    uint8_t temp = 20;
    //set the run mode of the ADC
    //set the ADC clock divided by 16 of the system clock, the conversion is left-alignment
    //ADC_ConfigRunMode(ADC_CLK_DIV_256, ADC_RESULT_LEFT);
    //====please refer to the user manual page 175====
    ADC_ConfigRunMode(ADC_CLK_DIV_16, ADC_RESULT_LEFT);

    //set ADC channels used
    GPIO_SET_MUX_MODE(P17CFG, GPIO_P17_MUX_AN20);//OTP check
    GPIO_SET_MUX_MODE(P05CFG, GPIO_P05_MUX_AN5);//12V output voltage check
    channel = CH_V12;
    ADC_EnableChannel(channel);
    while (temp-- != 0);

    //set the interrupt, here we don't need the interrupt
    //ADC_EnableInt();
    //IRQ_SET_PRIORITY(IRQ_ADC,IRQ_PRIORITY_HIGH);
    //IRQ_ALL_ENABLE();
    //start and enable the ADC, set ADEN bit to 1
    ADC_Start();
}

/**
*@name: TTC05104_ADBinary_Search
*@description: get the index of the table NTC_ADArray according to the ADC value
			   order by ASC
*@params: ad_value: the sampled ADC value
*@return: the final AD value
*/
static uint8_t  ARP_CWF4200_ADBinary_Search(uint16_t ad_value)
{	
   int start=0; //start index
   int end = 135; //max index
   int mid = 0;  //the index we need
   while(start<=end)
   {
      mid=(start+end)/2;//get the middle index
	  if(mid==135) break;//the maximum index
      if(ad_value==ARP_CWF4200[mid]) break;  //we get the right index  
      if((ad_value>ARP_CWF4200[mid])&&(ad_value<ARP_CWF4200[mid+1]))  break;
			
      if(ad_value>ARP_CWF4200[mid])  //the index we need is in the second part
		start = mid+1; 
		
      else if(ad_value<ARP_CWF4200[mid])
		end = mid-1;
   }
   return mid;//get the index
}

/*
* function name: Cal_Temperature
* description: convert the ADC value to temperature
* params: ad_value: NTC AD value
* return: the actual temperature multiplied by 100
*/
signed int Cal_Temperature(uint16_t ad_value)
{
	float temperature=0.00;
	signed short search_temperature=0;
	uint8_t temp=ARP_CWF4200_ADBinary_Search(ad_value);
	if(temp < 135)
	{
		search_temperature=temp-30;
		temperature=search_temperature+(float)(ARP_CWF4200[temp]-ad_value)/(float)(ARP_CWF4200[temp]-ARP_CWF4200[temp+1]);
		//temperature*=10;
	}
	else
	{
		return (105);//maximum temperature is 105
	}
    
	return (signed int)(temperature);
}

void ADC_Process(void)
{
    ADC_Sample();
    TMP_OUT = Cal_Temperature(otp_ad_value);
}

/**
*@name: ADC_Sample
*@description: Sample the AD value and set the sample_flag according to the result
*@params: none
*@return: none
*/
void ADC_Sample(void)
{
    uint16_t ad_data = 0;
    uint8_t temp = 20; //delay about 500ns when changing the ADC channel
    
    if(cFlag_2ms == 1) //2 milli-seconds timeout
    { 
        switch(channel)
        {
            case CH_V12:                
                ADC_GO();
                while (ADC_IS_BUSY);//wait while the ADGO bit is 1
                ad_data = ADC_GetADCResult();
                sample_ad_sum += ad_data;
                if (sample_cnt >= SAMPLE_COUNT)
                {
                    sample_cnt = 0;
                    v12_ad_value = sample_ad_sum >> 4;
                    sample_ad_sum = 0;
                    channel = CH_OTP;
                    ADC_EnableChannel(CH_OTP);
                    temp = 20;
                    while (temp-- != 0);
                }
                else
                {
                    sample_cnt++;
                }
                break;
                
            case CH_OTP:
                ADC_GO();
                while (ADC_IS_BUSY);
                ad_data = ADC_GetADCResult();
                sample_ad_sum += ad_data;
                if (sample_cnt >= SAMPLE_COUNT - 8)
                {
                    sample_cnt = 0;
                    otp_ad_value = sample_ad_sum >> 3;
                    sample_ad_sum = 0;
                    channel = CH_V12;
                    ADC_EnableChannel(CH_V12);
                    temp = 20;
                    while (temp-- != 0);
                }
                else
                {
                    sample_cnt++;
                }
                break;
            
            default:
                sample_cnt = 0;
                sample_ad_sum = 0;                
                channel = CH_V12;
                ADC_EnableChannel(CH_V12);
                temp = 20;
                while (temp-- != 0);
                break;
        }
        cFlag_2ms = 0;
    }
}

5、demo_adc.h:ADC头文件定义:

/*******************************************************************************
* Copyright (C) 2019 China Micro Semiconductor Limited Company. All Rights Reserved.
*
* This software is owned and published by:
* CMS LLC, No 2609-10, Taurus Plaza, TaoyuanRoad, NanshanDistrict, Shenzhen, China.
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with CMS
* components. This software is licensed by CMS to be adapted only
* for use in systems utilizing CMS components. CMS shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. CMS is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/

/*****************************************************************************/
/** \file demo_timer.h
**
**
**
** History:
** -
*****************************************************************************/
#ifndef __DEMO_ADC_H__
#define __DEMO_ADC_H__
/*****************************************************************************/
/* Include files */
/*****************************************************************************/
#include "cms8s6990.h"

/*****************************************************************************/
/* Global pre-processor symbols/macros ('#define') */
/*****************************************************************************/
#define         CH_V12                  ADC_CH_5
#define         CH_OTP                  ADC_CH_20

#define         ADCFS                   4096.0  //12-bit ADC maximum AD value
#define         ADCREF                  5.0     //3.3V reference voltage

#define         V12_DIV_RUP				(10.0)  //up and down resistors
#define         V12_DIV_RLOW			3.0
#define         ADC_DIV_REF             (float)(ADCFS/ADCREF)
#define         V12_DIV_GAIN			((float)(V12_DIV_RLOW/(V12_DIV_RLOW + V12_DIV_RUP)))//gain: 3.0/(3.0+13) 
#define         V12_OVP_AD              2458    //3.0V
#define         V12_OVP_RECOVERED_AD    2294    //2.8V
#define         V12_UVP_AD              1884    //2.3V
#define         V12_UVP_RECOVERED_AD    2048    //2.5V
   
//#define         V12_NORMAL_AD           2048    //2.5V
//#define         V12_ERROR_AD            1884    //2.3V
//#define         V12_UVP_ALARM           9.0
//#define         V12_OVP_ALARM           15.0
//#define         V12_UVP_ALARM_OFF       11.0
//#define         V12_OVP_ALARM_OFF       13.0
//#define         V12_UVP_ALARM_AD        (uint16_t)(V12_UVP_ALARM * V12_DIV_GAIN * ADC_DIV_REF)
//#define         V12_OVP_ALARM_AD        (uint16_t)(V12_OVP_ALARM * V12_DIV_GAIN * ADC_DIV_REF)
//#define         V12_UVP_ALARM_OFF_AD    (uint16_t)(V12_UVP_ALARM_OFF * V12_DIV_GAIN * ADC_DIV_REF)
//#define         V12_OVP_ALARM_OFF_AD    (uint16_t)(V12_OVP_ALARM_OFF * V12_DIV_GAIN * ADC_DIV_REF)

// APR-CWF104F4200FA20A Temperature sensor
#define		    T2OTP                   3083    // 100C,3.76V,5.57K
#define		    T2OTPHYS                2580    // 80C,3.15V,10.75K

/*****************************************************************************/
/* Global type definitions ('typedef') */
/*****************************************************************************/



/*****************************************************************************/
/* Global variable declarations ('extern', definition in C source) */
/*****************************************************************************/
extern uint16_t v12_ad_value;
extern uint16_t otp_ad_value;
extern signed int  TMP_OUT;

/*****************************************************************************/
/* Global function prototypes ('extern', definition in C source) */
/*****************************************************************************/
/******************************************************************************
 ** \brief   ADC_Config
 ** \param [in]
 **
 ** \return  none
 ** \note
 ******************************************************************************/
void ADC_Config(void);
void ADC_Process(void);
void ADC_Sample(void);
signed int Cal_Temperature(uint16_t ad_value);

#endif /* __DEMO_ADC_H__ */

6、demo_epwm.c:风扇调速设置,频率为4K,占空比最小20%,最大100%,根据温度线性调整占空比,1温度值占空比步进为2%,温度越高占空比越大:

/*******************************************************************************
* Copyright (C) 2019 China Micro Semiconductor Limited Company. All Rights Reserved.
*
* This software is owned and published by:
* CMS LLC, No 2609-10, Taurus Plaza, TaoyuanRoad, NanshanDistrict, Shenzhen, China.
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with CMS
* components. This software is licensed by CMS to be adapted only
* for use in systems utilizing CMS components. CMS shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. CMS is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/

/****************************************************************************/
/** \file demo_timer.c
**
**
**
**  History:
**
*****************************************************************************/
/****************************************************************************/
/*  include files
*****************************************************************************/
#include "demo_epwm.h"

/****************************************************************************/
/*  Local pre-processor symbols('#define')
****************************************************************************/

/****************************************************************************/
/*  Global variable definitions(declared in header file with 'extern')
****************************************************************************/

/****************************************************************************/
/*  Local type definitions('typedef')
****************************************************************************/

/****************************************************************************/
/*  Local variable  definitions('static')
****************************************************************************/

/****************************************************************************/
/*  Local function prototypes('static')
****************************************************************************/

/****************************************************************************/
/*  Function implementation - global ('extern') and local('static')
****************************************************************************/


/****************************************************************************/
/*  Function implementation - global ('extern') and local('static')
****************************************************************************/

/******************************************************************************
** \brief    EPWM_Config (complementary, no dead time)
** \param [in]
**
** \return  none
** \note
******************************************************************************/
void EPWM_Config(void)
{
    //set the run mode of the EPWM
    EPWM_ConfigRunMode(EPWM_COUNT_DOWN);
    //EPWM_ConfigRunMode(EPWM_WFG_COMPLEMENTARY|EPWM_OC_INDEPENDENT|EPWM_OCU_SYMMETRIC|EPWM_COUNT_DOWN);

    //set the clock of the EPWM, using system clock
    EPWM_ConfigChannelClk(EPWM4, EPWM_CLK_DIV_1);

    //set the dudy cycle of the EPWM
    EPWM_ConfigChannelPeriod(EPWM4, PWM_PERIOD);

#if (1)
    EPWM_ConfigChannelSymDuty(EPWM4, 0x0BB8);//50% duty cycle by default, 3000
#elif (0)
    EPWM_ConfigChannelSymDuty(EPWM4, 0);
#else
    EPWM_ConfigChannelSymDuty(EPWM4, 0xFFFF);
#endif

    //set the auto-load mode
    EPWM_EnableAutoLoadMode(EPWM_CH_4_MSK);

    //set the output polarity, disable the reverse output
    EPWM_DisableReverseOutput(EPWM_CH_4_MSK);
    //EPWM_DisableReverseOutput(EPWM_CH_0_MSK|EPWM_CH_1_MSK|EPWM_CH_2_MSK|EPWM_CH_3_MSK|EPWM_CH_4_MSK|EPWM_CH_5_MSK);

    //set the output of the EPWM
    EPWM_EnableOutput(EPWM_CH_4_MSK);
    //EPWM_EnableOutput(EPWM_CH_0_MSK|EPWM_CH_1_MSK|EPWM_CH_2_MSK|EPWM_CH_3_MSK|EPWM_CH_4_MSK|EPWM_CH_5_MSK);

    //disable the dead zone
    EPWM_DisableDeadZone(EPWM4);

    EPWM_EnableZeroInt(EPWM_CH_4_MSK);              //enable the Zero interrupt of the EPWM
    EPWM_AllIntEnable();                            //enable the global interrupt of the EPWM
    IRQ_SET_PRIORITY(IRQ_PWM, IRQ_PRIORITY_HIGH);
    IRQ_ALL_ENABLE();                               //enable the global interrupt

    //set the alternate function of the GPIO
    //here we can also set other pins to the EPWM output channel
    GPIO_SET_MUX_MODE(P25CFG, GPIO_MUX_PG4);

    //start the EPWM
    EPWM_Start(EPWM_CH_4_MSK);
}

/******************************************************************************
** \brief    adjust the duty cycle of the EPWM
** \param [value]: the duty cycle of the EPWM
**
** \return  none
** \note
******************************************************************************/
void Adjust_EPWM_Duty(uint16_t value)
{
    EPWM_ConfigChannelSymDuty(EPWM4, value);
}

7、demo_epwm.h:相应的头文件

/*******************************************************************************
* Copyright (C) 2019 China Micro Semiconductor Limited Company. All Rights Reserved.
*
* This software is owned and published by:
* CMS LLC, No 2609-10, Taurus Plaza, TaoyuanRoad, NanshanDistrict, Shenzhen, China.
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with CMS
* components. This software is licensed by CMS to be adapted only
* for use in systems utilizing CMS components. CMS shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. CMS is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/

/*****************************************************************************/
/** \file demo_epwm.h
**
**
**
** History:
** -
*****************************************************************************/
#ifndef __DEMO_EPWM_H__
#define __DEMO_EPWM_H__
/*****************************************************************************/
/* Include files */
/*****************************************************************************/
#include "cms8s6990.h"
#include "main.h"

/*****************************************************************************/
/* Global pre-processor symbols/macros ('#define') */
/*****************************************************************************/
#define PWM_FREQUENCY   4000 //the frequency of the EPWM
#define PWM_PERIOD      (24000000/PWM_FREQUENCY)//24000000(system clock)*(1/4000)

#define MAX_BASE        54.0
#define T54_DUTY        (uint16_t)((54.0/MAX_BASE)*PWM_PERIOD)
#define T52_DUTY        (uint16_t)((52.0/MAX_BASE)*PWM_PERIOD)
#define T50_DUTY        (uint16_t)((50.0/MAX_BASE)*PWM_PERIOD)
#define T48_DUTY        (uint16_t)((48.0/MAX_BASE)*PWM_PERIOD)
#define T44_DUTY        (uint16_t)((44.0/MAX_BASE)*PWM_PERIOD)

/*****************************************************************************/
/* Global type definitions ('typedef') */
/*****************************************************************************/



/*****************************************************************************/
/* Global variable declarations ('extern', definition in C source) */
/*****************************************************************************/


/*****************************************************************************/
/* Global function prototypes ('extern', definition in C source) */
/*****************************************************************************/
/******************************************************************************
** \brief    EPWM_Config (complementary, no dead time)
** \param [in]
**
** \return  none
** \note
******************************************************************************/
void EPWM_Config(void);
void Adjust_EPWM_Duty(uint16_t value);

#endif /* __DEMO_EPWM_H__ */

8、isr.c:中断处理,这里主要是Timer1超时溢出处理:

/*******************************************************************************
* Copyright (C) 2019 China Micro Semiconductor Limited Company. All Rights Reserved.
*
* This software is owned and published by:
* CMS LLC, No 2609-10, Taurus Plaza, TaoyuanRoad, NanshanDistrict, Shenzhen, China.
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with CMS
* components. This software is licensed by CMS to be adapted only
* for use in systems utilizing CMS components. CMS shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. CMS is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/

/****************************************************************************/
/** \file isr.c
**
**
**
**  History:
**
*****************************************************************************/
/****************************************************************************/
/*  include files
*****************************************************************************/
#include "cms8s6990.h"
#include "demo_timer.h"
#include "main.h"

/****************************************************************************/
/*  Local pre-processor symbols('#define')
****************************************************************************/

/****************************************************************************/
/*  Global variable definitions(declared in header file with 'extern')
****************************************************************************/

/****************************************************************************/
/*  Local type definitions('typedef')
****************************************************************************/

/****************************************************************************/
/*  Local variable  definitions('static')
****************************************************************************/


/****************************************************************************/
/*  Local function prototypes('static')
****************************************************************************/


/****************************************************************************/
/*  Function implementation - global ('extern') and local('static')
****************************************************************************/


/******************************************************************************
 ** \brief   INT0 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void INT0_IRQHandler(void)  interrupt INT0_VECTOR
{

}
/******************************************************************************
 ** \brief   Timer 0 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
******************************************************************************/
void Timer0_IRQHandler(void)  interrupt TMR0_VECTOR
{
    //P24 =~P24;
}
/******************************************************************************
 ** \brief   INT0 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void INT1_IRQHandler(void)  interrupt INT1_VECTOR
{
    ;
}
/******************************************************************************
 ** \brief   Timer 1 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
******************************************************************************/
void Timer1_IRQHandler(void)  interrupt TMR1_VECTOR
{
    cFlag_1ms = 1;
    ++cDelay_10ms;
    if(++c2mS_Nct >= 2)
    {
        cFlag_2ms = 1;
        c2mS_Nct = 0;
    }
    TH1 = (65536 - TIMER_1MS) >> 8 ;
    TL1 = 65536 - TIMER_1MS;
}
/******************************************************************************
 ** \brief   UART 0 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
******************************************************************************/
void UART0_IRQHandler(void)  interrupt UART0_VECTOR
{

}
/******************************************************************************
 ** \brief   Timer 2 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
******************************************************************************/
void Timer2_IRQHandler(void)  interrupt TMR2_VECTOR
{

}
/******************************************************************************
 ** \brief   UART 1 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
******************************************************************************/
void UART1_IRQHandler(void)  interrupt UART1_VECTOR
{
    ;
}
/******************************************************************************
 ** \brief   GPIO 0 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void P0EI_IRQHandler(void)  interrupt P0EI_VECTOR
{
    //if(GPIO_GetIntFlag(GPIO0, GPIO_PIN_5))//the AC is OK
    //{
    //ac_down_cnt=0;
    //GPIO_ClearIntFlag(GPIO0, GPIO_PIN_5);
    //}
}
/******************************************************************************
 ** \brief   GPIO 1 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void P1EI_IRQHandler(void)  interrupt P1EI_VECTOR
{
    ;
}
/******************************************************************************
 ** \brief   GPIO 2 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void P2EI_IRQHandler(void)  interrupt P2EI_VECTOR
{

}
/******************************************************************************
 ** \brief   GPIO 3 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void P3EI_IRQHandler(void)  interrupt P3EI_VECTOR
{
    ;
}

/******************************************************************************
 ** \brief   LVD interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void LVD_IRQHandler(void)  interrupt LVD_VECTOR
{

}
/******************************************************************************
 ** \brief   LSE interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void LSE_IRQHandler(void)  interrupt LSE_VECTOR
{

}

/********************************************************************************
 ** \brief   ACMP interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void ACMP_IRQHandler(void)  interrupt ACMP_VECTOR
{

}
/******************************************************************************
 ** \brief   Timer 3 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
******************************************************************************/
void Timer3_IRQHandler(void)  interrupt TMR3_VECTOR
{

}
/******************************************************************************
 ** \brief   Timer 4 interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
******************************************************************************/
void Timer4_IRQHandler(void)  interrupt TMR4_VECTOR
{

}
/******************************************************************************
 ** \brief   EPWM interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void EPWM_IRQHandler(void)  interrupt EPWM_VECTOR
{
    if (EPWM_GetZeroIntFlag(EPWM4))
    {
        //P24 = ~P24;
        EPWM_ClearZeroIntFlag(EPWM4);
    }
}
/******************************************************************************
 ** \brief   ADC interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void ADC_IRQHandler(void)  interrupt ADC_VECTOR
{

}
/******************************************************************************
 ** \brief   WDT interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void WDT_IRQHandler(void)  interrupt WDT_VECTOR
{
    if (WDT_GetOverflowIntFlag())
    {
        //P24 = ~P24;
        WDT_ClearOverflowIntFlag();
    }
}
/******************************************************************************
 ** \brief  I2C interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void I2C_IRQHandler(void)  interrupt I2C_VECTOR
{
    ;
}
/******************************************************************************
 ** \brief  SPI interrupt service function
 **
 ** \param [in]  none
 **
 ** \return none
 ******************************************************************************/
void SPI_IRQHandler(void)  interrupt SPI_VECTOR
{
    ;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1150959.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实战 | SQL注入

一、资产搜集 我们都知道sql注入的传参有些是明文的&#xff0c;有些是经过编码或者加密的&#xff0c;所以我们搜索的时候不要仅限于inurl:.php?id1&#xff0c;可以额外的尝试搜搜1的base64编码值MQ&#xff0c;即可以搜索inurl:.php?idMQ&#xff0c;或者搜索1的md5加密值…

C代码的单元测试

C代码中集成gtest单元测试_gtest测试c语言_山河故人~的博客-CSDN博客 Linux安装gtest_gtest安装_山河故人~的博客-CSDN博客 一&#xff1a;安装gtest: 1. 安装gtest 采用源码安装的方式&#xff0c;需确保cmake已经安装。 git clone https://github.com/google/googletest …

网络安全(黑客)—小白自学路线

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…

商业模式画布的9大模块全解读,产品经理不可不知!

“商场如战场”&#xff0c;在当今瞬息万变的商业环境中&#xff0c;创造出独特且创新的商业模式是每个企业家、策略家和决策者的首要任务。为了在激烈的市场竞争中取得优势&#xff0c;我们需要一个强大且直观的工具来帮助我们规划和塑造公司的商业模式&#xff0c;这个经常被…

从零开始实现神经网络(一)_NN神经网络

参考文章&#xff1a;神经网络介绍 一、神经元 这一神经网络的基本单元&#xff0c;神经元接受输入&#xff0c;对它们进行一些数学运算&#xff0c;并产生一个输出。 这里有三步。 首先&#xff0c;将每个输入&#xff08;X1&#xff09;乘以一个权重&#xff1a; 接下来&…

如何备份和恢复微信聊天记录?微信聊天记录1分钟轻松备份和恢复。

微信是一个非常流行的应用程序&#xff0c;不仅在中国&#xff0c;而且在全世界。这个应用程序允许来自其他国家的用户与他们的中国朋友进行群聊、语音消息、视频通话、发送贴纸或 GIF 以及照片。它可以为学生和商人/女性发送重要文件&#xff0c;以及位置共享以防游客在访问中…

内网穿透实现在外远程访问NAS威联通(QNAP)

文章目录 前言1. 威联通安装cpolar内网穿透2. 内网穿透2.1 创建隧道2.2 测试公网远程访问 3. 配置固定二级子域名3.1 保留二级子域名3.2 配置二级子域名 4. 使用固定二级子域名远程访问 前言 购入威联通NAS后&#xff0c;很多用户对于如何在外在公网环境下的远程访问威联通NAS…

系列四十、请谈一下Spring中事务的传播行为

一、概述 事务的传播行为指的是当一个事务方法被另一个事务方法调用时&#xff0c;这个事务方法应该如何进行。事务的传播行为至少发生在两个事务方法的嵌套调用中才会出现。 二、传播行为分类

专门解决数学问题的大模型

01 项目介绍 LLEMMA&#xff1a;一个专门解决数学问题的开源大语言模型&#xff0c;能力超过所有已知的开源模型 LLEMMA由多个大学和Eleuther AI公司共同研发&#xff0c;模型能够理解和生成数学表达式、解决数学问题&#xff0c;并与其他计算工具&#xff08;如Python解释器…

Jenkins Gerrit Trigger插件配置

安装Jenkins 以Jenkins 2.361.1版本为例 docker pull jenkins/jenkins:2.361.1运行容器&#xff0c;将主机的8080端口映射到容器的8080端口&#xff0c;同时将主机的50000端口映射到容器的50000端口&#xff08;用于构建代理&#xff09; docker run -d -p 8080:8080 -p 500…

操作系统(Linux)外壳程序shell 、用户、权限

文章目录 操作系统和shell外壳Linux用户普通用户的创建和删除用户的切换 Linux 权限Linux 权限分类文件访问权限修改文件的权限权限掩码粘滞位 大家好&#xff0c;我是纪宁。 这篇文章将介绍 Linux的shell外壳程序&#xff0c;Linux用户切换机Linux权限的内容。 操作系统和shel…

基于SpringBoot的养老院信息管理系统

基于SpringBoot的养老院信息管理系统&#xff0c;java项目&#xff0c;springboot项目&#xff0c;idea都能打开运行。 推荐环境配置&#xff1a;idea jdk1.8 maven mysql5.5/mysql5.7 主要技术: SpringBoot&#xff0c;MySql&#xff0c;ajax&#xff0c;MyBatis 本系统的主要…

Vue 路由指南:畅游单页应用的地图(Vue Router 和 <router-view>)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

STM32F407的系统定时器

文章目录 系统定时器SysTick滴答定时器寄存器STK_CTRL 控制寄存器STK_LOAD 重载寄存器STK_VAL 当前值寄存器STK_CALRB 校准值寄存器 初始化 Systick 定时器SysTick_InitSysTick_CLKSourceConfig delay_us寄存器delay_us库函数delay_xms短时delay_ms长时SysTick_Config 系统定时…

电阻距离------Resistance distance

原来的解释来自维基百科&#xff1a;https://en.wikipedia.org/wiki/Resistance_distance 在图论中&#xff0c;简单连通图G的两个顶点之间的电阻距离等于电网上两个等效点之间的电阻&#xff0c;电网被构造为与G相对应&#xff0c;每条边被一欧姆的电阻代替。它是图上的度量。…

Jenkins安装(Jenkins 2.429)及安装失败解决(Jenkins 2.222.4)

敏捷开发与持续集成 敏捷开发 敏捷开发以用户的需求进化为核心&#xff0c;采用迭代、循序渐进的方法进行软件开发。在敏捷开发中&#xff0c;软件项目在构建初期被切分成多个子项目&#xff0c;各个子项目的成果都经过测试&#xff0c;具备可视、可集成和可运行使用的特征。…

geatpy-遗传算法

参考: geatpy 官网 关注的点 在实操过程中,主要遇到以下问题: 不等式约束代码里怎么写?几种书写方式之间有何细节差别要注意入门案例一 包含不等式约束 import geatpy as ea import numpy as np# 构建问题 r = 1 # 目标函数需要用到的额外数据 @ea.Problem.single def …

黑豹程序员-架构师学习路线图-百科:PowerDesigner数据库建模的行业标准

PowerDesigner最初由Xiao-Yun Wang&#xff08;王晓昀&#xff09;在SDP Technologies公司开发完成。 目前PowerDesigner是Sybase的企业建模和设计解决方案&#xff0c;采用模型驱动方法&#xff0c;将业务与IT结合起来&#xff0c;可帮助部署有效的企业体系架构&#xff0c;并…

公众号推送消息自动化的简单方法

作为公众号运营者&#xff0c;你是否厌烦了每天都要手动推送内容给用户&#xff1f;现在&#xff0c;有了乔拓云公众号助手工具&#xff0c;你可以告别手动推送的繁琐&#xff0c;实现公众号的自动推送功能。下面&#xff0c;我们来看看如何操作。 第一步&#xff1a;注册并登录…