Timer0停止计数
芯片是STC8H3K64S4,30M时钟,定时器0是2mS,运行几分钟以后定时器0就停止计数了,程序和定时器0无关的部分正常运行。定时器0是用在按键和OLED刷新,所以出现故障很明显。
但是都是,如果在循环里任意一个地方读TR0,定时器就能继续计数。
那位知道这是神马原因?
你的程序有缺陷,你把你的代码完整地贴上来看看 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;
}
} angmall 发表于 2023-6-1 12:13
你的程序有缺陷,你把你的代码完整地贴上来看看
目前已知:ADC中断如果不开启中断嵌套(494行)就不会导致这个问题 jeff.c 发表于 2023-6-1 13:25
目前已知:ADC中断如果不开启中断嵌套(494行)就不会导致这个问题
那估计你的中断程序有问题,仔细检查。
用这个范例试下:
没有看见这个程序 Timer0Init(); 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;
} 那估计你的ADC中断程序运行超过两毫秒。你需要调整一下。 本帖最后由 pingfr 于 2023-6-2 11:41 编辑
我的STC32G12K也遇到类似问题,开timer0中断后进入一次就再也不进了,配置也没啥特殊的
页:
[1]
2