打印

快来看一看为什么定时器做延时函数出现问题

[复制链接]
6651|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wangwenzhao|  楼主 | 2013-6-29 19:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我是一个菜鸟,教科书上和网上怎么全是那种delay(xxx);的死等的延时函数,好多场合根本用不了,所以想用定时器做一个延时函数(直接调用的那种),写出来之后不知道怎么搞的这个程序延时10ms可以,但是时间长了就不行,但是加上红色字体的那几句就可以了(已测试),附件里面是开始的程序,为什么要加红色的那几句呢!(不加的话LED应该也会亮啊,)....各位看看....
#include <pic.h> //头文件在HI-TECH安装目录下\HI-TECH Software\PICC\std\9.60\include
#define uchar unsigned char
#define uint  unsigned int
#define LED RB4
void IO_init(void);
uchar time_delay(uint x);
void timer1_init(void) ;  
bank1 uchar time_flag;
bank1 uint time;
bank1 uchar flag;
//**********************IO初始化操作*************************************************
void IO_init(void)
{
    TRISB=0x00;      
    PORTB=0xff;   
    TRISC=0x00;      
 PORTC=0x00;   
   
    TRISD=0x10;      
    PORTD=0xff;  
  
    TRISE=0x00;        
    PORTE=0x00;
   
    TRISA=0x3F;        
    PORTA=0xFF;  
    ANSELH=0x00;
    ANSEL=0x08;
}
uchar time_delay(uint x)
{
   uchar i;
 if(flag==0)
  {
   time_flag=1;
   flag=1;
  }
   if(time>=x)
   {
     time_flag=0;
    flag=0;
     i=1;
   }
   return i;
}
//***********************************************************************************
void timer1_init(void)       //fosc/4=4M/4所以计数周期为1us
{
T1CON=0X01;              //16位定时方式
TMR1IF=0;                //清timer1中断标志
TMR1IE=1;                //timer1中断允许
TMR1H=(65536-1984)/256;                                
TMR1L=(65536-1984)%256;  
    PEIE=1;                  //允许外围中断
GIE=1;                   //开总中断
   
}
//****************************************************************************************  
//--------------------------------定时器中断----------------------------------------
//***********************************************************************************
void interrupt ISR(void)
{
    if(TMR1IF==1)
    {         
       TMR1H=(65536-1984)/256;                      //中断一次对TMR1写入一个调整值。
    TMR1L=(65536-1984)%256;  
    TMR1IF=0;                                    //清timer1中断标志  
      
     
       if(time_flag==1)
       {
        time++;   //1ms
       }
       else time=0;  
    }
   
}

//主函数
//***********************************************************************************
void main()
{
    __CONFIG(XT&WDTDIS&LVPDIS);//配置,设置为晶振XT方式振荡,禁看门狗,禁低电压编程
   
  
      IO_init();                 //I/O口初始化  
     
      timer1_init();      //定时器初始化
      
       while(1)                  
      {
   
        if(time_delay(1000)==1)//1后点亮LED_R
        {
         LED_R=0;
        }
   }
}

Untitled.zip

1.14 KB

沙发
NE5532| | 2013-6-29 19:24 | 只看该作者
flag用于在中断服务程序和主循环之间沟通,传递一些信息,楼主跟着程序读一下。

使用特权

评论回复
板凳
wangwenzhao|  楼主 | 2013-6-29 19:45 | 只看该作者
不要那个flagLED应该也会亮啊,不是一开始就把那个time_flag=1了吗?那time不是就开始++了吗,加到1000LED不就亮了吗

使用特权

评论回复
地板
NE5532| | 2013-6-30 08:21 | 只看该作者
那你就再想一想,这个标志什么时候被清除的。

使用特权

评论回复
5
wangwenzhao|  楼主 | 2013-7-1 09:11 | 只看该作者
NE5532 发表于 2013-6-30 08:21
那你就再想一想,这个标志什么时候被清除的。

能不能给我个提示,我可能进入自己思维的死胡同了,真不知道time_flag这个标志什么时候会被清除

使用特权

评论回复
6
xlsf1048| | 2013-7-1 10:15 | 只看该作者
跟红色字体应该没多大关系吧。参数定义时赋初值试试。time_delay里面的i,还有全局标志位。

使用特权

评论回复
7
wangwenzhao|  楼主 | 2013-7-1 10:36 | 只看该作者
xlsf1048 发表于 2013-7-1 10:15
跟红色字体应该没多大关系吧。参数定义时赋初值试试。time_delay里面的i,还有全局标志位。 ...

我这种方法可以不行,刚刚试下,老是出错,请问一般情况下要做延时处理,你是怎么做的,但又不想程序在一个地方死等且要调用方便的

使用特权

评论回复
8
xlsf1048| | 2013-7-1 10:50 | 只看该作者
wangwenzhao 发表于 2013-7-1 10:36
我这种方法可以不行,刚刚试下,老是出错,请问一般情况下要做延时处理,你是怎么做的,但又不想程序在一 ...

uchar i;===》uchar i=0;要做返回值,不赋初值感觉被忽悠的样子。采用定时,中断产生标志位,并在主循环里面检查标志位,检查到标志位表示延时完毕。

使用特权

评论回复
9
wangwenzhao|  楼主 | 2013-7-1 11:04 | 只看该作者
xlsf1048 发表于 2013-7-1 10:50
uchar i;===》uchar i=0;要做返回值,不赋初值感觉被忽悠的样子。采用定时,中断产生标志位,并在主循环 ...

能不能给个例子给我,我想看看定时器是怎么产生这个中断标志位,而主循环中是怎么查询这个标志位的.麻烦你了

使用特权

评论回复
10
xlsf1048| | 2013-7-1 11:17 | 只看该作者
wangwenzhao 发表于 2013-7-1 11:04
能不能给个例子给我,我想看看定时器是怎么产生这个中断标志位,而主循环中是怎么查询这个标志位的.麻烦 ...

void TIMER0_ISR(void)//中断服务函数
{
        if((INTCONbits.TMR0IF==1)&&(INTCONbits.TMR0IE==1))
        {
                INTCONbits.TMR0IF=0;//配合中断开启关闭
                TMR0H=0xc2;
                TMR0L=0xf7;
                start=1;//标志位产生,全局变量
        }
}

while(1)//主函数循环部分
        {
                ClrWdt();                // 清看门狗       
                if(start==1)
                {
                        start=0;
                        Deal();
                }
        }

标志位我大概就这样用!

使用特权

评论回复
11
wangwenzhao|  楼主 | 2013-7-1 16:39 | 只看该作者
xlsf1048 发表于 2013-7-1 11:17
void TIMER0_ISR(void)//中断服务函数
{
        if((INTCONbits.TMR0IF==1)&&(INTCONbits.TMR0IE==1))

有没有把延时函数封装成一个模块的那种程序,就是想延时多长时间就多长时间,直接调用的那种(但不是死等的那种).刚刚你这种方法只能延时一种固定的时间,

使用特权

评论回复
12
xlsf1048| | 2013-7-1 16:43 | 只看该作者
wangwenzhao 发表于 2013-7-1 16:39
有没有把延时函数封装成一个模块的那种程序,就是想延时多长时间就多长时间,直接调用的那种(但不是死等 ...

你写的不就是啊?

使用特权

评论回复
13
wangwenzhao|  楼主 | 2013-7-1 16:44 | 只看该作者
xlsf1048 发表于 2013-7-1 16:43
你写的不就是啊?

我写的那个不行啊,总出错

使用特权

评论回复
14
yklstudent| | 2013-7-1 17:38 | 只看该作者
#include <pic.h> //头文件在HI-TECH安装目录下\HI-TECH Software\PICC\std\9.60\include

__CONFIG(FOSC_XT & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & DEBUG_ON);//配置,设置为晶振XT方式振荡,禁看门狗,禁低电压编程

#define uchar unsigned char
#define uint  unsigned int

#define LED_R RB4
#define LED_Port        PORTB

typedef struct
{
        unsigned char t0_overflow:1;
        unsigned char blank:7;
}SysStatus1_T;

SysStatus1_T SysStatus1;

void IO_init(void);
uchar time_delay(uint x);
void timer1_init(void);  
bank1 uchar time_flag;
bank1 uint time;
bank1 uchar flag;

//**********************IO初始化操作*************************************************
void IO_init(void)
{
        TRISB=0x00;      
    PORTB=0xff;   
    TRISC=0x00;      
        PORTC=0x00;   
   
    TRISD=0x10;      
    PORTD=0xff;  
  
    TRISE=0x00;        
    PORTE=0x00;
   
    TRISA=0x3F;        
    PORTA=0xFF;  
    //ANSELH=0x00;
    ANSEL=0x08;
}

uchar time_delay(uint x)
{
        static unsigned char result = 0;
        if(time==0)
        {
                result = 0;
        }
        if(time>=x)
        {
                time = 0;
                result = 1;
        }
        return (result);
}

//***********************************************************************************
void timer1_init(void)       //fosc/4=4M/4所以计数周期为1us
{
        T1CON = 0x01;              //16位定时方式
        TMR1IF = 0;                //清timer1中断标志
        TMR1IE = 1;                //timer1中断允许
        TMR1H = (65536-10000)/256;                                
        TMR1L = (65536-10000)%256;  
    PEIE=1;                  //允许外围中断
        GIE=1;                   //开总中断   
}

//****************************************************************************************  
//--------------------------------定时器中断----------------------------------------
//***********************************************************************************
void interrupt ISR(void)
{
    if(TMR1IF==1)
    {   
            TMR1IF=0;                                    //清timer1中断标志        
               TMR1H=(65536-1000)/256;                      //中断一次对TMR1写入一个调整值。
            TMR1L=(65536-1000)%256;  
      
               if(time_flag==1)
               {
                time++;   //1ms
               }
        }  
}

//主函数
//***********************************************************************************
void main()
{
        IO_init();                 //I/O口初始化  

        timer1_init();      //定时器初始化
      
        while(1)                  
        {
                time_flag = 1;
                if(time_delay(100)==1)//1后点亮LED_R
        {
                        LED_Port ^= 0x55;
        }
        }
}#include <pic.h> //头文件在HI-TECH安装目录下\HI-TECH Software\PICC\std\9.60\include

__CONFIG(FOSC_XT & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & DEBUG_ON);//配置,设置为晶振XT方式振荡,禁看门狗,禁低电压编程

#define uchar unsigned char
#define uint  unsigned int

#define LED_R RB4
#define LED_Port        PORTB

typedef struct
{
        unsigned char t0_overflow:1;
        unsigned char blank:7;
}SysStatus1_T;

SysStatus1_T SysStatus1;

void IO_init(void);
uchar time_delay(uint x);
void timer1_init(void);  
bank1 uchar time_flag;
bank1 uint time;
bank1 uchar flag;

//**********************IO初始化操作*************************************************
void IO_init(void)
{
        TRISB=0x00;      
    PORTB=0xff;   
    TRISC=0x00;      
        PORTC=0x00;   
   
    TRISD=0x10;      
    PORTD=0xff;  
  
    TRISE=0x00;        
    PORTE=0x00;
   
    TRISA=0x3F;        
    PORTA=0xFF;  
    //ANSELH=0x00;
    ANSEL=0x08;
}

uchar time_delay(uint x)
{
        static unsigned char result = 0;
        if(time==0)
        {
                result = 0;
        }
        if(time>=x)
        {
                time = 0;
                result = 1;
        }
        return (result);
}

//***********************************************************************************
void timer1_init(void)       //fosc/4=4M/4所以计数周期为1us
{
        T1CON = 0x01;              //16位定时方式
        TMR1IF = 0;                //清timer1中断标志
        TMR1IE = 1;                //timer1中断允许
        TMR1H = (65536-10000)/256;                                
        TMR1L = (65536-10000)%256;  
    PEIE=1;                  //允许外围中断
        GIE=1;                   //开总中断   
}

//****************************************************************************************  
//--------------------------------定时器中断----------------------------------------
//***********************************************************************************
void interrupt ISR(void)
{
    if(TMR1IF==1)
    {   
            TMR1IF=0;                                    //清timer1中断标志        
               TMR1H=(65536-1000)/256;                      //中断一次对TMR1写入一个调整值。
            TMR1L=(65536-1000)%256;  
      
               if(time_flag==1)
               {
                time++;   //1ms
               }
        }  
}

//主函数
//***********************************************************************************
void main()
{
        IO_init();                 //I/O口初始化  

        timer1_init();      //定时器初始化
      
        while(1)                  
        {
                time_flag = 1;
                if(time_delay(100)==1)//1后点亮LED_R
        {
                        LED_Port ^= 0x55;
        }
        }
}

不如改成这样的用用吧 不过还是有局限性的 谁用谁知道

使用特权

评论回复
15
wangwenzhao|  楼主 | 2013-7-1 18:34 | 只看该作者
yklstudent 发表于 2013-7-1 17:38
#include  //头文件在HI-TECH安装目录下\HI-TECH Software\PICC\std\9.60\include

__CONFIG(FOSC_XT & WDT ...

time清0能否放在time_delay()调用之前,应该怎么插入进出

使用特权

评论回复
16
圈圈虫1989| | 2013-7-1 22:06 | 只看该作者
delay函数的延时可以用mplab 8.xx里面的sim仿真功能计算

使用特权

评论回复
17
NE5532| | 2013-7-2 08:45 | 只看该作者
楼主全局搜索,看这个标志什么时候清除不就知道了哇

使用特权

评论回复
18
wangwenzhao|  楼主 | 2013-7-2 09:03 | 只看该作者
NE5532 发表于 2013-7-2 08:45
楼主全局搜索,看这个标志什么时候清除不就知道了哇

怎么全局搜索啊,千万别喷我,我是真的想虚心请教:lol保证下次不问了

使用特权

评论回复
19
NE5532| | 2013-7-2 10:34 | 只看该作者
看你用的什么编辑器在写程序,楼主如果用的是Windows的记事本,就在上面菜单里找,而且推荐楼主使用UE,不要用记事本自虐了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

35

帖子

0

粉丝