完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
嗨,伙计们,我一直在研究一个计时器(TMR3)用来测量两个外部中断之间的时间的项目。另一计时器(TMR1)用于计数是否发生过溢出。第一个中断启动计时器,第二个中断关闭它,并调用一些后续计算的函数。然后在LCD.PIC18F26K40@ 64 MHz内部振荡器上显示,TMR3和TMR1没有前置或后置刻度。TMR3与FCYC同步,TMR1在TMR3OUT位上触发。目前,我在LCD上同时显示定时器值和计算值。我也有外部中断设置示波器,以准确地测量它们之间的时间。在Excel中,我把时间从范围内乘以FCYC(16MIPS)。我现在的问题是主计时器TMR3中的随机计数错误。我在TMR寄存器中平均得到1783个(额外的)“蜱”,但是它在整个地方(见附加的JPEG)。这在计算中造成很大的误差。如果它是一致的,那么我可以在计算中减去这个平均值。下面是代码的相关部分:VooStudioLa初始化(空隙){//NOSC HFIFToSC;NDIV 1;OSCCON1= 0x60;//CSWHOOD可以进行;SOSCPWR Low功率;OSCCON3= 0x00;//MFOEN禁用;LFOEN禁用;ADOEN禁用;OsChanq=0x00;//HFFRQ 64×MHz;OSCFRQ= 0x08;/OsTun= 0x00;}空TMR3-初始化(空隙){T3CONC:0x00;/CKPs 1:1;NT3Syc同步;TMR3ON关闭;T3RD16启用;T3GCON=0x00;//T3GE禁用;T3GTM禁用;T3GPOL低;T3GGO完成;T3GSPM禁用;T3GATE=0x00;/GSS T3GPIN;T3Clk=0x01;//CS FoC/4;TMR3H=0x00;/TMR3H 0;TMR3L= 0x00;/TMR3L 0;time3ReLoad=(UTI1616T)((TMR3H和LT;和8;)8)TMR3L;/ /加载TMR值以重新加载可变的PIR4BITS。TMR3IF=0;/ /在启用中断之前清除标志。空隙TMR3IE=1;//允许TMRC1初始化(空隙){T1CONC:0x09;/NK1SIMC同步;TMR1ON关闭;T1RD16启用;T1GCON=0x40;//0Xe0;/T1GE启用;T1GPOL高;T1GGO完成;T1GSPM禁用;T1GATE=0x04;//TMR3溢出//GSS TMR0A溢出T1Clk=0xA;//TMR 3溢出//CS TMR0a溢出;TMR1H=0x00;TMR1L= 0x00;Time1ReLoVADAL=(UTI1616T)((TMR1H和LT;和8;)TMR1L);/ /加载TMR值以重新加载可变的PIR4BITS。TMR1IF=0;/ /在启用中断之前清除标志。PIE4BIT.TMR1IE=1;//启用TMR1中断。TMR1-启动时间();/启动TMR1}空隙中断高优先级ISRY高(空隙){if(Pr0BIT.In0&I&Apple;Pix0Bix.In0IE=1)/ /检查第一个波束是否已被破坏{PiR0BIT.In0IF=0;/ /切换标志TMR1H=0x00;/ /重置所有定时器寄存器TMR1L= 0x00;TMR3H=0x00;TMR3L= 0x00,TMR3ON=1;//打开Time//T1CONTITS。TMR1ON=1;//打开溢出计数器LATABIT.LATA5=0;//打开BNC };(PIR0BIT.I.1&IF;PAN01I.= 1){PIR0BIT.It1IF=0;/ /切换标志T3CONTIT.TMR3ON=0;/ /关闭定时器//T1CONTIT.TMR1ON= 0;//关闭溢出计数器LATABIT.LATA5=1;//关闭BNC速度(;);空隙中断低优先级IsRyLoad(空隙){if(Pir4BIT.TMR3IF=1)//TMR3中断服务例程{PIR4BITS.TMR3IF=0;TMR3H=0x00;TMR3L= 0x00;}(PiR4BIT.TMR1IF=1)//TMR1中断服务路由器Ne{PiR4BITS.TMR1IF=0;TMR1H=0x00;TMR1L= 0x00;}
以上来自于百度翻译 以下为原文 Hi guys, I have been working on a project where a Timer (TMR3) is used to measure the time between two external interrupts. Another timer (TMR1) is used to count if any overflows have occurred. The first interrupt starts the timer, the second turns it off and calls a function for some subsequent calculations. Then it is displayed on an LCD. PIC18F26K40 @64MHz Internal Oscillator, TMR3 and TMR1 have no pre- or post-scale. TMR3 is sync'd to FCYC and TMR1 is triggered on the TMR3OUT bit. Currently I am displaying both timer values and the calculated value on the LCD. I also have the external interrupts set up to an oscilloscope to accurately measure the time between them. In Excel I have taken the time from the scope and multiplied by FCYC (16MIPS). The problem I have at the moment is random count errors in the main timer, TMR3. I am getting an average of 1,783 more (extra) "ticks" in the TMR registers but its all over the place (see attached JPEG). This is causing significant error in the calculation. If it were consistent, I could subtract this average in the calculation. Here are the relevant segments of code: void OSCILLATOR_Initialize(void) { // NOSC HFINTOSC; NDIV 1; OSCCON1 = 0x60; // CSWHOLD may proceed; SOSCPWR Low power; OSCCON3 = 0x00; // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled; OSCEN = 0x00; // HFFRQ 64_MHz; OSCFRQ = 0x08; // TUN 0; OSCTUNE = 0x00; } void TMR3_Initialize(void) { T3CON = 0x00; //CKPS 1:1; nT3SYNC synchronize; TMR3ON off; T3RD16 enabled; T3GCON = 0x00; //T3GE disabled; T3GTM disabled; T3GPOL low; T3GGO done; T3GSPM disabled; T3GATE = 0x00; //GSS T3G_pin; T3CLK = 0x01; //CS FOSC/4; TMR3H = 0x00; //TMR3H 0; TMR3L = 0x00; //TMR3L 0; timer3ReloadVal=(uint16_t)((TMR3H << 8) | TMR3L); // Load the TMR value to reload variable PIR4bits.TMR3IF = 0; // Clearing IF flag before enabling the interrupt. PIE4bits.TMR3IE = 1; // Enable TMR3 interrupt. } void TMR1_Initialize(void) { T1CON = 0x09; //CKPS 1:1; nT1SYNC synchronize; TMR1ON off; T1RD16 enabled; T1GCON = 0x40; //0xE0; //T1GE enabled; T1GTM enabled; T1GPOL high; T1GGO done; T1GSPM disabled; T1GATE = 0x04; // tmr3 overflow //GSS TMR0_Overflow; T1CLK = 0xA; //tmr 3 overflow //CS TMR0_Overflow; TMR1H = 0x00; TMR1L = 0x00; timer1ReloadVal=(uint16_t)((TMR1H << 8) | TMR1L); // Load the TMR value to reload variable PIR4bits.TMR1IF = 0; // Clearing IF flag before enabling the interrupt. PIE4bits.TMR1IE = 1; // Enable TMR1 interrupt. TMR1_StartTimer(); // Start TMR1 } void interrupt high_priority ISR_high(void) { if (PIR0bits.INT0IF && PIE0bits.INT0IE == 1) //Check if the first beam has been broken { PIR0bits.INT0IF = 0; //Toggle the Flag TMR1H = 0x00; //RESET all TIMER registers TMR1L = 0x00; TMR3H = 0x00; TMR3L = 0x00; T3CONbits.TMR3ON = 1; //Turn on the Timer //T1CONbits.TMR1ON = 1; //Turn on the Overflow Counter LATAbits.LATA5 = 0; //TURN ON BNC } if (PIR0bits.INT1IF && PIE0bits.INT1IE == 1) { PIR0bits.INT1IF = 0; //Toggle the Flag T3CONbits.TMR3ON = 0; //Turn off the Timer //T1CONbits.TMR1ON = 0; //Turn off Overflow counter LATAbits.LATA5 = 1; //TURN OFF BNC Velocity(); } } void interrupt low_priority ISR_low(void) { if (PIR4bits.TMR3IF == 1) //TMR3 Interrupt Service Routine { PIR4bits.TMR3IF = 0; TMR3H = 0x00; TMR3L = 0x00; } if (PIR4bits.TMR1IF == 1) //TMR1 Interrupt Service Routine { PIR4bits.TMR1IF = 0; TMR1H = 0x00; TMR1L = 0x00; } } Attached Image(s) |
|
相关推荐
19个回答
|
|
|
这些陈述的目的是什么?Time3ReLoDava=(UTI1616T)((TMR3H & lt;& 8;)TMR3L);Time1ReLoValAL=(UTI1616T)((TMR1H和lt;lt;8)TMR1L);您所显示的代码只需加载0。这是意料之中的事吗?你有16位模式的定时器吗?
以上来自于百度翻译 以下为原文 What is the purpose of these statements? timer3ReloadVal=(uint16_t)((TMR3H << 8) | TMR3L); timer1ReloadVal=(uint16_t)((TMR1H << 8) | TMR1L); The code you've shown will just load them with 0. Is that expected? Do you have the timers in 16-bit mode? |
|
|
|
|
|
定时器处于16位模式。这些线路使我可以用不同的初始值加载不同的定时器周期。
以上来自于百度翻译 以下为原文 Timers are in 16 bit mode. Those lines are so that I could load them with different initial values for different timer periods |
|
|
|
|
|
使用捕获/比较模块可能更简单?我过去曾做过脉搏测量。只是一个想法…
以上来自于百度翻译 以下为原文 Might be simpler using the capture/compare modules? I have done that in the past for pulse measurements. Just a thought... |
|
|
|
|
|
同意杰克使用捕获/比较模块。我可能错过了一些东西,但我不认为你需要中断Time3和Time1。清除ISR中的TMR3X将引入错误。编辑:显示您的速度()函数。你是按正确的顺序阅读计时器值吗?
以上来自于百度翻译 以下为原文 Agree with Jack on using Capture/Compare module. I might have missed something, but I don't think you need the interrupts for Timer3 and Timer1. Clearing TMR3x in the ISR will introduce error. Edit: show your velocity() function. Are you reading the timers values in the correct order. |
|
|
|
|
|
空隙速度(空隙){LCDA CULL();//这显示LCD上的定时器值,用于调试LCDJETSt*Curror(2,8);无符号int=TMR3A读数();无符号CHAR N[];UToA(n,t,10);LCDPutStr(n);LCDA StI*Curror(2,1);未签名的CHARC[];未签名INTOV= TMR1x读数();UToA(C,OV,10);LCDPutStr(C)///这是实际计算无符号int=TMR1a读数()* 41;///Exchange溢出计数为0.01毫秒/真溢出率为0.004096 s无符号int=tMR3a读数();/当前定时器值无符号int s=(d/1600);/ /将当前计时器计数转换为0.01毫秒/无符号int=t=S+Z;//当前定时器值+ 16位溢出乘以倍数×溢出/ /计算弹丸无符号长速度=(60700/(S+Z));//0.00 1M/S// 2.34英寸=0.0607米,V=DX/DT;CalcCurk(速度);//函数从XXXX转换为xx.xx}
以上来自于百度翻译 以下为原文 void Velocity (void) { Lcd_Clear(); // THIS DISPLAYS THE TIMER VALUES ON THE LCD FOR DEBUGGING Lcd_Set_Cursor(2,8); unsigned int t = TMR3_ReadTimer(); unsigned char n[]; utoa(n,t,10); LCDPutStr(n); Lcd_Set_Cursor(2,1); unsigned char c[]; unsigned int ov = TMR1_ReadTimer(); utoa(c,ov,10); LCDPutStr(c); //This is the actual calculation unsigned int z = TMR1_ReadTimer()*41; //convert overflow count to 0.01 ms //true overflow rate is 0.004096 s unsigned int d = TMR3_ReadTimer(); // Current timer value unsigned int s = (d/1600); //convert current timer count to 0.01 ms //unsigned int t = s + z; // Current timer value + 16 bit overflow multiplied by the # of times overflowed //Calculate the speed of the projectile unsigned long speed = (60700/(s + z)); //0.001m/s //2.34 inches = 0.0607 meters, v = dx/dt; Calc_Speed(speed); //function to convert from XXXX to XX.XX } |
|
|
|
|
|
我认为您应该发布TMR1YRealTimeR()和TMR3x RealTimeReor()代码,只有在POST 5中回答这个问题的方法。
以上来自于百度翻译 以下为原文 I think you should post the TMR1_ReadTimer() and TMR3_ReadTimer() functions (code), only way to answer the question in post#5 |
|
|
|
|
|
除了为两个TMRXYRADIMER()函数显示代码之外,还将一个大小分配给N[]和C[]数组。
以上来自于百度翻译 以下为原文 In addition to showing the code for the two TMRx_ReadTimer() functions, assign a size to the n[] and c[] arrays. |
|
|
|
|
|
无符号int tMR1a读定时器(空隙){UINT1616T ReADVAL;UINT88T Read Valuy;Read Value= TMR1L;Read Value= TMR1H;ReADVAL=((UINT1616T)Read ValueL& lt;and 8;)Read ValLoad;返回ReADVAL;} UTIN1616T TMR3A RealTimeT(空隙){UINT16LT ReADVAL;UINT8YT RealValLoad;UINT88T Read ValoW,Read Value= TMR3L;Read Value= TMR3H;ReADVAL=((Unt1616t)Read ValueL& and;lt;8);Read ValLoad;Read RevAdAL;}此外,我已经将探针附加到未使用的PIN上,并且在TMR3溢出ISR中,我正在切换该PIN以显示溢出频率和启动计时器中的任何延迟,TIGG。GLIN在按钮按压的下降沿,此时正在启动IMT0 ISR。这可能是问题所在,因为在定时器出现溢出之前有一个长而可变的周期,请参阅附加波形。
以上来自于百度翻译 以下为原文 unsigned int TMR1_ReadTimer(void) { uint16_t readVal; uint8_t readValHigh; uint8_t readValLow; readValLow = TMR1L; readValHigh = TMR1H; readVal = ((uint16_t)readValHigh << 8) | readValLow; return readVal; } uint16_t TMR3_ReadTimer(void) { uint16_t readVal; uint8_t readValHigh; uint8_t readValLow; readValLow = TMR3L; readValHigh = TMR3H; readVal = ((uint16_t)readValHigh << 8) | readValLow; return readVal; } Also, I have attached a probe to an unused pin and in the TMR3 Overflow ISR I am toggling this pin to show both the overflow frequency and any latency in starting the timer, triggering on the falling edge of a button press that at the moment is initiating the INT0 ISR. This may be where the issue is, as there is a long and variable period before the timer appears to overflow, see attached waveform Attached Image(s) |
|
|
|
|
|
你说定时器是在16位模式,但是这条代码行说:你的评论说启用,但是T3CON的1位必须设置为高(0x02)以启用16位读/写模式。
以上来自于百度翻译 以下为原文 You say the timers are in 16 bit mode howeer this line of code says otherwise: T3CON = 0x00; //CKPS 1:1; nT3SYNC synchronize; TMR3ON off; T3RD16 enabled; Your comment says enabled however bit 1 of T3CON must be set high (0x02) to enable 16 bit read/write mode. Same issue with Timer3 |
|
|
|
|
|
这一点已经得到纠正,但问题仍然存在。
以上来自于百度翻译 以下为原文 This has been corrected, however the issue still persists. |
|
|
|
|
|
|
|
|
|
|
|
我不这么认为。蓝色的轨迹是按钮捕捉。我看不到任何反弹,是吗?我相信我已经正确地执行了反跳电路,虽然这是一个有用的建议。
以上来自于百度翻译 以下为原文 I don't think so. The blue trace is the button capture. I dont see any bounces, do you? I believe that I have properly implemented debounce circuitry although this is a useful suggestion |
|
|
|
|
|
嗨,一个可能的问题是当你在主循环中访问同一个变量时会发生中断。因为定时器是16位的,所以不能在一个指令中正常地读取它们。因此,如果中断发生在这2行之间,并且改变TMR1H的值,它就会有错误的V。为了避免这种情况,你可以让序列原子(*)或在你的SW中保证在这个序列中不发生中断。
以上来自于百度翻译 以下为原文 Hi, One possible issue is that interrupts occur while you access the same variable in the main loop. Because timers are 16bits you cannot read them aomically (in a single instruction). Therefore if an interrupt occurs e.g. between these 2 lines and you change the value of TMR1H, it will have a wrong value... readValLow = TMR1L; // if interrupt occurs here TMR1H could be changed by your ISR readValHigh = TMR1H; To avoid this, you can either make the sequence atomic (*) or garantee in your SW that no interrupt can occur within this sequence. di(); readValLow = TMR1L; readValHigh = TMR1H; ei(); Regards |
|
|
|
|
|
如果我读了你的定时器设置正确,Time3应该从16 MHz时钟(FoSC/4)运行。这应该导致溢出中断后大约4毫秒。我没有看到在屏幕截图(或者我是在读取范围图像不正确?)编辑:有一个打印错误的时间是244 S/B 4。
以上来自于百度翻译 以下为原文 If I read your timer settings correctly Timer3 should be operating from a 16 Mhz clock (FOSC/4). This should result in an overflow interrupt after approx. 4 mS. I do not see that in your screen shot (or am I reading the scope image incorrectly?). EDIT: had a typo on the time WAS 244 s/b 4 . |
|
|
|
|
|
RISC:我喜欢你的建议,并没有考虑过这种可能性。这是很容易添加的,因此我会。杰克@ kkStack:是的,自从第一次尝试摆脱这个错误以来,我一直在改变东西。我从内部振荡器@ 64 MHz开始,然后添加/切换到没有PLL的16 MHz晶体,然后再次改变配置比特。使用4MHz锁相环16 MHz晶体。在该范围内捕获的是具有4X PLL的16 MHz晶体(因此SW FoSC=64 MHz,FCYC=16 MHz)。在该范围内仍然呈现出真实的奇怪和随机行为。我还尝试在It00ISR中开启定时器之前和之后切换该PIN(用一个γ-DelayyMS(1)来允许。引脚时间切换。有时,我得到两个脉冲,定时器被打开,但总是在按钮按下的下降沿,即使ITCON=0xE3;
以上来自于百度翻译 以下为原文 RISC: I like your suggestion, and hadn't thought about that possibility. It should be pretty easy to add this, and therefore I will. jack@kksound: Yea, I have been changing stuff since the first post trying to get rid of this error(s). I started with the internal oscillator @ 64 MHz, then added/switched to a 16 MHz crystal with no PLL and then changed the config bits again to use the 16 MHz crystal with 4x PLL. Captured in the scope is the 16 MHz crystal with 4x PLL (therefore SW FOSC = 64 MHz, FCYC = 16 MHz). Still getting real weird and random behavior showing up in the scope. I've also tried to toggle this same pin before and after the timer is turned on in the INT0_ISR (with a __delay_ms(1) to allow the pin time to toggle). Sometimes I get two pulses that the timer got turned on but always around the falling edge of the button push, even though INTCON = 0xE3; |
|
|
|
|
|
如果边沿触发的中断在错误的边缘触发(当您选择上升时下降),那么中断引脚的信号是可疑的,它有故障,它上升/下降到缓慢,它反弹,等等。您是否使用PPS特性来将It0函数移动到不同的PIN(默认为R)。B0)?您确定PIN是否设置为数字输入模式(禁用任何模拟特性)?端口B默认为模拟输入模式。
以上来自于百度翻译 以下为原文 If edge triggered interrupts are triggering on the wrong edge (falling when you have rising selected) then the signal to the interrupt pin is suspect, it has glitches, it rises/falls to slowly, it bounces, etc. Have you used the pps feature to move the INT0 function to a different pin (default is RB0)? Are you sure that the pin is set for digital input mode (any analog feature disabled? PORT B defaults to analog input mode). |
|
|
|
|
|
我不确定这是否会有帮助,只是大声思考。如果我单枪匹马怎么办?也许在CalcSuxSuffE()中(从Itn1 ISR调用的“速度”),添加一个循环来轮询连接到一个按钮的PIN,并且循环使它在那里等待,中断被禁用,直到按钮被按下,重新启用中断以及清除TMR寄存器。我确信这可能会有帮助,或者可能没有帮助。在这一点上,为了解决这个问题,只需要刺一刀。
以上来自于百度翻译 以下为原文 I'm not sure if this will help or not, just sort of thinking out-loud. What if I make it a single shot? Perhaps in Calc_Speed(), (which is called from Velocity(), which is called from the INT1 ISR), add a loop to poll a pin attached to a button, and loop causes it to wait there, with interrupts disabled, until the button is pressed, re-enabling interrupts as well as clearing the TMR registers. Not entirely sure how this may help, or may not help. Just sort of stabbing at things to try to solve it at this point. |
|
|
|
|
|
杰克@ KkStack:我使用PPS寄存器来移动中断引脚。我确信,LAT、TRIS、安塞尔、WPU和ODCON寄存器与它们相关联是正确的。此外,引脚被设置,并且在初始化中断之前系统被初始化了相当长的一段时间。系统启动,设置振荡器和引脚,然后初始化LCD(取30MS),然后切换3个引脚,最后中断在主环路之前初始化。这里是PPS输入更改例程,以确保我正确地进行了:BoOL状态=(无符号CHAR)GIE;PPSROCK=0x55;PPSLoCK=0xAA;PPsLoClbs.PPsLoCl= 0x00;;/ /解锁PPS It1ppsBut.It1PPS= 0x0a;//RB5(S4)-&Gt;ExtXIt:It1;In0ppsBist.In0PPS= 0x0d;//RB2(S1)-& Ext;It0;PPSROCK=0x55;PPSROCK=0xAA;PPSROCKIT BITSPLOCK=0x01;//锁定PPS GIE=状态;
以上来自于百度翻译 以下为原文 jack@kksound: I have used the PPS register to move the interrupt pins. And I am sure that the LAT, TRIS, ANSEL, WPU and ODCON registers associated with them are correct. Also, the pins are set-up and the system is initialized for quite a while before the interrupts are initialized. The system is started, which sets up the oscillator and pins, then the LCD is initialized (which takes ~30ms) then 3 pins are toggled and then finally the interrupt is initalized just before the main loop. Here is the PPS input change routine, to ensure that I did it properly: bool state = (unsigned char)GIE; GIE = 0; PPSLOCK = 0x55; PPSLOCK = 0xAA; PPSLOCKbits.PPSLOCKED = 0x00; // unlock PPS INT1PPSbits.INT1PPS = 0x0A; //RB5 (S4)->EXT_INT:INT1; INT0PPSbits.INT0PPS = 0x0D; //RB2 (S1)->EXT_INT:INT0; PPSLOCK = 0x55; PPSLOCK = 0xAA; PPSLOCKbits.PPSLOCKED = 0x01; // lock PPS GIE = state; |
|
|
|
|
|
喘气在稻草和不确定它是相关的问题在这里,但你有没有照顾的NVMeRG勘误问题的K40图片?
以上来自于百度翻译 以下为原文 Gasping at straws and not sure it is relevent to the issues here but have you taken care of the NVMREG errata issue of the K40 pics? |
|
|
|
|
只有小组成员才能发言,加入小组>>
5425 浏览 9 评论
2125 浏览 8 评论
2041 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3294 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2338 浏览 5 评论
930浏览 1评论
796浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
750浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
805浏览 0评论
692浏览 0评论
/6
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-4-5 05:24 , Processed in 1.954214 second(s), Total 111, Slave 95 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1547