中微CMS8S3680/69xx系列单片机

最近在使用中微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
{
    ;
}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值