找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1867|回复: 7
打印 上一主题 下一主题
收起左侧

STF15单片机关于一个延迟函数的问题

[复制链接]
跳转到指定楼层
楼主
ID:832039 发表于 2020-12-16 00:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
10黑币
下面的程序使用了一个5ms的定时器,对变量sys_tick进行了+1的操作.
程序的功能是使LED灯亮一秒,熄一秒.

目前程序运行后,通过逻辑分析仪分析 P2_3的电平输出,高低电平持续的时候大部分是准时的,但是有时会少于1000ms,会出现800多ms,500多ms的情况.

如果每次延迟的时候去掉下面红字部分的注释则能正常.请问程序出现的问题在哪?

#include <stdint.h>
void Timer0Init(void) //5毫秒@11.0592MHz

{
    AUXR |= 0x80; //定时器时钟1T模式
    TMOD &= 0xF0; //设置定时器模式
    TL0 = 0x00; //设置定时初值
    TH0 = 0x28; //设置定时初值
    TF0 = 0; //清除TF0标志
    TR0 = 1; //定时器0开始计时
    ET0 = 1;
}

typedef uint32_t size_tick;


volatile size_tick sys_tick = 0;


void Timer0Int() __interrupt TF0_VECTOR
{
    ++sys_tick;
}



void Delay(uint16_t ms)
{
    size_tick tick_num = ms / 5;
    // sys_tick = 0; // 如果这行注释去掉的话定时是正确的
    size_tick cur_tick = sys_tick;
    while (sys_tick - cur_tick < tick_num)
    {;}
}



void main()
{
    EA = 1; //开总中断
    Timer0Init();
    while (1)
    {

        P2_3 = 0;
        Delay(1000);


        P2_3 = 1;
        Delay(1000);


    }
}


另外,我在每次延迟后通过串口输出 sys_tick的值. 理论上 sys_tick每次输出的值应该是相隔200左右 ( 1000ms/5ms = 200 ).
但是总是在固定时候输出是啊小于200的.
200
400
600
800
1000
1201
1402
1536
1737
1938
2048
2249
2450
2560
2761
2962
3072
3273
3474



最佳答案

查看完整内容

按你的思路给你改写了,但通常不会有人这么写延时函数,浪费资源。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2020-12-16 00:23 | 只看该作者

按你的思路给你改写了,但通常不会有人这么写延时函数,浪费资源。
  1. #include <STC15F2K60S2.H>
  2. sbit P2_3 = P2^3;
  3. bit flag=0;
  4. unsigned int num;

  5. void Timer0Init(void)                //1毫秒@11.0592MHz
  6. {
  7.         AUXR |= 0x80;                //定时器时钟1T模式
  8.         TMOD &= 0xF0;                //设置定时器模式
  9.         TL0 = 0xCD;                //设置定时初值
  10.         TH0 = 0xD4;                //设置定时初值
  11.         TF0 = 0;                //清除TF0标志
  12.         TR0 = 1;                //定时器0开始计时
  13.         ET0 = 1;                //开T0中断
  14.         EA = 1;                 //开总中断
  15. }

  16. void Timer0Int()interrupt 1
  17. {
  18.         if(flag==1 && num>0)
  19.                 num--;
  20. }

  21. void Delay(unsigned int ms)
  22. {
  23.         flag=1;
  24.         num=ms;
  25.         while(num);
  26.         flag=0;
  27. }

  28. void main()
  29. {
  30.         Timer0Init();
  31.         while(1)
  32.         {
  33.                 P2_3 = 0;
  34.                 Delay(1000);
  35.                 P2_3 = 1;
  36.                 Delay(1000);
  37.         }
  38. }
复制代码
回复

使用道具 举报

板凳
ID:861234 发表于 2020-12-16 13:59 | 只看该作者
你这程序里定时器启动后就一直在运行,sys_tick是自动变的,在不调用延时程序时都会变化,当调用延时程序时如果不预先清0则sys_tick可能已经被定时器程序增加到某一数值,当然延时时间就不准确了
回复

使用道具 举报

地板
ID:832039 发表于 2020-12-16 14:31 | 只看该作者
小牢头 发表于 2020-12-16 13:59
你这程序里定时器启动后就一直在运行,sys_tick是自动变的,在不调用延时程序时都会变化,当调用延时程序时 ...

size_tick cur_tick = sys_tick;
while (sys_tick - cur_tick < tick_num)
{;}

这里的做延迟前是先取sys_tick sys_tick,在后再while循环里面中断会不断改sys_tick的前和之前的取值对比.
回复

使用道具 举报

5#
ID:213173 发表于 2020-12-16 17:35 | 只看该作者
STF15单片机,有这个型号的单片机?
回复

使用道具 举报

6#
ID:832039 发表于 2020-12-16 19:16 | 只看该作者
wulin 发表于 2020-12-16 17:35
STF15单片机,有这个型号的单片机?

STC15单片机
回复

使用道具 举报

7#
ID:832039 发表于 2020-12-16 23:06 | 只看该作者
wulin 发表于 2020-12-16 21:21
按你的思路给你改写了,但通常不会有人这么写延时函数,浪费资源。

一直占用定时器确实不好.你的写法是可行的.只是我想知道的是我贴出的程序问题出现在哪.因为目的不是实现功能,而是发现问题和解决问题
回复

使用道具 举报

8#
ID:832039 发表于 2020-12-16 23:07 | 只看该作者
想了很久,知道问题在哪了,是原子性的问题.
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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