Hi, After receiving a command on the serial port I want to disable all interrupts and then wait for the serial port to receive a byte. The following code shows what I am doing.
IEN = 0 ; _nop_() ; _nop_() ; while( !S0RIR ) ; rxbyte = ( uint8_t ) S0TBUF ; S0RIR = 0 ;
Hi Elliot, Doesn't seem like there is anything wrong with that piece of code. A byte arrives - S0RIR gets set, regardless of IEN or S0RIE. That's provided that ASC0 control register holds the right value. For example, here is an extract from the microcontroller manual: S0REN Receiver Enable Bit 0: Receiver disabled 1: Receiver enabled (Reset by hardware after reception of byte in synchronous mode) Another thing: how do you know that you reach the loop? Do you have an in-circuit debugger set up? - mike
The only debugging I can do is with a serial coms program that lets me look at values in nvSRAM. I set a value before the
while(!S0RIR ) ;
It appears for some reason that the flag is not set Not necessarily so. It is possible that the program crashes for a different reason before the flag is set (while in the loop or not even reaching the loop) - NMI or watchdog or whatever. It's all speculation, though, not having seen the full source code. - mike
Have you checked the serial line with an oscilloscope? Do you use the Debugger (which also uses S0)?
I have found a solution to my problem. The receive code needs to be as follows for it to work correctly.
while( !S0RIR & !S0EIR ) ; rx_char = ( uint8_t ) S0RBUF ; S0RIR = 0 ; S0EIR = 0 ;
I thought that the S0EIR flag was set simultaneously with the S0RIR flag from my reading of the manual. I thought so too. According to the manual, in your piece of code
while( !S0RIR & !S0EIR ) ;
while( !S0RIR ) ;
while( !S0RIR && !S0EIR ) ;
Hi Again This code works at 9600 baud but seems to have problems at higher rates and is contrary to the manual.
uint8_t GetByte( void ) { uint8_t rx_char ; while( !S0EIR && !S0RIR ) ; rx_char = ( uint8_t ) S0RBUF ; S0RIR = 0 ; S0EIR = 0 ; return rx_char ; }
uint8_t GetByte( void ) { uint8_t rx_char ; while( !S0RIR ) ; rx_char = ( uint8_t ) S0RBUF ; S0RIR = 0 ; return rx_char ; }
Well, without an in-circuit debugger you can never be sure what's going on. Besides, hardware problems is always a possibility (floating NMI pin, for example.) Set up debugging with Monitor166. Even if there is no external RAM in your target hardware, you should be able to debug small pieces of code with 6Kbyte of XRAM. Good luck! - mike
Servicing my non-running watchdog timer means that the code now works fine.
while( !S0RIR ) { _srvwdt_() ; } rx_char = ( uint8_t ) S0RBUF ; S0RIR = 0 ;
The watchdog timer is running unless you stop it before an EINIT or SRVWDT instruction. Sauli