找回密码
 立即注册
查看: 1282|回复: 10

Timer0停止计数

[复制链接]

1

主题

3

回帖

23

积分

新手上路

积分
23
发表于 2023-6-1 12:02:45 | 显示全部楼层 |阅读模式
芯片是STC8H3K64S4,30M时钟,定时器0是2mS,运行几分钟以后定时器0就停止计数了,程序和定时器0无关的部分正常运行。

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

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:522
  • 最近打卡:2025-05-02 00:29:54

10

主题

1159

回帖

5121

积分

论坛元老

积分
5121
发表于 2023-6-1 12:13:39 | 显示全部楼层
你的程序有缺陷,你把你的代码完整地贴上来看看
回复 支持 反对

使用道具 举报 送花

1

主题

3

回帖

23

积分

新手上路

积分
23
发表于 2023-6-1 13:21:07 | 显示全部楼层
angm*** 发表于 2023-6-1 12:13
你的程序有缺陷,你把你的代码完整地贴上来看看
  1. /***********************************************
  2. File Name: S500.main
  3. Author:
  4. Date:230525
  5. Note:
  6. ************************************************/
  7. #include <STC8H.H>
  8. #include <intrins.h>
  9. #include <stdio.h>
  10. #include "common.h"
  11. #include "I2C.h"
  12. #include "OLED.h"
  13. #include "Display.h"
  14. #include "ScanKey.h"
  15. #include "Config.h"
  16. #include "NTC.c"
  17. #include "SPWM.h"
  18. #include "ADCaverage.h"
  19. //回读修正
  20. xdata float K_V = 8.338;                //AD/显示       
  21. xdata float K_I = 108.05;                //AD/显示               
  22. //基准输出比例
  23. xdata float K_V_REF = 13.087;                //峰值电压基准/输出设定
  24. xdata float K_I_REF = 169.6;                //峰值电流基准/输出设定
  25. //全局变量
  26. bit EN;                //开关;0:关,1:开
  27. bit Start;                //开关机状态
  28. bit Save;                //保存
  29. xdata unsigned char StatusWord = 1;                //0x00:待机;0x01:正常;0x11:故障;0x12输入欠压;0x13输入过压;0x14:过热;0x15:输出欠压;0x16:输出过压;0x17:过流
  30. xdata float Set_V = 0;        //电压设置值
  31. xdata float Set_I = 0;        //电流设置值
  32. xdata unsigned int Set_F = 0;        //频率设置值
  33. unsigned int REF_V;                //电压峰值基准
  34. unsigned int REF_I;                //电流峰值基准
  35. xdata float Test_V = 0;        //电压测量值
  36. xdata float Test_I = 0;        //电流测量值
  37. xdata unsigned char Test_T = 0;        //温度测量值
  38. unsigned int Sense_V, Sense_I, Sense_T, Sense_B, Sense_BUS;                //AD采样值
  39. unsigned long SamplingV;                //电压长采样值
  40. unsigned long SamplingI;                //电流长采样值
  41. unsigned int SamplingCountV;                //电压长采样计数
  42. unsigned int SamplingCountI;                //电流长采样计数
  43. //bit SamplingNewV;                //电压长采样更新
  44. //bit SamplingNewI;                //电流长采样更新
  45. //bit ADC_Busy;
  46. xdata unsigned char inquireCount = 0;                //查询定时
  47. bit IS_OK;                //浪涌抑制完成
  48. //PWM部分
  49. bit PWM_EN;                //PWM启动
  50. bit SoftStart = 1;                //软启动标识,1:需要软启动;0:软启动完成
  51. unsigned char M;                //调制
  52. //保护
  53. bit IN_O;                //输入过压
  54. bit IN_U;                //输入欠压
  55. bit OverV;                //输出过压
  56. bit OverU;                //输出欠压
  57. bit OverI;                //输出过流
  58. bit OverC;                //输出短路
  59. bit OverT;                //过热
  60. xdata unsigned int OverTime;                //过流事件|过流计时
  61. xdata unsigned int OverTimeMemory;                //过流事件|过流计时
  62. xdata unsigned int OverRecover;
  63. bit ErrNew;
  64. bit busy;
  65. //显示部分
  66. xdata char Str_Set_V[6] = {'0', '0', '0', '0', '0', '\0'};
  67. xdata char Str_Set_I[6] = {'0', '0', '0', '0', '0', '\0'};
  68. xdata char Str_Set_F[6] = {'0', '0', '0', '0', '0', '\0'};
  69. xdata char Str_V[6] = {'0', '0', '0', '0', '0', '\0'};
  70. xdata char Str_I[6] = {'0', '0', '0', '0', '0', '\0'};
  71. xdata char Str_F[6] = {'0', '0', '0', '0', '0', '\0'};
  72. xdata unsigned char Display_cls1 = 0, Display_cls2 = 0, Display_cls3 = 0;
  73. xdata unsigned char Display_clsrst = 0;
  74. void CLK_Init(void)
  75. {       
  76.         XOSCCR = 0xc8;                //启动外部晶振       
  77.         while (!(XOSCCR & 1));                //等待时钟稳定
  78.         CLKDIV = 0x00;                //时钟不分频
  79.         CLKSEL = 0x01;                //选择外部高速晶振
  80. }
  81. void GPIO_Init(void)
  82. {
  83.         P0M1 = 0xFD; P0M0 = 0x02; //P0(高高高高高高推高)
  84.         P1M1 = 0xBF; P1M0 = 0x40; //P1(高推高高高高高高)
  85.         P2M1 = 0x00; P2M0 = 0xF3; //P2(推推推推双双推推)
  86.         P3M1 = 0xFD; P3M0 = 0x0E; //P3(高高高高开开推高)
  87.         P4M1 = 0xEB; P4M0 = 0x14; //P4(高高高推高推高高)
  88.         P5M1 = 0xFF; P5M0 = 0x00; //P5(高高高高高高高高)
  89.        
  90.         P01 = 1;
  91.         P20 = 0;
  92.         P21 = 0;
  93.         P24 = 0;
  94.         P25 = 0;
  95.         P26 = 0;
  96.         P27 = 0;
  97.         P42 = 0;
  98. }
  99. void WDTInit(void)
  100. {
  101.         WDT_CONTR |= 0x05;                //配置看门狗定时器 1.26S@20M
  102.         WDT_CONTR |= 0x10;
  103.         WDT_CONTR |= 0x20;       
  104. }
  105. void Timer1Init(void)                //5毫秒@30.000MHz
  106. {
  107.         AUXR &= 0xBF;                //定时器时钟12T模式
  108.         TMOD &= 0x0F;                //设置定时器模式
  109.         TL1 = 0x2C;                //设置定时初始值
  110.         TH1 = 0xCF;                //设置定时初始值
  111.         TF1 = 0;                //清除TF1标志
  112.         ET1 = 1;                //允许中断
  113.         TR1 = 0;                //定时器1开始计时
  114. }
  115. void Config()
  116. {
  117.         REF_V = (unsigned int)(Set_V * K_V_REF);
  118.         REF_I = (unsigned int)(Set_I * K_I_REF);
  119.         PWMA_ARR = MainClock/Element/Set_F+0.5;
  120.         MiddleValue = (PWMA_ARR/2)+0.5;
  121. }
  122. void Change()
  123. {
  124.         xdata unsigned char str[7];
  125.         if(Direction != 0)
  126.         {
  127.                 if(CursorPosition == 0)
  128.                 {
  129.                         if(Direction == 1)
  130.                         {
  131.                                 if(Set_V <= S_O_V_H - 0.1) Set_V +=0.1;
  132.                         }
  133.                         if(Direction == 2)
  134.                         {
  135.                                 if(Set_V >= S_O_V_L + 0.1) Set_V -=0.1;
  136.                         }
  137.                         if(Direction == 10)
  138.                         {
  139.                                 if(Set_V <= S_O_V_H - 1) Set_V +=1;
  140.                         }
  141.                         if(Direction == 20)
  142.                         {
  143.                                 if(Set_V >= S_O_V_L + 1) Set_V -=1;
  144.                         }
  145.                         REF_V = (unsigned int)(Set_V * K_V_REF);
  146.                         sprintf(str, "%5.1f", Set_V);
  147.                         //str[5] = '\0';
  148.                         Display_cls1 = 1;
  149.                         Display_cls2 = 0;
  150.                         Display_cls3 = 0;
  151.                         OLED_P6x8Str_R(68,5,str);
  152.                 }
  153.                 if(CursorPosition == 1)
  154.                 {
  155.                         if(Direction == 1)
  156.                         {
  157.                                 if(Set_I <= S_O_I_H - 0.1) Set_I +=0.1;
  158.                         }
  159.                         if(Direction == 2)
  160.                         {
  161.                                 if(Set_I >= S_O_I_L + 0.1) Set_I -=0.1;
  162.                         }
  163.                         if(Direction == 10)
  164.                         {
  165.                                 if(Set_I <= S_O_I_H - 1) Set_I +=1;
  166.                         }
  167.                         if(Direction == 20)
  168.                         {
  169.                                 if(Set_I >= S_O_I_L + 1) Set_I -=1;
  170.                         }
  171.                         sprintf(str, "%5.2f", Set_I);
  172.                         REF_I = (unsigned int)(Set_I * K_I_REF);
  173.                         //str[5] = '\0';
  174.                         Display_cls1 = 0;
  175.                         Display_cls2 = 1;
  176.                         Display_cls3 = 0;
  177.                         OLED_P6x8Str_R(68,6,str);
  178.                 }
  179.                 if(CursorPosition == 2)
  180.                 {
  181.                         if(Direction == 1)
  182.                         {
  183.                                 if(Set_F <= S_O_F_H - 1) Set_F +=1;
  184.                         }
  185.                         if(Direction == 2)
  186.                         {
  187.                                 if(Set_F >= S_O_F_L + 1) Set_F -=1;
  188.                         }
  189.                         if(Direction == 10)
  190.                         {
  191.                                 if(Set_F <= S_O_F_H - 10) Set_F +=10;
  192.                         }
  193.                         if(Direction == 20)
  194.                         {
  195.                                 if(Set_F >= S_O_F_L + 10) Set_F -=10;
  196.                         }
  197.                         PWMA_ARR = MainClock/Element/Set_F+0.5;
  198.                         MiddleValue = (PWMA_ARR/2)+0.5;
  199.                         str[0] = Set_F/100+48;
  200.                         str[1] = Set_F/10%10+48;
  201.                         str[2] = Set_F%10+48;
  202.                         str[3] = '\0';
  203.                         Display_cls1 = 0;
  204.                         Display_cls2 = 0;
  205.                         Display_cls3 = 1;
  206.                         OLED_P6x8Str_R(80,7,str);
  207.                 }
  208.                 Direction = 0;
  209.         }
  210. }
  211. //刷新
  212. void Display_Refresh()
  213. {
  214.         xdata unsigned char i;
  215.         xdata unsigned char str[7];
  216.        
  217.         ET0 = 0;
  218.        
  219.         //Change();
  220.         if(Refresh_Count > 250)
  221.         {               
  222.                 Refresh_Count = 0;
  223.                 if((Display_cls1 == 1) || (Display_cls2 == 1) || (Display_cls3 == 1))
  224.                 {
  225.                         if(Direction == 0) Display_clsrst++;
  226.                         if(Display_clsrst > 10)
  227.                         {
  228.                                 Display_cls1 = 0;
  229.                                 Display_cls2 = 0;
  230.                                 Display_cls3 = 0;
  231.                                 Display_clsrst = 0;
  232.                                 //save
  233.                         }
  234.                 }
  235.                
  236.                 sprintf(str, "%5.1f", Test_V);
  237.                 for(i=0; i<6; i++)
  238.                 {
  239.                         Str_V[i] = str[i];
  240.                 }
  241.                
  242.                 sprintf(str, "%5.2f", Test_I);
  243.                 for(i=0; i<6; i++)
  244.                 {
  245.                         Str_I[i] = str[i];
  246.                 }               
  247.                 if(StatusWord == 0x01)
  248.                 {
  249.                         Str_F[0] = Set_F/100+48;
  250.                         Str_F[1] = Set_F/10%10+48;
  251.                         Str_F[2] = Set_F%10+48;
  252.                         Str_F[3] = '\0';
  253.                 }
  254.                 else
  255.                 {
  256.                         Str_F[0] = '0';
  257.                         Str_F[1] = '0';
  258.                         Str_F[2] = '0';
  259.                         Str_F[3] = '\0';
  260.                 }
  261.                
  262.                 Display_Cursor(CursorPosition);                //更新光标位置
  263.                 Display_Fill1(StatusWord);
  264.                 if(Display_cls1 == 0) Display_Fill(4, Str_V);
  265.                 if(Display_cls2 == 0) Display_Fill(5, Str_I);
  266.                 if(Display_cls3 == 0) Display_Fill(6, Str_F);               
  267.                        
  268.                        
  269.                 //OLED_Display_16bit_number(68,3,Test_T-40);                //test
  270.                 OLED_Display_16bit_number(68,3,PWMA_ARR);                //test
  271.         }       
  272.         ET0 = 1;
  273. }
  274. void ONOFF()
  275. {
  276.         //开机过程               
  277.         if((EN) && (IS_OK))                //开机
  278.         {
  279.                 Start = 1;
  280.         }
  281.         else
  282.         {
  283.                 Start = 0;
  284.         }
  285.        
  286.         if(Start)
  287.         {
  288.                 PWM_EN = 1;       
  289.         }
  290.         else
  291.         {
  292.                 M = 0;
  293.                 PWM_EN = 0;
  294.                 SoftStart = 1;
  295.         }
  296.        
  297.         if((PWM_EN == 1) && (SoftStart == 1))                //软启动
  298.         {
  299.                 TR1 = 1;                //定时器1计时控制
  300.         }
  301. }
  302. //定时器1中断
  303. void timer1_isr() interrupt 3                //软起动&保护
  304. {
  305.        
  306.         //软启动
  307.         if((PWM_EN == 1) && (SoftStart == 1))               
  308.         {
  309.                 M++;
  310.                 if(M >= Level-20)
  311.                 {
  312.                         SoftStart = 0;
  313.                 }
  314.                
  315.                 //Sense_V = Absolute(Get_ADC(0x01), Get_ADC(0x00));
  316.                 if(Sense_V >= REF_V - 50)
  317.                 {                               
  318.                         SoftStart = 0;
  319.                 }
  320.         }
  321.        
  322.         //温度查询
  323.         inquireCount++;
  324.         if(inquireCount > 100)
  325.         {
  326.                 xdata unsigned char i;
  327.                 inquireCount = 0;
  328.                 Sense_T = ADCaverage(0x02);
  329.                 if(Sense_T < 6)
  330.                 {
  331.                         Test_T = 254;
  332.                 }
  333.                 if(Sense_T > 3104)
  334.                 {
  335.                         Test_T = 255;
  336.                 }
  337.                 for(i=0;i<160;i++)
  338.                 {
  339.                         if(NTCV[i] >= Sense_T)
  340.                         {
  341.                                 Test_T = i;
  342.                                 break;
  343.                         }
  344.                 }
  345.         }
  346. }
  347. unsigned int Absolute(unsigned int a, unsigned int b)
  348. {
  349.         unsigned int c;
  350.         if(a >= b)
  351.         {
  352.                 c = a - b;
  353.         }
  354.         else
  355.         {
  356.                 c = b - a;
  357.         }
  358.         return (c);
  359. }
  360. void inquire()
  361. {
  362.         Sense_B = ADCaverage(0x0c);
  363.         Sense_BUS = ADCaverage(0x0b);
  364. }
  365. void Sampling()                //20uS
  366. {
  367.        
  368. }
  369. void status()
  370. {
  371. //bit IN_O;                //输入过压
  372. //bit IN_U;                //输入欠压
  373. //bit OverV;                //输出过压
  374. //bit OverU;                //输出欠压
  375. //bit OverI;                //输出过流
  376. //bit OverC;                //输出短路
  377. //bit OverT;                //过热
  378. }
  379. void PID()                //12bit:23uS/45uS
  380. {
  381.         unsigned char Factor = 15;                //比例系数
  382.         unsigned int Diffe;                //差值
  383.         bit Direction;                //差值方向
  384.         unsigned int P;                //增量
  385.        
  386.         if(SinPeak)
  387.         {
  388.                 SinPeak = 0;
  389.                 Sense_V = Absolute(Get_ADC1(0x01), Get_ADC1(0x00));
  390.                 if(Sense_V >= REF_V)
  391.                 {
  392.                         Diffe = Sense_V - REF_V;
  393.                         Direction = 1;
  394.                         SoftStart = 0;
  395.                 }
  396.                 else
  397.                 {
  398.                         Diffe = REF_V - Sense_V;
  399.                         Direction = 0;
  400.                 }
  401.                
  402.                 P = Diffe / Factor;                //P
  403.                
  404.                 if(!SoftStart)
  405.                 {
  406.                         if(Direction)
  407.                         {
  408.                                 M = M - P;
  409.                         }
  410.                         else
  411.                         {
  412.                                 M = M + P;
  413.                         }
  414.                 }
  415.                
  416.                 //
  417.                 if(M <= 0)
  418.                 {
  419.                         M = 0;
  420.                 }
  421.                 if(M >= Level)
  422.                 {
  423.                         M = Level - 1;
  424.                 }
  425.                
  426.                 //电压长采样
  427.                 SamplingV += Sense_V;
  428.                 SamplingCountV++;
  429.                 if(SamplingCountV >= (Element - 1))
  430.                 {
  431.                         Test_V = (float)(SamplingV / SamplingCountV) / K_V;
  432.                         SamplingV = 0;
  433.                         SamplingCountV = 0;
  434.                                                
  435.                         //SamplingNewV = 1;
  436.                 }
  437.                 //电流长采样
  438.                 Sense_I = Absolute(Get_ADC1(0x0e), Get_ADC1(0x0d));
  439.                 SamplingI += Sense_I;
  440.                 SamplingCountI++;
  441.                 if(SamplingCountI >= (Element - 1))
  442.                 {
  443.                         Test_I = (SamplingI / SamplingCountI) / K_I;
  444.                         SamplingI = 0;
  445.                         SamplingCountI = 0;
  446.                                                
  447.                         //SamplingNewV = 1;
  448.                 }
  449.                
  450.         }       
  451.        
  452. }
  453. void ADC_Isr() interrupt 5
  454. {
  455.        
  456.         ADC_CONTR &= ~0x20;         //清中断标志       
  457.         EA = 1;       
  458.         TR0 = 1;                //定时器0开始计时
  459.         EADC = 0;                //使能ADC中断               
  460.         PID();       
  461. }
  462. void main()
  463. {
  464.         P_SW2 |= 0x80;         //使能访问 XFR       
  465.         CLK_Init();
  466.         GPIO_Init();
  467.         ADCInit();
  468.         ConfigRead();
  469.         PWM_Init();
  470.         Config();
  471.         I2C_Init();
  472.         OLED_Init();
  473.         //Display_Start();
  474.         Display_Frame();
  475.         Timer0Init();
  476.         Timer1Init();
  477.        
  478.         //OLED_Display_16bit_number(68,3,REF_I);
  479.         EN = 1;       
  480.         IS_OK = 1;
  481.         M = 98;
  482. ///////////////////////
  483.        
  484.        
  485.         IP = 0x10;
  486.         IPH = 0x20;
  487.         IP2 = 0x04;
  488.         IP2H = 0x04;
  489.         EA = 1;
  490.         Change();
  491.         while(1)
  492.         {
  493.                 Change();
  494.                 ONOFF();
  495.                 Display_Refresh();
  496.                
  497.                
  498.                
  499.                 if(Save == 1)
  500.                 {
  501.                         Save = 0;
  502.                         OLED_P8x16Str(68,3,"Save...");
  503.                         ConfigWrite();
  504.                         OLED_P8x16Str(68,3,"       ");
  505.                 }
  506.                
  507.                 //P26 = TR0;
  508.                
  509.         ///////////////////////////////////////////////////////
  510.         WDT_CONTR |= 0x10;
  511.         }
  512. }
复制代码
回复 支持 反对

使用道具 举报 送花

1

主题

3

回帖

23

积分

新手上路

积分
23
发表于 2023-6-1 13:25:42 | 显示全部楼层
angm*** 发表于 2023-6-1 12:13
你的程序有缺陷,你把你的代码完整地贴上来看看

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

点评

那估计你的中断程序有问题,仔细检查。  详情 回复 发表于 2023-6-1 13:54
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:50
  • 最近打卡:2025-04-30 22:59:03

73

主题

5882

回帖

1万

积分

超级版主

积分
12073
发表于 2023-6-1 13:54:03 | 显示全部楼层
jef*** 发表于 2023-6-1 13:25
目前已知:ADC中断如果不开启中断嵌套(494行)就不会导致这个问题

那估计你的中断程序有问题,仔细检查。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:20
  • 最近打卡:2025-04-28 16:56:43

21

主题

376

回帖

2345

积分

超级版主

积分
2345
发表于 2023-6-1 16:02:14 | 显示全部楼层

用这个范例试下:
1.png
电话:0513-55012946 QQ:2195591714  微信:  19952583740
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:522
  • 最近打卡:2025-05-02 00:29:54

10

主题

1159

回帖

5121

积分

论坛元老

积分
5121
发表于 2023-6-1 16:10:37 | 显示全部楼层
没有看见这个程序 Timer0Init();
回复 支持 反对

使用道具 举报 送花

1

主题

3

回帖

23

积分

新手上路

积分
23
发表于 2023-6-1 16:23:47 | 显示全部楼层
STC32G12*** 发表于 2023-6-1 16:02
用这个范例试下:

是的,平时都是用STCISP工具配置的定时器
  1. void Timer0Init(void)                //2毫秒@30.000MHz
  2. {
  3.         AUXR &= 0x7F;                //定时器时钟12T模式
  4.         TMOD &= 0xF0;                //设置定时器模式
  5. //        TL0 = 0x3C;                //设置定时初始值                //1mS
  6. //        TH0 = 0xF6;                //设置定时初始值
  7.         TL0 = 0x78;                //设置定时初始值                //2mS
  8.         TH0 = 0xEC;                //设置定时初始值
  9.         TF0 = 0;                //清除TF0标志
  10.         TR0 = 1;                //定时器0开始计时
  11.         ET0 = 1;
  12.         //IP &= 0xfd;
  13.         //IPH &= 0xfd;
  14. }
复制代码
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:522
  • 最近打卡:2025-05-02 00:29:54

10

主题

1159

回帖

5121

积分

论坛元老

积分
5121
发表于 2023-6-1 16:34:47 | 显示全部楼层
那估计你的ADC中断程序运行超过两毫秒。你需要调整一下。
回复 支持 反对

使用道具 举报 送花

4

主题

12

回帖

67

积分

注册会员

积分
67
发表于 2023-6-2 11:40:13 | 显示全部楼层
本帖最后由 pingfr 于 2023-6-2 11:41 编辑

我的STC32G12K也遇到类似问题,开timer0中断后进入一次就再也不进了,配置也没啥特殊的
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:46 , Processed in 0.147431 second(s), 119 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表