jeff.c 发表于 2023-6-1 12:02:45

Timer0停止计数

芯片是STC8H3K64S4,30M时钟,定时器0是2mS,运行几分钟以后定时器0就停止计数了,程序和定时器0无关的部分正常运行。

定时器0是用在按键和OLED刷新,所以出现故障很明显。

但是都是,如果在循环里任意一个地方读TR0,定时器就能继续计数。
那位知道这是神马原因?

angmall 发表于 2023-6-1 12:13:39

你的程序有缺陷,你把你的代码完整地贴上来看看

jeff.c 发表于 2023-6-1 13:21:07

angmall 发表于 2023-6-1 12:13
你的程序有缺陷,你把你的代码完整地贴上来看看

/***********************************************
File Name: S500.main
Author:
Date:230525
Note:
************************************************/
#include <STC8H.H>
#include <intrins.h>
#include <stdio.h>
#include "common.h"
#include "I2C.h"
#include "OLED.h"
#include "Display.h"
#include "ScanKey.h"
#include "Config.h"
#include "NTC.c"
#include "SPWM.h"
#include "ADCaverage.h"



//回读修正
xdata float K_V = 8.338;                //AD/显示       
xdata float K_I = 108.05;                //AD/显示               
//基准输出比例
xdata float K_V_REF = 13.087;                //峰值电压基准/输出设定
xdata float K_I_REF = 169.6;                //峰值电流基准/输出设定


//全局变量
bit EN;                //开关;0:关,1:开
bit Start;                //开关机状态
bit Save;                //保存
xdata unsigned char StatusWord = 1;                //0x00:待机;0x01:正常;0x11:故障;0x12输入欠压;0x13输入过压;0x14:过热;0x15:输出欠压;0x16:输出过压;0x17:过流
xdata float Set_V = 0;        //电压设置值
xdata float Set_I = 0;        //电流设置值
xdata unsigned int Set_F = 0;        //频率设置值
unsigned int REF_V;                //电压峰值基准
unsigned int REF_I;                //电流峰值基准



xdata float Test_V = 0;        //电压测量值
xdata float Test_I = 0;        //电流测量值
xdata unsigned char Test_T = 0;        //温度测量值

unsigned int Sense_V, Sense_I, Sense_T, Sense_B, Sense_BUS;                //AD采样值

unsigned long SamplingV;                //电压长采样值
unsigned long SamplingI;                //电流长采样值
unsigned int SamplingCountV;                //电压长采样计数
unsigned int SamplingCountI;                //电流长采样计数
//bit SamplingNewV;                //电压长采样更新
//bit SamplingNewI;                //电流长采样更新
//bit ADC_Busy;
xdata unsigned char inquireCount = 0;                //查询定时

bit IS_OK;                //浪涌抑制完成

//PWM部分
bit PWM_EN;                //PWM启动
bit SoftStart = 1;                //软启动标识,1:需要软启动;0:软启动完成
unsigned char M;                //调制

//保护
bit IN_O;                //输入过压
bit IN_U;                //输入欠压
bit OverV;                //输出过压
bit OverU;                //输出欠压
bit OverI;                //输出过流
bit OverC;                //输出短路
bit OverT;                //过热
xdata unsigned int OverTime;                //过流事件|过流计时
xdata unsigned int OverTimeMemory;                //过流事件|过流计时
xdata unsigned int OverRecover;
bit ErrNew;
bit busy;

//显示部分
xdata char Str_Set_V = {'0', '0', '0', '0', '0', '\0'};
xdata char Str_Set_I = {'0', '0', '0', '0', '0', '\0'};
xdata char Str_Set_F = {'0', '0', '0', '0', '0', '\0'};
xdata char Str_V = {'0', '0', '0', '0', '0', '\0'};
xdata char Str_I = {'0', '0', '0', '0', '0', '\0'};
xdata char Str_F = {'0', '0', '0', '0', '0', '\0'};
xdata unsigned char Display_cls1 = 0, Display_cls2 = 0, Display_cls3 = 0;
xdata unsigned char Display_clsrst = 0;



void CLK_Init(void)
{       
        XOSCCR = 0xc8;                //启动外部晶振       
        while (!(XOSCCR & 1));                //等待时钟稳定
        CLKDIV = 0x00;                //时钟不分频
        CLKSEL = 0x01;                //选择外部高速晶振
}

void GPIO_Init(void)
{
        P0M1 = 0xFD; P0M0 = 0x02; //P0(高高高高高高推高)
        P1M1 = 0xBF; P1M0 = 0x40; //P1(高推高高高高高高)
        P2M1 = 0x00; P2M0 = 0xF3; //P2(推推推推双双推推)
        P3M1 = 0xFD; P3M0 = 0x0E; //P3(高高高高开开推高)
        P4M1 = 0xEB; P4M0 = 0x14; //P4(高高高推高推高高)
        P5M1 = 0xFF; P5M0 = 0x00; //P5(高高高高高高高高)
       
        P01 = 1;
        P20 = 0;
        P21 = 0;
        P24 = 0;
        P25 = 0;
        P26 = 0;
        P27 = 0;
        P42 = 0;
}

void WDTInit(void)
{
        WDT_CONTR |= 0x05;                //配置看门狗定时器 1.26S@20M
        WDT_CONTR |= 0x10;
        WDT_CONTR |= 0x20;       
}

void Timer1Init(void)                //5毫秒@30.000MHz
{
        AUXR &= 0xBF;                //定时器时钟12T模式
        TMOD &= 0x0F;                //设置定时器模式
        TL1 = 0x2C;                //设置定时初始值
        TH1 = 0xCF;                //设置定时初始值
        TF1 = 0;                //清除TF1标志
        ET1 = 1;                //允许中断
        TR1 = 0;                //定时器1开始计时
}


void Config()
{
        REF_V = (unsigned int)(Set_V * K_V_REF);
        REF_I = (unsigned int)(Set_I * K_I_REF);
        PWMA_ARR = MainClock/Element/Set_F+0.5;
        MiddleValue = (PWMA_ARR/2)+0.5;
}

void Change()
{
        xdata unsigned char str;
        if(Direction != 0)
        {
                if(CursorPosition == 0)
                {
                        if(Direction == 1)
                        {
                                if(Set_V <= S_O_V_H - 0.1) Set_V +=0.1;
                        }
                        if(Direction == 2)
                        {
                                if(Set_V >= S_O_V_L + 0.1) Set_V -=0.1;
                        }
                        if(Direction == 10)
                        {
                                if(Set_V <= S_O_V_H - 1) Set_V +=1;
                        }
                        if(Direction == 20)
                        {
                                if(Set_V >= S_O_V_L + 1) Set_V -=1;
                        }
                        REF_V = (unsigned int)(Set_V * K_V_REF);
                        sprintf(str, "%5.1f", Set_V);
                        //str = '\0';
                        Display_cls1 = 1;
                        Display_cls2 = 0;
                        Display_cls3 = 0;
                        OLED_P6x8Str_R(68,5,str);
                }
                if(CursorPosition == 1)
                {
                        if(Direction == 1)
                        {
                                if(Set_I <= S_O_I_H - 0.1) Set_I +=0.1;
                        }
                        if(Direction == 2)
                        {
                                if(Set_I >= S_O_I_L + 0.1) Set_I -=0.1;
                        }
                        if(Direction == 10)
                        {
                                if(Set_I <= S_O_I_H - 1) Set_I +=1;
                        }
                        if(Direction == 20)
                        {
                                if(Set_I >= S_O_I_L + 1) Set_I -=1;
                        }
                        sprintf(str, "%5.2f", Set_I);
                        REF_I = (unsigned int)(Set_I * K_I_REF);
                        //str = '\0';
                        Display_cls1 = 0;
                        Display_cls2 = 1;
                        Display_cls3 = 0;
                        OLED_P6x8Str_R(68,6,str);
                }
                if(CursorPosition == 2)
                {
                        if(Direction == 1)
                        {
                                if(Set_F <= S_O_F_H - 1) Set_F +=1;
                        }
                        if(Direction == 2)
                        {
                                if(Set_F >= S_O_F_L + 1) Set_F -=1;
                        }
                        if(Direction == 10)
                        {
                                if(Set_F <= S_O_F_H - 10) Set_F +=10;
                        }
                        if(Direction == 20)
                        {
                                if(Set_F >= S_O_F_L + 10) Set_F -=10;
                        }
                        PWMA_ARR = MainClock/Element/Set_F+0.5;
                        MiddleValue = (PWMA_ARR/2)+0.5;
                        str = Set_F/100+48;
                        str = Set_F/10%10+48;
                        str = Set_F%10+48;
                        str = '\0';
                        Display_cls1 = 0;
                        Display_cls2 = 0;
                        Display_cls3 = 1;
                        OLED_P6x8Str_R(80,7,str);
                }
                Direction = 0;
        }
}

//刷新
void Display_Refresh()
{
        xdata unsigned char i;
        xdata unsigned char str;
       
        ET0 = 0;
       
        //Change();
        if(Refresh_Count > 250)
        {               
                Refresh_Count = 0;
                if((Display_cls1 == 1) || (Display_cls2 == 1) || (Display_cls3 == 1))
                {
                        if(Direction == 0) Display_clsrst++;
                        if(Display_clsrst > 10)
                        {
                                Display_cls1 = 0;
                                Display_cls2 = 0;
                                Display_cls3 = 0;
                                Display_clsrst = 0;
                                //save
                        }
                }
               
                sprintf(str, "%5.1f", Test_V);
                for(i=0; i<6; i++)
                {
                        Str_V = str;
                }
               
                sprintf(str, "%5.2f", Test_I);
                for(i=0; i<6; i++)
                {
                        Str_I = str;
                }               

                if(StatusWord == 0x01)
                {
                        Str_F = Set_F/100+48;
                        Str_F = Set_F/10%10+48;
                        Str_F = Set_F%10+48;
                        Str_F = '\0';
                }
                else
                {
                        Str_F = '0';
                        Str_F = '0';
                        Str_F = '0';
                        Str_F = '\0';
                }
               
                Display_Cursor(CursorPosition);                //更新光标位置
                Display_Fill1(StatusWord);
                if(Display_cls1 == 0) Display_Fill(4, Str_V);
                if(Display_cls2 == 0) Display_Fill(5, Str_I);
                if(Display_cls3 == 0) Display_Fill(6, Str_F);               
                       
                       
                //OLED_Display_16bit_number(68,3,Test_T-40);                //test
                OLED_Display_16bit_number(68,3,PWMA_ARR);                //test
        }       
        ET0 = 1;
}

void ONOFF()
{
        //开机过程               
        if((EN) && (IS_OK))                //开机
        {
                Start = 1;
        }
        else
        {
                Start = 0;
        }
       
        if(Start)
        {
                PWM_EN = 1;       
        }
        else
        {
                M = 0;
                PWM_EN = 0;
                SoftStart = 1;
        }
       
        if((PWM_EN == 1) && (SoftStart == 1))                //软启动
        {
                TR1 = 1;                //定时器1计时控制
        }
}



//定时器1中断
void timer1_isr() interrupt 3                //软起动&保护
{
       
        //软启动
        if((PWM_EN == 1) && (SoftStart == 1))               
        {
                M++;
                if(M >= Level-20)
                {
                        SoftStart = 0;
                }
               
                //Sense_V = Absolute(Get_ADC(0x01), Get_ADC(0x00));
                if(Sense_V >= REF_V - 50)
                {                               
                        SoftStart = 0;
                }
        }
       
        //温度查询
        inquireCount++;
        if(inquireCount > 100)
        {
                xdata unsigned char i;
                inquireCount = 0;
                Sense_T = ADCaverage(0x02);
                if(Sense_T < 6)
                {
                        Test_T = 254;
                }

                if(Sense_T > 3104)
                {
                        Test_T = 255;
                }

                for(i=0;i<160;i++)
                {
                        if(NTCV >= Sense_T)
                        {
                                Test_T = i;
                                break;
                        }
                }
        }
}

unsigned int Absolute(unsigned int a, unsigned int b)
{
        unsigned int c;
        if(a >= b)
        {
                c = a - b;
        }
        else
        {
                c = b - a;
        }
        return (c);
}

void inquire()
{
        Sense_B = ADCaverage(0x0c);
        Sense_BUS = ADCaverage(0x0b);
}

void Sampling()                //20uS
{
       
}
void status()
{
//bit IN_O;                //输入过压
//bit IN_U;                //输入欠压
//bit OverV;                //输出过压
//bit OverU;                //输出欠压
//bit OverI;                //输出过流
//bit OverC;                //输出短路
//bit OverT;                //过热
}

void PID()                //12bit:23uS/45uS
{
        unsigned char Factor = 15;                //比例系数
        unsigned int Diffe;                //差值
        bit Direction;                //差值方向
        unsigned int P;                //增量
       
        if(SinPeak)
        {
                SinPeak = 0;
                Sense_V = Absolute(Get_ADC1(0x01), Get_ADC1(0x00));

                if(Sense_V >= REF_V)
                {
                        Diffe = Sense_V - REF_V;
                        Direction = 1;
                        SoftStart = 0;
                }
                else
                {
                        Diffe = REF_V - Sense_V;
                        Direction = 0;
                }
               
                P = Diffe / Factor;                //P
               
                if(!SoftStart)
                {
                        if(Direction)
                        {
                                M = M - P;
                        }
                        else
                        {
                                M = M + P;
                        }
                }
               
                //
                if(M <= 0)
                {
                        M = 0;
                }
                if(M >= Level)
                {
                        M = Level - 1;
                }
               
                //电压长采样
                SamplingV += Sense_V;
                SamplingCountV++;
                if(SamplingCountV >= (Element - 1))
                {
                        Test_V = (float)(SamplingV / SamplingCountV) / K_V;
                        SamplingV = 0;
                        SamplingCountV = 0;
                                               
                        //SamplingNewV = 1;
                }
                //电流长采样
                Sense_I = Absolute(Get_ADC1(0x0e), Get_ADC1(0x0d));
                SamplingI += Sense_I;
                SamplingCountI++;
                if(SamplingCountI >= (Element - 1))
                {
                        Test_I = (SamplingI / SamplingCountI) / K_I;
                        SamplingI = 0;
                        SamplingCountI = 0;
                                               
                        //SamplingNewV = 1;
                }
               
        }       
       
}

void ADC_Isr() interrupt 5
{
       
        ADC_CONTR &= ~0x20;         //清中断标志       
        EA = 1;       
        TR0 = 1;                //定时器0开始计时
        EADC = 0;                //使能ADC中断               
        PID();       
}

void main()
{
        P_SW2 |= 0x80;         //使能访问 XFR       
        CLK_Init();
        GPIO_Init();
        ADCInit();
        ConfigRead();
        PWM_Init();
        Config();
        I2C_Init();
        OLED_Init();
        //Display_Start();
        Display_Frame();
        Timer0Init();
        Timer1Init();
       
        //OLED_Display_16bit_number(68,3,REF_I);
        EN = 1;       
        IS_OK = 1;
        M = 98;
///////////////////////
       
       
        IP = 0x10;
        IPH = 0x20;
        IP2 = 0x04;
        IP2H = 0x04;
        EA = 1;
        Change();
        while(1)
        {
                Change();
                ONOFF();
                Display_Refresh();
               

               
               
                if(Save == 1)
                {
                        Save = 0;
                        OLED_P8x16Str(68,3,"Save...");
                        ConfigWrite();
                        OLED_P8x16Str(68,3,"       ");
                }
               
                //P26 = TR0;
               
        ///////////////////////////////////////////////////////
        WDT_CONTR |= 0x10;
        }

}

jeff.c 发表于 2023-6-1 13:25:42

angmall 发表于 2023-6-1 12:13
你的程序有缺陷,你把你的代码完整地贴上来看看

目前已知:ADC中断如果不开启中断嵌套(494行)就不会导致这个问题

梁工 发表于 2023-6-1 13:54:03

jeff.c 发表于 2023-6-1 13:25
目前已知:ADC中断如果不开启中断嵌套(494行)就不会导致这个问题

那估计你的中断程序有问题,仔细检查。

32G12K128 发表于 2023-6-1 16:02:14


用这个范例试下:

angmall 发表于 2023-6-1 16:10:37

没有看见这个程序 Timer0Init();

jeff.c 发表于 2023-6-1 16:23:47

STC32G12K128 发表于 2023-6-1 16:02
用这个范例试下:

是的,平时都是用STCISP工具配置的定时器
void Timer0Init(void)                //2毫秒@30.000MHz
{
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
//        TL0 = 0x3C;                //设置定时初始值                //1mS
//        TH0 = 0xF6;                //设置定时初始值
        TL0 = 0x78;                //设置定时初始值                //2mS
        TH0 = 0xEC;                //设置定时初始值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
        ET0 = 1;
        //IP &= 0xfd;
        //IPH &= 0xfd;
}

angmall 发表于 2023-6-1 16:34:47

那估计你的ADC中断程序运行超过两毫秒。你需要调整一下。

pingfr 发表于 2023-6-2 11:40:13

本帖最后由 pingfr 于 2023-6-2 11:41 编辑

我的STC32G12K也遇到类似问题,开timer0中断后进入一次就再也不进了,配置也没啥特殊的
页: [1] 2
查看完整版本: Timer0停止计数