完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我有一个PIC24F好奇心板-PIC24FJ128GA204-我正试图得到一个准确的第二个时间与tiM1。作为一个源,我使用二次振荡器,它使用一个32678 kHz的XTL。计时器被配置为一个32周期,对应于1毫秒,因此每1 ms调用一个中断,其中MS的计数被存储在主回路中的UTI32 32变量中,我在TMR1OOB.C上忙着等待。ONT变量,当它达到1000时,在UART发送一条消息。在UART的另一面,我有一个应用程序,它读取消息并记录接收到的时间,以及与先前消息的毫秒数的差异。问题是,每个消息都有一个~8ms的累积。22: 5.026 100822: 6.035 100922: 7.045 101022:8.054 100822:9.063 1008怀疑它可能是与UART传输有关的一些东西经常被打断我试图每隔10秒而不是1发送消息。每隔10秒,延时就一直累积到80ms。最后,可能是32个蜱不对应于1毫秒,而是1×x ms,以测试我将周期改变为32768,即1秒。我预期结果大致相同,但它们不是31∶15.216 99 931:16.216 99 931:17.216 1000 31:18.216 99 931:19.216 99 931:20.215 99 931:21.216 1000,看来这个周期影响计时器的准确性。我不明白怎么做。难道每次中断都会丢失一些微秒吗?我在数据表上看不到任何东西,但我找不到任何其他解释。
以上来自于百度翻译 以下为原文 I have a PIC24F Curiosity Board -PIC24FJ128GA204- and I'm trying to get an accurate second timing with the TIM1. As a source I'm using the secondary oscillator, which uses a 32678 kHz xtl. The timer is configured with a 32 period, which corresponds to 1 ms void TMR1_Initialize (void) { //TMR1 0; TMR1 = 0x0000; //Period = 0.001 s; Frequency = 32000 Hz; PR1 32; PR1 = 0x0020; //TCKPS 1:1; TON enabled; TSIDL disabled; TCS External; TECS SOSC; TSYNC enabled; TGATE disabled; T1CON = 0x8006; IFS0bits.T1IF = false; IEC0bits.T1IE = true; tmr1_obj.timerElapsed = false; } So, every 1 ms the following interrupt is called, where the count of ms is stored on a uint32_t variable void __attribute__ ( ( interrupt, no_auto_psv ) ) _T1Interrupt ( ) { tmr1_obj.count++; tmr1_obj.timerElapsed = true; IFS0bits.T1IF = false; } In the main loop I do a busy wait on the tmr1_obj.count variable, and when it reaches 1000 a message is sent in UART. int main(void) { // initialize the device SYSTEM_Initialize(); TMR1_Start(); char msg[] = "Arn"; while (1) { // Add your application code int value = TMR1_SoftwareCounterGet(); if (value == 1000) { printf("%s", msg); TMR1_SoftwareCounterClear(); } } return -1; } On the other side of the UART I have an application that reads the message and logs the time when it was received and the difference in milliseconds with respect to the previous message. The problem is that I have an accumulation of ~8ms for each message. 22:05.026 1008 22:06.035 1009 22:07.045 1010 22:08.054 1008 22:09.063 1008 Suspecting it could be something related to the UART transmission being often interrupted I tried to send the message every 10 seconds instead of 1. The delay was consistently accumulated to ~80ms each 10 seconds. Finally, it could be that the 32 ticks do not correspond to 1 ms but to 1.x ms. To test that I changed the period to be 32768, that is, 1 second. I expected the results to be roughly the same, but they weren't 31:15.216 999 31:16.216 999 31:17.216 1000 31:18.216 999 31:19.216 999 31:20.215 999 31:21.216 1000 It seems that the period affects the accuracy of the timer. And I don't understand how. Could it be that for each interruption some microseconds were lost ? I don't see anything on the data sheet, but I can't find any other explanation. |
|
相关推荐
19个回答
|
|
您的精度问题取决于您连接到Time1振荡放大器的晶体的实际频率。在您的帖子中,您已经说过这是一个32.768 kHz晶体。有了这个频率,32分的结果在0.9765625毫秒,而不是1毫秒,正如你在你的文章中所说的。那么你实际使用的实际晶体的实际频率是多少?
以上来自于百度翻译 以下为原文 Your accuracy issues depend on the actual frequency of the crystal you have connected to the TIMER1 oscillation amplifier. In your post you have said this is a 32.768KHz crystal. With this frequency a divisor of 32 results in a period of 0.9765625 milliseconds not 1 millisecond as you stated in your post. So what is the actual frequency of the actual crystal that you actually used? |
|
|
|
尝试将预缩放器设置为256.32768 / 256=128,并将周期设置为127。这将使ISR每秒一次地发生火灾。
以上来自于百度翻译 以下为原文 Try setting the pre-scaler to 256. 32768 / 256 = 128 and setting the period to 127. That should make the isr fire once every second. |
|
|
|
不管计时器精度如何,因为计时器达到1000点到你清除它的时间被加到你的动作周期中,所以你应该期望你的周期比计时器所产生的时间长。为了获得准确的周期,你需要一个由ITSE滚动的自由运行计时器。LF,没有额外的延迟。您可以通过设置PR1寄存器来实现这一点。
以上来自于百度翻译 以下为原文 Regardless of the timer accuracy, the time since the timer reaches 1000 to the point where you clear it is added to the period of your actions, so you should expect your period to be longer than the timer would produce. To get an accurate period you need a free-running timer which rolls over by itself, without extra delays. You can do this by setting PR1 register. |
|
|
|
你是对的,一个32的除数不会导致1毫秒的周期,因为我只关心数秒,我应该计算1024个周期而不是1000个周期。我纠正了它,延迟每回合1024个周期增加到30Ms。22: 59.783 A23:0.814 1030 A23:1.844 1030 A23:2.874 1029 A23:3.904 1030 A23:4.935占卜A23:占卜实际频率,我还没有在这个板上测量,但是,实际上,这正在发生。对我来说,在两个不同的板与两个不同的图片-另一个是PIC24FJ256GB406-。在另一块板上,我测量了它,它实际上是32768千赫,延迟与我在这里的~30毫秒相同。我在这里复制问题。但是,即使频率不是32.768千赫,如果它是恒定的,我不明白为什么触发的中断次数会影响AC。狡猾。不管周期如何,我认为延迟应该是一样的。
以上来自于百度翻译 以下为原文 You're right, a divisor of 32 doesn't result in a period of 1 ms. As I'm only concerned with counting seconds, I should count to 1024 periods instead of 1000. I've corrected it and the delay has increased to ~30ms for each round of 1024 periods. int main(void) { // initialize the device SYSTEM_Initialize(); TMR1_Start(); char msg[] = "Arn"; while (1) { // Add your application code int value = TMR1_SoftwareCounterGet(); if (value == 1024 - 1) { printf("%s", msg); TMR1_SoftwareCounterClear(); } } return -1; } 22:59.783 1030 A 23:00.814 1030 A 23:01.844 1030 A 23:02.874 1029 A 23:03.904 1030 A 23:04.935 1030 A 23:05.965 1030 A Regarding the actual frequency, I haven't measured it on this board, but, actually, this is happening to me in two different boards with two different PICs -the other being a PIC24FJ256GB406-. On that other board I measured it and it was actually 32768 kHz and the delay was the same as I'm getting here ~30ms. I'm kind of replicating the problem here. But, even if the frequency was not 32.768 kHz, if it is constant, I don't see why the number of interruptions triggered should affect the accuracy. Regardless of the period, the delay should be the same, I think. |
|
|
|
我不能这样做,系统的其他部分在32个时期进行中继。
以上来自于百度翻译 以下为原文 I can't do that, other parts of the system relay on the 32 period. |
|
|
|
我希望增加一些时间——从中断返回,与1024进行比较,清除定时器-但每次中断不超过30微秒。无论如何,我可以试着不重置计时器。
以上来自于百度翻译 以下为原文 I expect some time to be added - returning from the interrupt, compare with 1024 and clear the timer- but not as much as ~30 microseconds per interrupt. Anyway, I can try not resetting the timer. |
|
|
|
相同的结果不清除定时器。53: 14.522 1029 A53: 15.553 15.553 1030 A53: 16.583 1030 A53:17.613 1029 A53:18.643 1030 A
以上来自于百度翻译 以下为原文 Same results without clearing the timer. int main(void) { // initialize the device SYSTEM_Initialize(); TMR1_Start(); char msg[] = "Arn"; while (1) { // Add your application code int value = TMR1_SoftwareCounterGet(); if (value > 0 && value % (1024 - 1) == 0) { printf("%s", msg); } } return -1; } 53:14.522 1029 A 53:15.553 1030 A 53:16.583 1030 A 53:17.613 1029 A 53:18.643 1030 A |
|
|
|
使用另一个定时器,如果你想要精度,那么得到一个RTC芯片,像Maxim-集成极端精确的DS323。除了作为一个具有2个定时器的RTC,它还可以输出1, 1024, 4096、8192和32768秒的方波。它在芯片内部有它自己的XTAL。你所需要的只是芯片、备用电池和在I2C总线上的上拉。
以上来自于百度翻译 以下为原文 Use another timer. If you want accuracy then get a RTC chip like the Maxim Integrated extremly accurate DS3231. Besides being a RTC with 2 timers, it can also output a square wave of 1, 1024, 4096, 8192 and 32768 per second. It has it's own xtal inside the chip. All you need is the chip, backup battery and pullups on the i2c bus. |
|
|
|
我想你错过了一个事实,你需要少一个进入公关登记册。所以使用31而不是32.100/32×33=1031 I. e.你正在得到的错误!你不应该清点账目。公关比赛将做到:29、30、31、0、1等
以上来自于百度翻译 以下为原文 I think you missed the fact that you need to put one less into the PR register. So use 31 instead of 32. 1000/32 * 33 = 1031 i.e. the error you are getting! You should not clear the count. The PR match will do that: 29,30,31,0,1 etc |
|
|
|
|
|
|
|
谢谢,我忘了减去1个周期,你是对的。结果肯定改进了50:95950:109850:4.476 99 850:5.475 99 950:7.473 99 950:8.472 99 850:9.471 99 950:10.470 99 950:11.469 99 850:OUTHUNTH 1.479,现在我是每秒1ms,这是误差为0.1%。我不知道XTL的规格,但在最坏的情况下,这甚至超过了50 ppm的偏差。如果这是一个拖延,我可以责怪它的一些处理,虽然它仍然是太多,但这么多的未来是一些我不明白。原因是什么?
以上来自于百度翻译 以下为原文 Thanks, I forgot subtracting 1 to period, you were right. The results have certainly improved 50:01.479 999 50:02.478 999 50:03.477 998 50:04.476 998 50:05.475 999 50:06.474 999 50:07.473 999 50:08.472 998 50:09.471 999 50:10.470 999 50:11.469 998 50:12.468 998 As you see, now I'm ~1ms per second ahead, which is an error of ~0.1%. I don't know the specs of the xtl, but this is way more than even a 50 ppm deviation, in the worst case. If it were a delay I could blame it on some processing, though it is still too much, but being so much ahead is something I don't understand. What could be the cause ? |
|
|
|
你还有这个吗?如果是这样,删除“-1”应该固定。
以上来自于百度翻译 以下为原文 Do you still have this: if (value > 0 && value % (1024 - 1) == 0) { printf("%s", msg); } ? If so, removing "-1" should fix it. |
|
|
|
我没有这个代码,我有这个,但我已经改变了1023到1024,准确度现在好多了。我明白,我没有让第一千零二十三段结束,重新设置之前,它已经完全完成。这就说明了在前面。诺思哥,这是你的推理吗?这些结果是No.48:26.675(27.675)48 48:29.675 99 948:30.675 99 948:31.675 1000 948:32.675 99 48:34.675 99 948:35.675 99 948:36.674 99 948:37.674 99 948:199 948:47.674 99 948:49.674 99 948:51.674 99 948:52.674 99 948:54.674 99 948:55.674 99 948:56.674 99 948:57.674 99 948:58.674 99 949:1 1000 49:1 99 949:1 99 949:1 1000 49:1 99 949:1 99 949:1 1000 49:1 1000 49∶09。673 99 949:10.673 99 949:11.673 1000 49:12.673 99 949:13.673 99 949:14.673 99 949:15.673 99 949:16.673 99 949:17.673 99 949:18.673 999~1 ms在秒秒内丢失。我想这对我来说可能够好了,谢谢大家!
以上来自于百度翻译 以下为原文 I didn't had this code, I had this int main(void) { // initialize the device SYSTEM_Initialize(); TMR1_Start(); char msg[] = "Arn"; while (1) { // Add your application code uint32_t value = TMR1_SoftwareCounterGet(); if (value == 1023) { TMR1_SoftwareCounterClear(); printf("%s", msg); } } return -1; } but I have changed the 1023 to 1024 and the accuracy is much better now. I understand that i was not letting the 1023th period to end, resetting it before it has fully completed. That would explain being ahead. Was that your reasoning, NorthGuy?. These are the results now 48:26.675 1000 48:27.675 1000 48:28.675 999 48:29.675 999 48:30.675 999 48:31.675 999 48:32.675 1000 48:33.675 999 48:34.675 999 48:35.675 999 48:36.674 999 48:37.674 999 48:38.674 999 48:39.674 999 48:40.674 999 48:41.674 999 48:42.674 999 48:43.674 999 48:44.674 999 48:45.674 999 48:46.674 999 48:47.674 999 48:48.674 999 48:49.674 999 48:50.674 999 48:51.674 999 48:52.674 999 48:53.674 999 48:54.674 999 48:55.674 999 48:56.674 999 48:57.674 999 48:58.674 999 48:59.673 999 49:00.673 1000 49:01.673 999 49:02.673 999 49:03.673 999 49:04.673 1000 49:05.673 999 49:06.673 999 49:07.673 1000 49:08.673 1000 49:09.673 999 49:10.673 999 49:11.673 1000 49:12.673 999 49:13.673 999 49:14.673 999 49:15.673 999 49:16.673 999 49:17.673 999 49:18.673 999 ~1 ms lost in 23 seconds. I think that may be good enough for me. Thank you all! |
|
|
|
剩下的错误很可能是在另一端打印那些时间!;-)
以上来自于百度翻译 以下为原文 The remaining error is just as likely to be at the other end printing those times out! ;-) |
|
|
|
晶体将具有50 ppm的精度(或更好)仅与指定的电容器(对于并联谐振型)。你需要两个电容器,一个从晶体的每一边到地。如果它指定了20个PF,则需要两个40个PF电容器,因为它们本质上是串联在晶体上,并有一个分接头到GND。你可以用一个可变电容器或一个“噱头”来调整这些值,这只是一对漆包线缠绕在一起形成一个几PF的电容器,你可以通过在一个精确的计数器观察频率的同时稍微削掉一点来调整。更多的电容降低了频率。
以上来自于百度翻译 以下为原文 The crystal will have 50 PPM accuracy (or better) only with the specified capacitors (for a parallel resonant type). You need two capacitors, one from each side of the crystal to ground. If it specifies 20 pF, you need two 40 pF capacitors, because they are essentially in series across the crystal with a tap to GND. You can tweak the values by using a variable capacitor or a "gimmick", which is just a pair of enamel coated wires twisted together to form a capacitor of a few pF, and you can adjust by cutting a little off the end while observing frequency with an accurate counter. More capacitance lowers the frequency. |
|
|
|
|
|
|
|
23秒后的1毫秒是0.00 1/23=43 ppm。
以上来自于百度翻译 以下为原文 1 mSec out of 23 seconds is 0.001/23 = 43 ppm. |
|
|
|
|
|
|
|
您可能仍然中断1分钟中断。请尝试此代码,看看它是否有帮助:
以上来自于百度翻译 以下为原文 You may still be off by one TIMER1 interrupt. Please try this code to see if it helps: int main(void) { // initialize the device char msg[] = "Arn"; uint32_t Time0; uint32_t Time1; SYSTEM_Initialize(); TMR1_Start(); // Get initial clock time IEC0bits.T1IE = false; // disable TIMER1 interrupt to prevent corrupted read of count from ISR Time0 = TMR1_SoftwareCounterGet(); IEC0bits.T1IE = true; // enabable TIMER1 interrupt while (1) { // Add your application code IEC0bits.T1IE = false; // disable TIMER1 interrupt to prevent corrupted read of count from ISR Time1 = TMR1_SoftwareCounterGet(); // Sample current clock time IEC0bits.T1IE = true; // enabable TIMER1 interrupt // Test for at least one second of elapse time if (Time1 - Time0 > 1023) { Time0 += 1024; // Add the number of TIMER1 interrupts in one second printf("%s", msg); } } return -1; } |
|
|
|
只有小组成员才能发言,加入小组>>
5183 浏览 9 评论
2005 浏览 8 评论
1932 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3178 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2229 浏览 5 评论
739浏览 1评论
626浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
510浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
637浏览 0评论
535浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 21:58 , Processed in 1.703384 second(s), Total 112, Slave 96 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号