/*******************************************************
*Copyright(C),2020,Shanghai Eastsoft Microelectronics Co.,Ltd.
*文件名：capture_pwm_input.c
*作  者：AE Team
*版  本：v1.0，编译于iDesigner(v4.2.3.166) + 工具链HRCC(v1.2.0.106)
*日  期：2020/07/23
*描  述：多功能定时器pwm输入捕捉模式，T31_CH1(PB5)输入波形，调试状态下全速运行程序后暂停，
        可以直接查看波形的周期长度和占空比长度
        注意：若程序在调试状态下暂停运行，由于pwm仍在输入且捕捉功能依然有效，T31CH1R和T31CH2R仍会更新。所以
        程序暂停时若程序计数器停止在捕捉中断函数中则有可能得到不正确的Period和Duty。用户可尝试将断点打在捕捉1中断
        函数中的不同语句上实际查看Period、Duty、T31CH1R、T31CH2R的值体验一下。程序全速运行时不受影响。
        建议：设置合理的预分频，最好保证pwm周期小于计数器溢出周期。
*备  注：本软件仅供学习和演示使用，对用户直接引用代码所带来的风险或后果不承担任何法律责任。
*******************************************************/
#include <hic.h>

#define CLRWDT()   {__Asm CWDT;}        //宏定义清狗指令

unsigned int Period, Duty;       //保存pwm输入的波形周期和占空比

/******************************************************
函数名：void RAMclear(void)
描  述：RAM区数据清零，RAM区地址0x0000~0x03FF
输入值：无
输出值：无
返回值：无
*******************************************************/
void RAMclear(void)
{
    for (IAAH = 0; IAAH <= 0x03; IAAH++)
    {
        for (IAAL = 0; IAAL < 0xFF; IAAL++)
            IAD = 0x00;

        IAD = 0x00;
    }
}

/******************************************************
函数名：void GPIOInit(void)
描  述：首先初始化所有未用到的IO口为输出低电平
输入值：无
输出值：无
返回值：无
*******************************************************/
void GPIOInit(void)
{
    ANSL = 0xFF;        //选择对应端口为数字IO功能
    ANSH = 0xFF;
    PAT = 0x00;         //所有IO设为输出低电平
    PBT = 0x00;
    PCT = 0x00;
    PA = 0x00;
    PB = 0x00;
    PC = 0x00;

    PBT5 = 1;           //T31_CH1设为输入
    //PBPU5 = 1;          //使能上拉
}

/*******************************************************
函数名：void isr(void) interrupt
描  述：中断服务程序，两次捕捉1中断表示一个pwm周期的长度
输入值：无
输出值：无
返回值：无
*******************************************************/
void isr(void) interrupt
{
    if (MIS1 == 1 && MIF1 == 1)   //捕捉1中断
    {
        MIC1 = 1;       //清捕捉1中断标志
        T31IF = 0;      //清定时器总标志位

        Period = T31CH1RH;        //保存捕捉事件时计数器的值
        Period = (Period << 8) | T31CH1RL;
        Duty = T31CH2RH;          //保存捕捉事件时计数器的值
        Duty = (Duty << 8) | T31CH2RL;
    }
}

/*******************************************************
函数名：void main(void)
描  述：主函数，pwm输入模式，两个捕捉通道映射到一个输入口T31_CH1(PB5)，由T31_CH1(PB5)输入波形。
        通道1捕捉上升沿成功时将计数器的值复制到T31CH1R，并复位计数器重新从0开始计数，通道2捕捉
        下降沿成功时将计数器的值复制到T31CH2R。则在一个pwm周期，T31CH1R保存PWM的长度，T31CH2R保存PWM占空比长度
输入值：无
输出值：无
返回值：无
*******************************************************/
void main(void)
{
    RAMclear();
    GPIOInit();
    T31PRSH = 0x00;       //预分频系数1:16
    T31PRSL = 0x0F;
    T31CH2C = 0x02;       //T31_CH1作为通道2的捕捉管脚，无滤波，无预分频
    T31CH1C = 0x01;       //T31_CH1作为通道1的捕捉管脚，无滤波，无预分频
    T31PINCL = 0x20;      //通道2下降沿有效，通道1上升沿有效
    T31C2L = 0x54;        //选择通道1为触发输入(TRGI)，上升沿重新初始化计数器
    CH2E = 1;       //使能通道2捕捉
    CH1E = 1;       //使能通道1捕捉
    MIE1 = 1;       //使能通道1捕捉中断
    T31IE = 1;      //开启多功能定时器中断
    MIC1 = 1;       //清捕捉1中断标志
    T31IF = 0;      //清定时器总标志位
    GIE = 1;        //开全局中断
    T31EN = 1;      //使能计数器

    while (1)
    {
        CLRWDT();
    }
}