完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我使用的是PIC16F1788,我已经通过RS232建立了与超级终端的通信。在Web上彻底搜索之后,我了解了USAT正在工作的方式,并且在主程序中编写了一个例程,它正在编写/读取RS232中的字符(或字符串)。但是,老实说,我还不明白USAT是如何与中断一起使用的。我想实现如下:我有一个计数器,它计数一些事件,当我从超级终端发送字符时,我想激活一个计数器,它在随机时间间隔(事件发生时)在超级终端上发送时间戳。有人能解释一下EUSA是怎样的吗?RT可以与中断一起使用吗?如何通过中断发送或接收字符?
以上来自于百度翻译 以下为原文 I'm using the PIC16F1789 and I have managed to establish the communication with the HyperTerminal over RS232. After a thorough search in the web, I've understood the way that the USART is working and I've written a routine in the main program which is writing/reading a character (or a string) to/from RS232. But, to be honest, I haven't understood how the USART can be used with the interrupts. Basically, what I want to implement is the following: I have a counter which is counting some events and when I send character from the HyperTerminal, I want to activate a counter which is sending at random time intervals (when an event occurs) the timestamp at the HyperTerminal. Could someone explain me how the EUSART can be used with the interrupts? How can we sent or receive a character via the interrupts? |
|
相关推荐
12个回答
|
|
中断不会发送任何东西。中断只会改变执行流程。一旦发生某种事件,程序停止,中断代码开始执行和执行,直到代码决定返回执行主程序。我认为您不需要中断来执行所描述的一组任务。
以上来自于百度翻译 以下为原文 Interrupts don't send anything. Interrupts merely change execution flow. Once some sort of event happens, your program stops and an interrupt code starts executing and executes until the code decides to return back to executing the main program. I don't think you would need interrupts to perform the set of tasks you're describing. |
|
|
|
要清楚,你不需要中断你所描述的内容,通常当你每次只接收一个字符时,你可以在主循环中足够快地对USAT进行轮询。当你的代码忙于做其他事情时,中断变得有用,并且你计划接收“完全消息”。作为“hello & lt;Cr & gt”或类似的:中断代码捕获每个字符,因为它从另一侧到达并将其存储到缓冲器中,并且将升起一个标志,然后接收终止符。此时,您的主循环可以“查看”并处理完整的消息。
以上来自于百度翻译 以下为原文 To be clear, you don't need interrupts for what you describe, and generally when you're going to receive only one char at a time and you can poll the USART quick enough in the main loop. Interrupts become useful when your code is busy doing other things and you plan on receiving "full messages" such as "HELLO |
|
|
|
也许我的描述不是那么精确。我不想只发送一个字符,但是,在我的实现的后面一步,我想发送一个字符串,这些字符将存储在ANEEPROM中,它们将在LCD上显示。很清楚,您所描述的是什么,但我不理解的是,实际上,什么时候PC进入I?锶?什么是中断主执行并进入ISR的事件?为什么我需要一个中断来发送一个字符串,因为我知道什么时候发送它们,这是我自己的决定(在主程序中)当我发送它们的时候?相反,我不知道什么时候收到字符串。据我所知,USAT中断不像其他普通中断,当发生事件(寄存器溢出、外部事件等)时,引发一个标志,主程序的执行中断。ED来服务这个事件,一旦我们清除这个标志,PC返回主程序。
以上来自于百度翻译 以下为原文 Maybe my description was not so precise. I don't want to send only a character but, in a later step in my implementation, I want to send a string of characters which will be stored in an EEPROM and they will be displayed at an LCD. It's clear what you are describing but what I haven't understood is, practically, when does the PC enter the ISR? What is that event that interrupts the main execution and enters the ISR? Why do I need an interrupt to send a string of characters since I know when to send them and it's my own decision (in the main program) when I'll send them? On the contrary, I don't know when I'm gonna receive a string of character. As far as I have understood, the USART interrupts are not like the other ordinary interrupts, where when an event occurs (register overflow, external event, etc.) a flag is raised and the execution of main program is interrupted to serve this event and once we clear this flag, the PC returns to the main program. |
|
|
|
不,发送你不需要它们-我总是劝阻使用IRQ,因为我说的是接收。我不会说收到IRQ是“奇怪”的——它会在收到字符后发生。考虑到TX IRQ,嗯,是的,这是有点“特殊”的,因为缓冲区是空的(这是我阻止的原因之一)。
以上来自于百度翻译 以下为原文 No, for sending you don't need them - and I always discourage using IRQs for that I was talking about receiving. I would not say IRQ on receive is "strange" - it will happen as soon as a char is received. Thinking of TX IRQ, well yes, this is a bit "special" since it happens when the buffer is empty (that's part of the reasons I discourage that). |
|
|
|
对于USAT接收中断,只要一个完整的字符在接收缓冲器中。对于USAT传输中断,一旦发送缓冲器准备好了另一个字符。(这意味着如果你没有任何可以发送的东西,你必须禁用它们,这可能会变得相当混乱。正如Cinzia所说,只使用接收中断更常见。除非代码需要同时做其他事情。否则,它们与其他中断完全相同。接收设置RCIF标志,触发中断。“清除标志”不返回PC到主程序,当中断服务程序退出时,它停止它再次中断。
以上来自于百度翻译 以下为原文 For USART receive interrupts, as soon as a complete character is in the receive buffer. For USART transmit interrupts, as soon as the transmit buffer is ready for another character. (That means you have to disable them if you don't have anything ready to send, which can get quite messy. As Cinzia stated, it's more common to only use receive interrupts. You don't, unless your code needs to be doing something else at the same time. They are exactly the same as other interrupts. Receive sets the RCIF flag, which triggers the interrupt. Transmit sets the TXIF flag, which triggers an interrupt. "Clearing the flag" doen't return the PC to the main program, that just stops it re-interrupting when the interrupt service routine is exited. |
|
|
|
Hi,Durfys,一种看待这个问题的方法,即中断是计算机硬件调用的函数,而不是程序中的调用语句。在XC8中,要调用的函数由函数名前的“中断”来标识。实际函数名并不重要,您PIC16微控制器只能有一个中断功能,因为它是由硬件调用的,中断函数不能有任何参数,它不能返回一个函数值。n个程序,你可以使用全局变量、全局结构和全局数组。有几个硬件事件可以激活中断处理程序的功能。当你进入中断函数时,你必须找出你在那里的原因。有一组SFR寄存器告诉:PiR1,PiR2…外围中断请求X,您从这些位中找出原因。还有另一套SFR寄存器:PIE1、PY2…在您的主程序中,外围中断使能X设置PIEx位以启用您希望发生的那些中断。您可以从中断处理程序调用其他函数,但有理由不要过度使用。最好避免在主线代码和中断CON中调用相同的函数。如果需要的话,XC8编译器可以在这附近工作。如果使用中断来接收UART中的字符,则可以创建一个全局数组作为接收缓冲区,具有类似的全局INT作为缓冲区中的下一个空闲位置的索引。在中断处理程序中,将接收到的字符放置在缓冲区数组中,并递增索引变量。然后清除中断标志:PrI1BITS.RCIF=0;结束中断句柄:结束括号:},不返回语句,编译器将处理中断处理程序PROLO和EXROG代码。D中断处理程序。这是对编译器的警告,这个变量可能由于编译器无法知道的原因而改变,因此必须在使用时从内存中读取,而不是优化。
以上来自于百度翻译 以下为原文 Hi, dirfys, One way to look at this, is that interrupt is a function that is called by the hardware of the computer, not by a call statement in the program. In XC8, the function to be called is identified by the keyword: 'interrupt' before the function name. void interrupt InterruptManager (void) { ... The actual function name doesn't matter, you cannot use the name anywhere else, but it must be there. On PIC16 microcontrollers, there can be only one interrupt function. Since it is called by the hardware, the interrupt function cannot have any arguments, and it cannot return a function value. To communicate between interrupt code and your main program, you may use global variables, global structs and global arrays. There are several hardware events that may activate the interrupt handler function. When you get into the interrupt function, you will have to figure out the reason you are there. There are a set of SFR registers telling: PIR1, PIR2 ... Peripheral Interrupt Request x, You sort out the reason from those bits. There is another set of SFR registers: PIE1, PIE2 ... Peripheral Interrupt Enable x, In your main program, set PIEx bits to enable those interrupts you want to happen. You may call other functions from the interrupt handler, but there are reasons to not overdo this. It is best to avoid calling the same functions both in mainline code and in interrupt context, XC8 compiler can work around this if it have to. To use interrupts for receiving characters from UART, you may make a global array to act as receive buffer, with a similar global int to act as index to the next free location in the buffer. In the interrupt handler, place the character received in the buffer array, and increment the index variable. Then clear the Interrupt Flag: PIR1bits.RCIF = 0; End the interrupt handler with a ending brace: } , no return statement, the compiler will take care of interrupt handler prolog and epilog code. There is a C language specifier 'volatile' to use with variables that will be shared between main code, and interrupt handler. volatile int Index = 0; /* Index in UART receive buffer */ This is a warning to the compiler, that this variable may change for reasons that the compiler cannot know, and thus must be read from memory when it is used, not optimized away. Regards, Mysil |
|
|
|
当你需要快速处理某件事之后,你会使用中断。假设一个UART字符到达。一旦PIC收到UART字符,你必须在下一个字符到达之前做一些事情。否则,字符将丢失。对于这个问题,你是否需要一个中断。如果你收到8MUDD速率的UART数据,那么字符之间只有10条指令。这是一个很短的时间,这是不够的,进入中断,做一些事情,然后退出。所以,中断是没有意义的。你必须禁用它们,坐在主循环中并逐个接收字符。如果你接收到1MUAUD速率的UART数据,那么字符之间有80条指令。这不足以在主循环中做一些有意义的事情,但是使用中断是足够的。因此,您创建一个中断来接收字符。一个字符到达,中断开始,你接收字符,存储它并留下中断。到那时,可能还有20-30条指令剩下,直到下一个字符。这些指令将在等待中断时由主代码使用。如果接收到9600波特,则中断之间有8300条指令。最可能的是,处理所有的主循环任务就足够了,一旦完成,就可以检查新字符是否到达。由于传输速度太慢,所以不需要中断。虽然,您仍然可以使用中断,但是只有中断不干扰其他的YETFLASH进程。现在,您收到9600波特,但是您的主循环执行长时间的任务,需要花费超过8300条指令才能完成。虽然传输速度很慢,但代码速度较慢,而且需要中断代码才能及时到达字符。
以上来自于百度翻译 以下为原文 You use interrupt when you need to process something fast after it happens. Say, an UART character arrives. Once the PIC received an UART character, you must do something before the next character arrives. Otherwise, the character will be lost. Whether you need an interrupt for this is the question of timing. If you receive UART data at 8MBaud rate then there's only 10 instructions between characters. This is such a short time, that it is not enough to enter the interrupt, do something and exit. So, interrupts are meaningless. You must disable them, sit in the main loop and receive characters one by one. If you receive UART data at 1MBaud rate then there's 80 instructions between characters. This is not enough to do something meaningful in the main loop, but it is enough to use interrupts. So, you create an interrupt for receiving characters. A character arrives, interrupt starts, you receive character, store it and leave the interrupt. By that time, there may be still 20-30 instructions left until the next character. These instructions will be utilised by the main code while it is waiting for the interrupt. If you receive at 9600 baud, then there's 8300 instructions between interrupts. Most likely, it is enough to process all your main loop tasks, and once you're done you can check if a new character arrived or not. Since the transmission is so slow, there's no need for the interrupt. Although, you still may use an interrupt, but only if the interrupt doesn't interfere with other, yet faster processes. Now, you receive at 9600 baud, but your main loop is performing lengthy tasks which take longer than 8300 instructions to complete. Even though the transmission is slow, your code is yet slower, and again you need to interrupt your code to get to your characters in time. |
|
|
|
NothGee的一个很好的建议。底线是,如果需要的话中断可以是很好的,但并不总是最好的方法,而且调试很困难,尤其是如果你不熟悉中断处理的概念。
以上来自于百度翻译 以下为原文 Great advice by NorthGuy. The bottom line is, interrupts can be great IF YOU NEED THEM, but are not always the best way to do something, and can make debugging difficult, particularly if you are not familiar with the concepts of interrupt processing. |
|
|
|
您的分析非常有用。因此,如果我们读取主循环中接收到的字符,那么这可以作为主循环中的以下代码完成吗?主循环中的代码是否正确?顺便说一下,在这个例子中,我通过计算传入字符来计算一个数字(使用一个变量)。
以上来自于百度翻译 以下为原文 Your analysis was very helpful. Thus, in case that we read the received characters in the main loop, this can be done as the following code in the main loop? void main(void) { //*** PIC Initialization Init_Clock(); Init_PortA(); Init_PortB(); Init_PortC(); Init_PortD(); Init_PortE(); __delay_ms(1000); //ADC Initialization Init_ADC(); //Fixed Voltage Reference (FVR) Initialization Init_FVR_APF(); //Comparator1 Initialization Init_Comparator1(); //LCD initialization EN = 0; InitLCD(); //EUSART initialization Init_EUSART(); /*** Configure TMR0 that is used for the Interrupts***/ TMR0_config(); //*** Configure TMR1 that is used for the Real Time Clock TMR1_config(); // Initialize the 'Poll_Buttons_cntr' Poll_Buttons_cntr = 0; INTCONbits.GIE = Enabled; //Enable Global Interrupts INTCONbits.PEIE = Enabled; //Enable Peripheral Interrupts //Retrieve the last values of the time and date after a power off. hours = eeprom_read(MemAddr5); minutes = eeprom_read(MemAddr6); seconds = eeprom_read(MemAddr7); day = eeprom_read(MemAddr8); month = eeprom_read(MemAddr9); year = eeprom_read(MemAddr10); //Retrieve the last value of EncoderCounter after a power off. EncoderCounter = eeprom_read(EncoderMemAddr); while (1) { ......... /*EUSART Inputs*/ if (PIR1bits.RCIF) ReadDigits(); ...... } //End of while } //End of main /*************************************/ void ReadDigits(void) { static unsigned int DecNum = 0; unsigned char ASCII_char; ASCII_char = USART_ReadByte(); if ((ASCII_char >= '0') && ASCII_char <= '9') { DecNum *= 10; DecNum = DecNum + (ASCII_char - '0'); USART_WriteByte(ASCII_char); //Echo back at the terminal the typed character } else if ((ASCII_char == NewLine) || (ASCII_char == BeginOfLine)) { USART_WriteString("nNum is OK", true); DecNum = 0; } else USART_WriteString("Invalid character", true); } //End of ReadDigits /*************************************/ unsigned char USART_ReadByte() { while (!PIR1bits.RCIF) { } return RC1REG; } //End of USART_ReadByte() Is this code in the main loop correct? By the way, in this example, I'm calculating a number (using a single variable) by the evaluation of the incoming characters. In case that I want to read and store a string of alphanumeric characters, how can this be done? |
|
|
|
我可以说,你可以用同样的方式保存一个字符串,只是一个字符一个数组的时间。在你的USAT代码中,你应该总是考虑错误检查。同时也要注意,当然,在发送回来时,你将无法接收新的字符——这可能是也可能不是问题。
以上来自于百度翻译 以下为原文 I'd say you can save a string in the same way you're storing a number, just one char a time into an array. You should always consider error checking, in your USART code. Also beware that, of course, while transmitting back you won't be able to receive new chars - which may or may not be a problem |
|
|
|
我启动了一个关于使用PIC16F1778的EUSAT中断的线程:HTTP://www. McCHIP.COM/FUMMS/M9722.2.ASPXI使用MCC来设置EUSAT,但它存在一些问题。但是,您可以看到如何设置一个FIFO缓冲区来接收和传输。MCC生成的代码有一些阻塞循环,它似乎中断了中断驱动的通信的好处。您需要了解进程的动态性,例如,您可以使用缓冲区和中断将字符串写入到EUSAT中,并且“PUTSH()”函数将执行。TE在几微秒,但实际传输可能需要几毫秒,所以你必须小心不要发送字符这么快,缓冲区溢出。您可以编写Putcf()函数,使得它使用一个循环来阻止执行,直到缓冲区中有空间,或者可以使它成为一个布尔函数,如果缓冲区满了,则返回false。在进入阻塞循环之前,还可能需要重新启用中断,以便其他中断驱动的进程(如定时器和ADC功能)可以在数据传输时继续。
以上来自于百度翻译 以下为原文 I started a thread about using interrupts for the EUSART of a PIC16F1778: http://www.microchip.com/forums/m977422.aspx I used the MCC to set up the EUSART but it had some problems. However, you can see how to set up a FIFO buffer to receive and transmit. The code generated by MCC had some blocking loops that seem to negate the benefits of interrupt-driven communication. You do need to understand the dynamics of the process, where, for instance, you might write a string to the EUSART using a buffer and interrupts, and the "puts()" function will execute in a few microseconds, but the actual transmission may take several milliseconds, so you must take care not to send characters so quickly that the buffer gets overrun. You can write the putc() function such that it uses a loop to block execution until there is room in the buffer, OR you can make it a boolean function that returns FALSE if the buffer is full. You may also need to re-enable interrupts before entering the blocking loop, so that other interrupt-driven processes (like timers and ADC functions) can continue while the data is being transmitted. |
|
|
|
我认为你是对的。在EUSAARTHARED()函数中有一个“while”条件,同时EuSARTRAXCOUNT变量在EUSAARTIZIALIALIZE()例程中初始化为EUSARTRXCOUNT=0;一旦到达这个点,就会陷入这个循环中,这就是全部。你无法逃脱。
以上来自于百度翻译 以下为原文 I think that you are right. There is a 'while' condition in the EUSART_Read() function and at the same time the eusartRxCount variable is initialized at the EUSART_Initialize() routine as eusartRxCount = 0;: uint8_t EUSART_Read(void) { uint8_t readValue = 0; while(0 == eusartRxCount) { } .... } void EUSART_Initialize(void) { // disable interrupts before changing states PIE1bits.RCIE = 0; PIE1bits.TXIE = 0; // Set the EUSART module to the options selected in the user interface. // ABDOVF no_overflow; SCKP Non-Inverted; BRG16 16bit_generator; WUE disabled; ABDEN disabled; BAUD1CON = 0x08; // SPEN enabled; RX9 8-bit; CREN enabled; ADDEN disabled; SREN disabled; RC1STA = 0x90; // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN enabled; SYNC asynchronous; BRGH hi_speed; CSRC slave; TX1STA = 0x24; // Baud Rate = 9615.385; SP1BRGL 103; SP1BRGL = 0x67; // Baud Rate = 9615.385; SP1BRGH 0; SP1BRGH = 0x00; // initializing the driver state eusartTxHead = 0; eusartTxTail = 0; eusartTxBufferRemaining = sizeof(eusartTxBuffer); eusartRxHead = 0; eusartRxTail = 0; eusartRxCount = 0; // enable receive interrupt PIE1bits.RCIE = 1; } Once, you reach this point, you get trapped in this loop and that's all. You can't escape. |
|
|
|
只有小组成员才能发言,加入小组>>
5244 浏览 9 评论
2035 浏览 8 评论
1955 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3209 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2260 浏览 5 评论
779浏览 1评论
672浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
598浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
682浏览 0评论
579浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 04:18 , Processed in 1.909288 second(s), Total 100, Slave 84 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号