Jump to content

Recommended Posts

I am currently working on a project in which the pic is made to read adc values from an external adc chip. The adc chip outs the data in a bcd format (-20,000 to +20,000 counts) & it generates 5 strobe pulses during which it outs the 5 digits of its adc result. Using ext interrupts i load these value into the pic. Simultaneously I am reading a rotary positional encoders output again thro' ccp interrupts . The value of the adc or the encoder is displayed on to 6 no. of 7-segment led display which are multiplexed on to 8 i/o pins. Now i also need to transmit the adc and encoder values thro' rs232 to a PC.

 

As you can see my interrupt routine is heavily loaded. What i need to know is if i use the emulated(software) usart will the transmitted data get corrupted due to extended soft ware delay(due to interrupts), which is used to generate the baud rate ?

 

Regards

Raghunathan.

Edited by ra68gi
Link to post
Share on other sites
Not if you intelligently use priority interrupts or alternativly give NOVOS a spin.

 

No priority interrupts, I am using pic16f877. I am talking about software usart and so it does not generate any interrupt ( for that matter i think even the hw uart lib of source boost does not generate interrupt, but does a software polling of the interrupt or status flags( the rx & tx interrupt enable bits are cleared). I don't want to use my own routine. If i use the SB lib i have the advantage of handling strings ,ascii etc with ease( i suppose, i haven't tried).

 

Regards

Raghunathan.

Link to post
Share on other sites
Not if you intelligently use priority interrupts or alternativly give NOVOS a spin.

 

No priority interrupts, I am using pic16f877. I am talking about software usart and so it does not generate any interrupt ( for that matter i think even the hw uart lib of source boost does not generate interrupt, but does a software polling of the interrupt or status flags( the rx & tx interrupt enable bits are cleared). I don't want to use my own routine. If i use the SB lib i have the advantage of handling strings ,ascii etc with ease( i suppose, i haven't tried).

 

Regards

Raghunathan.

 

 

Use the hardware UART, problem solved.

The problem with the SW UART is that any interrupts could stretch the bit time and so cause a mistransmissin/ reception.

The hardware UART will handle the bit timing, and if your interrupt service is less than the time to TX/RX a byte via the UART you should have no problems. (assuming interrupts dont come flying in so fast that you cant read consecutive RX words).

 

Another solution is to generate a supervisor interrupt using a timer as the sole interrupt source at a rate sufficient to handle all situations, and poll all interrupts in the service.

Link to post
Share on other sites

The hardware USART really does not need or benifit from canned libraries, sorry but it is true.

Aside from calculating the desired baudrate (usually the datasheet has a pre-calculated table anyway)

and intializing the module (altho this is simple as well), every task you might do is simple

to implement in a non-blocking method. Canned functions are usually blocking and polling

to make it easier for people to use (they dont have to worry about setting up extra stuff).

 

Look at what you want to do, and then look at using the TXIF and RCIF interrupt flags.

Careful usage and a wisely selected baudrate as Picxie suggests are your best solution.

 

Here is a very simple(and possibly flawed) off the cuff example of TX and RX interrupt usage.

The rest of the code to handle the actual data at your leisure would be inside your main.

 

void interrupt(void)
{
if(txif)	/* Transmit interrupt flag - triggers when empty */
{
	txreg=_txArrayToSend[_txCount];	/* load buffer to send */
	if(_txCount == _txLength)	/* are we done yet? if so reset counter */
	{
		_txCount=0;
		_txDoneFlag = 1;	/* extra flag incase we want to send something else */
		txie = 0;	/* we are done so we can disable the interrupt */
	}
	else
	{
		_txCount++;	/* keep on counting */
	}
	txif = 0;
}

if(rcif)	/* rx interrupt */
{
	_rxCapture[_rxCount] = rxreg;	/* capture values until we are done */
	_rxCount++;	/* array storage is easier to extract data from - redundancy, CRC. etc */
	rcif=0;
}
}

Edited by emte
Link to post
Share on other sites
void interrupt(void)
{

if(rcif)	/* rx interrupt */
{
	_rxCapture[_rxCount] = rxreg;	/* capture values until we are done */
	_rxCount++;	/* array storage is easier to extract data from - redundancy, CRC. etc */
	rcif=0;
}
}

 

Software UARTS implemented with cycle counting and interrupts are mutually exclusive. Using a RTOS does not solve the problem for such a SW UART implementation.

 

For most applications it is not necessary to implement a transmit interrupt handler. This is a task that can (usually) be handled as a polled function from a mainline task. This minimizes context switching and overhead especially when you consider that intercharacter latency variation for transmitted characters in a asynchronous environment is usually a non issue. A general exception to this guide would be in the event that each character received must also be echoed or repeated to another asynchronous port.

 

To minimize the interrupt overhead, ensure all variables within the handler are 8 bit variables. Clearing the RCIF flag is handled automatically when the rxreg is read. Clearing it manually (as shown above) can result in character loss in race conditions (don't do it). The PIC is brain dead with respect to its asynchronous port, in the event of an overrun error (not clearing the RXREG before the next character is received) the PIC disables the asynchronous receive logic - to avoid this problem the receive interrupt handler needs to check the error status and in event of error it needs to disable and immediately reenable the receive logic.

 

An alternative method of implementing a rx handler is to use a ring buffer with head and tail pointers. When a byte is received it is added to the buffer -rxCapture[head++]; if (head >= buffer_size) head = 0;

 

To determine if there is anything in the buffer then if (head != tail) // something is in the buffer ;

 

To extract a character from the buffer: new_char = rxCapture(tail++); if (tail >= buffer_size) tail = 0;

Link to post
Share on other sites
Clearing the RCIF flag is handled automatically when the rxreg is read. Clearing it manually (as shown above) can result in character loss in race conditions (don't do it). The PIC is brain dead with respect to its asynchronous port, in the event of an overrun error (not clearing the RXREG before the next character is received) the PIC disables the asynchronous receive logic - to avoid this problem the receive interrupt handler needs to check the error status and in event of error it needs to disable and immediately reenable the receive logic.

 

This is true, but also flawed in quite a lot of Microchip's silicon. There is a lot of errata stating that reading does not always clear the flag.

As for the potential race condition, in practice i have yet to see it even when using baudrates in excess of 115.2k.

 

Depending on which family of devices your using the USART will disable after the second or third level buffers are full, but the interrupt flag will still be enabled.

 

Error checking is essential for any protocol, but is a bit advanced for someone trying to figure out the basics of using the USART.

Link to post
Share on other sites
Error checking is essential for any protocol, but is a bit advanced for someone trying to figure out the basics of using the USART.

 

I disagree. Lockup of the PIC's USART is a common trap for newbies - they waste a lot of time chasing phantom problems.

Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...