PIC18F 分钟和小时定时器
Posted
技术标签:
【中文标题】PIC18F 分钟和小时定时器【英文标题】:PIC18F timer for minutes and hours 【发布时间】:2014-11-19 16:15:36 【问题描述】:#include<p18f452.h>
void T0_init();
void main()
TRISC=0; // Configure PortB as output Port.
LATC=0x01;
T0CON=0x07; // Prescaler= 1:256, 16-bit mode, Internal Clock
T0_init();
while(1)
// Initialize Timer0
LATC=0x00;
T0_init(); //Delay for 1 sec
LATC=0x01;
T0_init(); //Again delay for 1 sec
void T0_init()
int a=0;
//while(a<2) //
TMR0H=0xF0; // Values calculated for 1 second delay with 4MHz crystal
TMR0L=0xBD; //4/4MHz =1us=1us*prescaler=256us=1sec/256u=0xF42-(FFFF)=F0BD
T0CONbits.TMR0ON=1; // Timer0 On
while(INTCONbits.TMR0IF==0); // Wait until TMR0IF gets flagged
T0CONbits.TMR0ON=0; // Timer0 Off
INTCONbits.TMR0IF=0; // Clear Timer0 interrupt flag
// a++;
//
这是非常准确的延迟,它正在发挥作用,但我想要更长的延迟,比如几小时或几分钟。那么,对于更长的延迟该怎么办。我尝试使用在每个标记时递增的计数器,但它不起作用。
【问题讨论】:
Any Body Home 我正在等待回复任何答案?? 我不确定,但您可能必须先通过设置 TMR0IE=1 来启用中断。int a
是您尝试的计数器吗?如果是这样,您需要将其声明为“静态”。
创建一个计数器变量或将延迟函数包装在for
循环(或两个或三个)中确实并不难。试一试。
@AndrewMedico 感谢您的关注,但我必须在此使用计时器。
【参考方案1】:
我不是一个经验丰富的程序员,也不确定你想在哪里使用延迟,但我曾尝试使用 pic18f4550 进行长时间的延迟,但它不起作用,即几分钟和几小时。但我考虑过使用像 CD4060 或 DS1307 这样的 IC。您可以点击此链接获取 CD4060:http://dmohankumar.wordpress.com/2012/05/13/design-your-circuit-part-ii-cd-4060-timer/。对于 DS1307,您可以在 studentcompanion 网站上查看:http://www.studentcompanion.co.za/post/Digital-Clock-using-PIC-Microcontroller-and-the-DS1307-Real-Time-Clock-XC8-Compiler/。祝你成功,谢谢
【讨论】:
感谢您对 Tiras 的关注,但我必须为 PIC 制作代码 :)【参考方案2】:忘记内部定时器,自己做一个繁忙的等待程序:首先做一个 1 秒的延迟例程(非常简单,要准确地做到这一点,注意调用和 retf 执行时间!),然后做一个 1-在第一个延迟例行程序之上,然后在 1 分钟之上制定一个 1 小时延迟例程......你明白了。
【讨论】:
对不起!!但我必须在其中使用 Timer,因为延迟将由用户在运行时输入,并且每次你知道我想说的是运行时值时它都会改变 嗯,不清楚。你是说它必须与用户输入同时运行吗? 是的,稍后我必须从键盘输入并计算其信号 好的,因此您可以仅使用计时器来执行 1 秒的例程,让您的代码扫描键盘。 1 分钟和 1 小时例程仅用于 1 秒函数的循环。外部 for 循环(用于 1 分钟和 1 小时例程的循环)非常快,以至于大部分时间都花在 1 秒例程中,让您的代码在整个延迟期间扫描键盘。 你的逻辑的问题是PIC中有看门狗定时器,它将在2.3秒后重置,以避免在任何情况下损坏PIC。 Timer1 关闭 WDT【参考方案3】:一秒是 1000000 微秒,即小于 256*256*256=16777216。因此,一个 256 预分频的 16 位定时器足以计数一秒。但光是一分钟是不够的。
解决方案是添加一个for
循环来计算秒数。正如@Andrew 建议的那样,另一个是几分钟,另一个是几个小时。
不确定性的来源是在while()
循环中检查了一次定时器的溢出。因此,如果在该循环中执行长时间计算,精度将会降低。为了克服这个问题,使用中断是要走的路。不管发生什么,随着定时器溢出,中断标志被提升,中断函数在几个周期内执行。
由于在while(1)
循环中没有做任何事情,我想使用SLEEP()
命令来节省一些精力。不幸的是,SLEEP()
命令关闭了 timer0。不是timer1的情况,而是timer1是一个8-prescaled 16-bit timer……所以需要一个for循环来计数秒。
这是一段由XC8编译并用MPLAB X模拟器测试的代码……
#include <xc.h>
#pragma config WDT=OFF
volatile unsigned char nb;
volatile unsigned char seconds;
volatile unsigned char minutes;
volatile unsigned char hours;
void interrupt high_isr (void)
if(PIR1bits.TMR1IF) //interrupt flag of TIMER1
if(nb==0)
TMR1H=0; // Values calculated for 1 second delay with 4MHz crystal
TMR1L=0;
nb=1;//4/4MHz =1us=1us*prescaler=8us=1sec/8u=...
else
TMR1H=23;
TMR1L=184;
nb=0;
if(nb==1)
seconds++;
if(seconds==60)
seconds=0;
minutes++;
if(minutes==60)
minutes=0;
hours++;
PIR1bits.TMR1IF=0; //erase interrupt flag of TIMER1
void interrupt low_priority low_isr (void)
void main(void)
//OSCCON=0x7D;//Internal oscillator, 8Mhz
T1CONbits.RD16=1; //timer1 is a 16-bit timer
T1CONbits.T1CKPS1=1; //prescaler 11 -> 8-prescaled
T1CONbits.T1CKPS0=1;
T1CONbits.TMR1ON=1;// switch on timer1
TMR1H=0x00; //setting timer1 : high bit first
TMR1L=0x00;
// TMR0H=0;
// TMR0L=0;
TRISC=0;
LATC=0x00;
INTCON2bits.TMR0IP=0; // low priority interuption timer0
IPR1bits.TMR1IP=1; // high priority interuption timer1
INTCONbits.TMR0IF=0;//erase interruption flap if set
PIR1bits.TMR1IF=0; //erase interruption flag if set
RCONbits.IPEN=1;// Interruption prioritaires
INTCONbits.TMR0IE=0;// interuption activation on timer0 (0=no active)
PIE1bits.TMR1IE=1;//enable interupt on timer1
nb=1;
seconds=0;
minutes=0;
hours=0;
PORTCbits.RC0=0;
PORTCbits.RC1=0;
PORTCbits.RC2=0;
INTCONbits.GIEH=1;// autorise interuptions
INTCONbits.GIEL=1;
// INTCONbits.GIE=1;
while(1)
//problem with modulo and pic...do not use %
if(seconds-2*(seconds/2)==1)
PORTCbits.RC0=1;
else
PORTCbits.RC0=0;
if(minutes-2*(minutes/2)==1)
PORTCbits.RC1=1;
else
PORTCbits.RC1=0;
if(hours-2*(hours/2)==1)
PORTCbits.RC2=1;
else
PORTCbits.RC2=0;
SLEEP();
return;
“秒”的持续时间需要谨慎...可能需要使用TMR1H
、TMR1L
和nb
。
使用外部时钟源(石英)更好:How to make Timer1 more accurate as a real time clock?
【讨论】:
感谢您的回答.. 我明天会试一试我的电脑已经离开了一天,所以等到那时我会再次添加关于我的查询的评论顺便说一句谢谢。 我尝试了你的代码,但我的编译器在 #include<xc.h>
是xc8编译器对应的头文件。转到project->properties->Conf[default]
(右键单击项目名称)并选择 XC8 作为编译器工具链。可以通过at microchip 下载免费(或非免费)版本的 xc8。或者尝试通过#include<p18f452.h>
更改标题。您可能需要在void high_isr(void)
之前添加#pragma code high_vector=0x08
、#pragma code low_vector=0x18
在void low_isr(void)
之前和#pragma code
在main 之前。
我在 C18 上运行项目我正在下载 XC8 :)
我加了几个关于timer1的cmets。以上是关于PIC18F 分钟和小时定时器的主要内容,如果未能解决你的问题,请参考以下文章
24 小时倒计时计时器,带有三个单独的文本视图,分别显示小时、分钟、秒