完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
您好,我正在使用计时器0、定时器1和HW UART在一个项目中接收中断。控制器是16F1947。我想知道在UART字符接收之前是否有一个定时器中断会使这个字符松动。在EXE期间是否有可能丢失任何串行输入数据。目前,我正在检查接收中断中的每个字符,并使用开关case语句来填充缓冲区。下面一个是单独的问题;如果我打算只检查预期数据的第一个字符,然后在FIFO缓冲器中填充期望的字符被满足,在读(1)循环时,缓冲区读取缓冲区(一些字符丢失),由于触发计时器中断,所以不能很好地读取缓冲区。有没有办法在读取FIFO缓冲器之前禁用计时器中断。
以上来自于百度翻译 以下为原文 Hello, I am using timer 0,Timer 1 and HW UART Receive Interrupts in a project.The controller is 16F1947. I want to know if a timer interrupt fires just before the reception of a character from UART will I loose that character.Is there any possibility of loosing any serial incoming data during the execution of timer interrupts. Currently I am checking every character within the Receive Interrupt and filling a buffer accordingly using switch case statements. Below one is a separate question; If I intend to do this by only checking first character of the intended data and fill a FIFO buffer when the expected character is met and reading the buffer within the while(1) loop I can not read the buffer(some characters are lost) very well due to the firing timer interrupts.Is there any way to disable the timer interrupts just before reading the FIFO buffer. Thanks in advance, |
|
相关推荐
12个回答
|
|
|
NoOnly如果在中断服务中执行这么多代码,那么USAT会接收到三个字符并得到一个溢出错误。一个写得好的中断服务应该尽可能地减少,并且尽可能快地再次退出。你的代码,我们可以告诉你出了什么问题。(我使用的是精确的设备,1KHz定时器中断和快速串行I/O都在USAT上,并且没有丢失任何字符。)
以上来自于百度翻译 以下为原文 No Only if you execute so much code inside the interrupt service that the USART receives three characters and gets an overrun error. A well written interrupt service should do the minimum possible, and exit again as quickly as possible. It's more likely a bug in the code that you have not posted. Post your code, and we can probably tell you what is going wrong. (I'm using that precise device, with 1kHz timer interrupts and rapid serial I/O on both USARTs, and not losing any characters.) |
|
|
|
|
|
感谢您的响应。请查找下面的代码,其中只发送相关的部分,*定义eSuART1xTXA BuffelySub 16μ定义EuSARTAR1RxBuffelySosig 256定义EuSART1O1DATARADY(EASARTAR1RXCOUNT)易失性无符号char EUSATAR1TXHORD=0;易失性无符号char EUSATAR1TXTRAY=0;易失签名char EUARTAR1TXBuff[EUARART1OXTXBAUBRIZHORIZ];易失性无符号CHAREUARTAR1RXHORD=0;易失性CHAR未签名EUARTAR1RXTRAY=0;易失性CHAR无符号EUARTAR1RXBuff[ESOART1ORXBuffelySimple ];易失性无符号char EUSATAR1RXCOUNT;CHAB HBSPLASE(48);无效在改变状态RC1IEA比特=0之前,EUARTAR1X初始化(空隙){//禁止中断;BUD1CONE=0x08;RC1STA= 0x90;TX1Reg=0x0;TX1STA= 0x25;SP1BRGL= 0x0;SP1BRGH=0x0;/ /初始化驱动状态EUARTAR1TXHORD=0;EUARTAR1TXTRAY=0;ESOART1TXBUFFER剩余= SIZEOF(E)USAART1RXHORD=0;EUARTAR1RXTRAY=0;EUARTAR1RXCOUNT=0;RC1IEHIT比特=1;}虚振器初始化(空隙){//SCS FoC;SPLLN禁用;IrCF 8MHZYHF;OSCCon=0x70;//TUN 0;OSCUNTY=0x00;/ /设置二级振荡器OSCSTAT=0x00;/ /等待PLL稳定(PLLR==)x00=0x00;LATA= 0x20;LATF=0x00;LATD= 0x01;LATC= 0x1a;LATG=0xFd;TPISF=0x01;TrISG= 0x24;TrISD=0B000 0 01;TrISE=0xF0;TrISB=0xFD;TrISC= 0xBC;TrISA=0xC0;ANSELE=0x00;Audio=0x00;ANSELG=0;0){}}空隙PixMauner-Read初始化(空隙){APFCON= 0OSCCon=0x70;OSCSTAT=0x00;OSCTUNE=0x00;//(PLLRL比特=0){空隙}{PEIEA位=1;GieZeBit=1;PinsiMaungRixAlpIZILIZE();WDTTIX初始化();EUTART1IX初始化();T1CONN=0x21;T1GCONN=0x0;TMR1IFN1比特=0;TMR1H=0xFF;TMR1L= x00;ANSELLA=0x00;opthy.Re.b7= 0x0CDayIn();Delay-Fix=(200);TMR1IEHEL比特=1;计数=0;TuthiVar=0;I=0;LCDY-CMD(Y-LCDA清除);char EuSART11Read(空隙){Car Read Value= 0;而(0=eSARTAR1RXCOUNT){}读值=EUARTAR1RXBuff[ESOART1RXTUR++];IF(SIUART1RxBuffels:lt=;EUSATAR1RXTAI)0x0A;尾=0;} rC1IExBIT=0;RC1IE1比特=1;返回读取值;}空隙EUARART1IORIVEVIO.ISR(空隙){RC1IFNITBIT==0;IF(1=RC1STA.OErr){//EUSATAR1错误-重新启动RC1STA.CREN=0;RC1STA.CREN=1;} EUARTAR1RXBuff[ESOART1RXCHIDE]=RC1Reg;CMDyBoe= EUSATAR1RXBuff[EUSA] L){EuSART1RX如果(SIUART1RxBuffels<= EUSATAR1RXHORD){EUARTAR1RXCHILD=0;} EUTARTAR1RXCOUNT++;}空Time1IsR(空隙){TMR1IFN1比特=0;塌陷时间+++;如果(塌陷时间T>333)/读过滤按钮输入{if(Purb.B0==0)ButoOnClut+++;如果(ButoOnng&G.&&Po.B.B==1){PUL)RT1RXHead} //更新4x7段DISPADSDSPBFFF(0)=计数/ 1000;DSPBuff[1 ]=(计数/ 10)%10;DSPBuff[3 ]=计数%10;DISSPORK0=10;DISSPORK1=α;DISSPORK2=;DSPSIRA++;如果(DSPSIRA==γ){DSPSIRA=;} DAT= DSPDATACONV[DSPBuff[DSPSIRA] ];SeeOK=TRUE;ButoOnCub计数=0;S塌陷时间=0;}= DAT.B4;O-SEGF=DAT.B5;Y SeGG=DAT.B6;开关(DSPSIRA){{ DISSPORK0=1;中断;} DISSPORK1=1;中断;} DISSPORK2=1;中断;} PaseK3=1;中断;} TMR1H=0XFF;TMR1L=0x0A;KyyRead(&;TuSuVar);和/或读取16输入键盘3无效。DAT.B0;γSEGB= DAT.B1;Y-SeCc=DAT.B2;//中断处理程序if(PeeAdBIT=1和AMP;RC1IEHYBIT=1和&;RC1IF1位=1){EntART1ILAccEvEvIsR();}否则(ItNo.Peee=1和&;PIE1.TX1IE=1和&;PIR1.TX1IF=1){EuSART11EngulixISR();}否则(PEEAYBIT=1和AMP&TMR1IEYBIT=1和&);中断(空){(1){ Time1IsIr-();} }无效的主(){init();}(/)1,{ / /如果定时器1中断在常规工作下被禁用,否则它会松动USAT 115200 IF(EUARTAR1A DATAARADY){字符=0=0,读写=EUARTAR1A读()的字符/ /波特率;{De}{HBsPlas[j]=EuStAR1YRE(+);j++;}(EUARTAR1RXCOUNT!)= 0);} LCDIOUT(2,1,&HBSBuffer(6));MeMSET(HBSBuffer,0,StLLEN(HBSBuffer));
以上来自于百度翻译 以下为原文 Thanks for your response.Please find below the code where only the related parts are sent, #define EUSART1_TX_BUFFER_SIZE 16 #define EUSART1_RX_BUFFER_SIZE 256 #define EUSART1_DataReady (eusart1RxCount) volatile unsigned char eusart1TxHead = 0; volatile unsigned char eusart1TxTail = 0; volatile unsigned char eusart1TxBuffer[EUSART1_TX_BUFFER_SIZE]; volatile unsigned char eusart1TxBufferRemaining; volatile unsigned char eusart1RxHead = 0; volatile char unsigned eusart1RxTail = 0; volatile char unsigned eusart1RxBuffer[EUSART1_RX_BUFFER_SIZE]; volatile unsigned char eusart1RxCount; char HBSBuffer[48]; void EUSART1_Initialize(void) { // disable interrupts before changing states RC1IE_bit=0; TX1IE_bit=0; BAUD1CON = 0x08; RC1STA = 0x90; TX1REG=0X0; TX1STA = 0x25; SP1BRGL = 0x44; SP1BRGH = 0x0; // initializing the driver state eusart1TxHead = 0; eusart1TxTail = 0; eusart1TxBufferRemaining = sizeof(eusart1TxBuffer); eusart1RxHead = 0; eusart1RxTail = 0; eusart1RxCount = 0; RC1IE_bit=1; } void OSCILLATOR_Initialize(void) { // SCS FOSC; SPLLEN disabled; IRCF 8MHz_HF; OSCCON = 0x70; // TUN 0; OSCTUNE = 0x00; // Set the secondary oscillator OSCSTAT = 0x00; // Wait for PLL to stabilize while(PLLR == 0) { } } void PIN_MANAGER_Initialize(void) { APFCON = 0x00; LATB =0x00; LATA =0xDF; WPUG =0x20; LATF =0x00; LATE =0x00; LATD =0x01; LATC =0x1A; LATG =0x00; WPUB =0xFD; TRISF=0x01; TRISG =0x24; TRISD =0B00000001; TRISE =0xF0; TRISB =0xFD; TRISC =0xBC; TRISA =0xC0; ANSELE =0x00; ANSELF =0x00; ANSELG =0x00; ANSELA =0x00; OPTION_REG.B7 = 0x0; OSCCON = 0x70; OSCSTAT = 0x00; OSCTUNE = 0x00;// while (PLLR_bit==0) {} } void init (void) { peie_bit=1; gie_bit=1; PIN_MANAGER_Initialize(); OSCILLATOR_Initialize(); WDT_Initialize(); EUSART1_Initialize(); T1CON = 0x21; T1GCON=0X0; TMR1IF_bit = 0; TMR1H = 0XFF; TMR1L = 0x0A; INTCON = 0xC0; lcd_init(); delay_ms(200); BUZZER=false; TMR1IE_bit = 1; count=0; tus_var=0; i=0; lcd_cmd(_lcd_clear); readletter=0; } char EUSART1_Read(void) { char readValue = 0; while(0 == eusart1RxCount) { } readValue = eusart1RxBuffer[eusart1RxTail++]; if(sizeof(eusart1RxBuffer) <= eusart1RxTail) { eusart1RxTail = 0; } RC1IE_bit = 0; eusart1RxCount--; RC1IE_bit = 1; return readValue; } void EUSART1_Receive_ISR(void) { RC1IF_bit == 0; if(1 == RC1STA.OERR) { // EUSART1 error - restart RC1STA.CREN = 0; RC1STA.CREN = 1; } eusart1RxBuffer[eusart1RxHead] = RC1REG; cmd_letter=eusart1RxBuffer[eusart1RxHead]; if (sizeof(eusart1RxBuffer)<=eusart1RxHead) { eusart1RxHead = 0; } eusart1RxCount++; } void Timer1_ISR(void) { TMR1IF_bit=0; collapsed_time++; if(collapsed_time > 333) //Reading filtered button input { if(PORTB.B0==0)button_count++; if(button_count > 21 && PORTB.B0==1){PULSE_OK=true;button_count=0;collapsed_time=0;} } //Updating 4x7 segment displays dspbuff[0]=count/1000; dspbuff[1]=(count/100)%10; dspbuff[2]=(count/10)%10; dspbuff[3]=count % 10; disp_k0=0; disp_k1=0; disp_k2=0; disp_k3=0; dspsira++; if (dspsira==4 ) {dspsira=0;} dat= dsp_dataconv[dspbuff[dspsira]]; _sega=dat.b0; _segb=dat.b1; _segc=dat.b2; _segd=dat.b3; _sege=dat.b4; _segf=dat.b5; _segg=dat.b6; switch(dspsira) { case 3:{disp_k0=1;break;} case 2:{disp_k1=1;break;} case 1:{disp_k2=1;break;} case 0:{disp_k3=1;break;} } TMR1H=0XFF; TMR1L=0X0A; key_read(&tus_var); // Reading 16 input keypad } void interrupt(void) { // interrupt handler if(PEIE_bit == 1 && RC1IE_bit == 1 && RC1IF_bit == 1) { EUSART1_Receive_ISR(); } else if(INTCON.PEIE == 1 && PIE1.TX1IE == 1 && PIR1.TX1IF == 1) { EUSART1_Transmit_ISR(); } else if(PEIE_bit == 1 && TMR1IE_bit == 1 && TMR1IF_bit == 1) { Timer1_ISR(); } } void main() { init (); } while(1) { //If Timer 1 interrupt is disabled below routine works otherwise it looses some characters //Baud rate of the USART 115200 if(EUSART1_DataReady) { j=0; readletter=EUSART1_Read(); if(readletter=='<'){ do{ HBSBuffer[j]=EUSART1_Read(); j++; }while( eusart1RxCount!=0); } } lcd_out(2,1,&HBSBuffer[6]); memset(HBSBuffer,0,strlen(HBSBuffer)); |
|
|
|
|
|
是的,RIC建议你的Time1IsR()做得太多了。更改您的方法以尽可能少地在中断处理程序和轮询中进行主循环中要做的工作的指示。
以上来自于百度翻译 以下为原文 Yeah, as Ric suggested your Time1_ISR() is doing far too much. Change your approach to do as little as possible in the interrupt handler and poll for indications of work to do in the main loop. |
|
|
|
|
|
在ISR中有616位分区操作正在进行中,这应该是您修复的第一件事。在主代码中显示显示数据,这样就可以在ISR中获得可用的段值。
以上来自于百度翻译 以下为原文 You've got six sixteen-bit division operations going on in the ISR; that should be the first thing you fix. Render your display data in your main code so you already have the segment values available in the ISR. |
|
|
|
|
|
你的意思是,我将把所有刷新代码的代码放入主循环中。
以上来自于百度翻译 以下为原文 Do you mean that i shall port all code for refreshing displays into the main loop. Thanks to all for the tips sonra far. |
|
|
|
|
|
不是刷新显示的代码,而是决定显示数字的代码。将创建DSPBFF的代码移动到主循环中,然后ISR正在编写已经存在的段值。
以上来自于百度翻译 以下为原文 Not the code for refreshing the display, the code that determines what numbers will appear on the display. Move the code that creates dspbuff into your main loop, then the ISR is just writing the already-existing segment values. |
|
|
|
|
|
我会尝试你的建议。一个问题是,如果我能在读取FIFO缓冲器之前禁用主循环中的定时器中断,然后在读取缓冲器之后重新启用它。在我看来,它似乎不起作用。
以上来自于百度翻译 以下为原文 I will try your suggestion.A side question is if i can disable the timer interrupt within the main loop just before I read the FIFO Buffer and then re enable it after the buffer is read.It seems is does not work in my case. |
|
|
|
|
|
不会因为缓冲区的阅读而产生问题。如果你花费太长时间来维护计时器中断,那么在它们被放入缓冲区之前,你会丢失字符。注意,这不会造成伤害,但是这个指令是无意义的,这是一个只读标志。唯一的办法是通过阅读RCREG,你稍后会做一些说明。
以上来自于百度翻译 以下为原文 It won't as the problem isn't in reading FROM the buffer. If you're spending too long servicing timer interrupts, then you will be missing characters before they even get put into the buffer. Also note, it won't hurt, but this instruction is pointless RC1IF_bit == 0; That is a read-only flag. The ONLY way to clear it is by reading RCREG, which you do a few instructions later anyway. |
|
|
|
|
|
不会因为缓冲区的阅读而产生问题。如果你花费太长时间来维护计时器中断,那么在它们被放入缓冲区之前,你会丢失字符。注意,这不会造成伤害,但是这个指令是无意义的,这是一个只读标志。清除它的唯一方法是读RCREG,你稍后会做一些说明。也不应该(即使它是一个无用的指令):RC1IF=0;因为双等号(==)在这一点上是不合适的?只是一个挑剔的小无关紧要的事情……可能是代码开始时的一个排版。
以上来自于百度翻译 以下为原文 It won't as the problem isn't in reading FROM the buffer. If you're spending too long servicing timer interrupts, then you will be missing characters before they even get put into the buffer. Also note, it won't hurt, but this instruction is pointless RC1IF_bit == 0; That is a read-only flag. The ONLY way to clear it is by reading RCREG, which you do a few instructions later anyway. Also should that not be (even if it is a useless instruction) : RC1IF = 0; since a double equal sign (==) would be inappropriate at this point? Just a picky little unimportant thing...and probably a typo in the beginning listing of the code. |
|
|
|
|
|
我的意思是,我不能禁用while循环中的Time1或全局中断。16F不是支持这一点,也不是说直接写TMR1I/GEE=0;
以上来自于百度翻译 以下为原文 I meant I can no disable the Timer1 or Global Interrupt within while loop.Does not 16F support this or is that not that straightforward just to write TMR1IE/GIE=0; |
|
|
|
|
|
每个单独的中断源都有一个特定的中断使能位(即TIMR1IE),并且还有一般的中断使能位(GIE),它将禁用所有中断。此外,PEI-位将禁用外围中断。具体地说:PIR1BITS.TMR1IE=0;将禁用定时器1中断。ItCnButs.GEE=0;将禁用所有Ipututh.AdStNCONTITES。PEI= 0;将禁用大部分外围中断。S.
以上来自于百度翻译 以下为原文 Each individual interrupt source will have a specific interrupt enable bit(ie TIMR1IE) and there is also the general interrupt enable bit(GIE) which will disable all interrupts. Also the PEIE bit will disable the peripheral interrupts. Specifically : PIR1bits.TMR1IE = 0; will disable the timer 1 interrupt. INTCONbits.GIE = 0; will disable ALL interupts. And INTCONbits.PEIE = 0; will disable MOST of the peripheral interrupts. See the datasheet section on interrupts for more specifics. |
|
|
|
|
|
是的,但是正如我已经解释过的,当问题在定时器中断服务中停留太长时间时,这将对你毫无帮助。阻止这种情况发生的唯一方法是:(1)重写它以使它更快,或者(2)永远不能启用定时器中断。
以上来自于百度翻译 以下为原文 Yes, but as I already explained, that's not going to help you at all, when the problem is staying inside the timer interrupt service for too long. The only way to stop that happening is: [1] rewrite it to make it quicker, or [2] never enable timer interrupts at all |
|
|
|
|
只有小组成员才能发言,加入小组>>
MPLAB X IDE V6.25版本怎么对bootloader和应用程序进行烧录
503 浏览 0 评论
5812 浏览 9 评论
2350 浏览 8 评论
2237 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3544 浏览 3 评论
1160浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
1122浏览 1评论
我是Microchip 的代理商,有PIC16F1829T-I/SS 技术问题可以咨询我,微信:A-chip-Ti
889浏览 1评论
MPLAB X IDE V6.25版本怎么对bootloader和应用程序进行烧录
503浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-14 08:06 , Processed in 1.055248 second(s), Total 95, Slave 78 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1352