Strange Behaviour - Comments / opinions invited

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

Using MS7, RobotDyn 2560 MegaPro and 3 of it's 4 Serial ports.

 

As part of a much bigger project and for flexibility to enable future functionality I have designed all my functions to operate on all 4 ports of a 2560.

 

I've been trying to debug my main routine for days now by trying to output various bytes (max 10) at suitable locations by just writing to a port  with a delay if needed (code as below). Now this just didn't work reliably if more than say 2 or 3 bytes where sent and I just couldn't find where the problem was ... until 

 

Eventually, even though I only require 1 Serial Rx on USART1, I found that as I had enabled all the 4 serial port Rx interrupts of a 2560 (UCSRnB = 0x98, 0b10011000) but don't use them, delays/serial transmissions would intermittently stop working and my program would hang. 

Subsequently, I found that if I DIDN'T set the RXCIE3 bit for the unused port 4 (UCSR3B= 0x18, 0b00011000)  things would start working again as expected - interesting!!

 

Now 3 of the 4 ports have something 'electronic' connected to them, Port 2 only has the Tx pin connected to an LCD and all these work fine. Port 4 has no external electrical connection attached to it!  

 

So my question is, have I found the smoking gun - and this known behaviour or is something else going on that I've missed

 

Thanks

 

This code (in it's entirety) does work if UCSR3B = 0x18) or sei() is commented out.

#define F_CPU 16000000UL    // Define MCU clock speed (for delays only)

#include <stdint.h>            // Needed for uint8_t
#include <avr/io.h>            // AVR Pin and Register Names
#include <avr/interrupt.h>     // AVR Interrupt Vectors
#include <util/delay.h>        // Usage -> milli Seconds  = '_delay_ms(50);' micro Seconds = '_delay_us();'


int main(void)
{
    
    cli();                                          // Disable Global Interrupts until initial Configuration Complete
    
    Usart_Init_Setup();                             // Frame, 8n1, Async, Tx, Rx & ISR enabled etc 
    Usart_Speed_Setup(USART0,baud_9600);            // Debug PC (Tera Term)
    Usart_Speed_Setup(USART1,baud_57200);           // Driver Chip
    Usart_Speed_Setup(USART2,baud_9600);            // Debug LCD
    Usart_Speed_Setup(USART3,baud_9600);            // Not Used

    sei();                                          // Enable 'Global Interrupt Enable'
    _delay_ms(2);
    
    //>>>>>>>>>>>>>>>>>>>>>>>  debug -    All WORKING TO HERE        <<<<<<<<<<<<<<<<<<<
    
    
    for (uint8_t i=0x20; i<0xFE;i++)        // Visible ASCII Character set
    
    {
        while(!(UCSR0A &(1<<UDRE0)))        // Wait until clear to send
        ;
        UDR0 = i;                           //Sent Ascii to PC
        _delay_ms(250);                   
    }
    
    
    return 0;
}

 

 

 

This topic has a solution.
Last Edited: Fri. Jan 22, 2021 - 11:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't shown the UART library code you are using (or have written?) but it sounds a lot like Usart_Init_Setup() may be setting "IE" bits in more than one UART. In fact how do you tell it "enable interrupts only on 0 and 3 but not 1 and 2 when the function has no parameters?

 

Normally you'd have an init where you maybe pass a struct{} or similar and you fill that in to say which UART and how you want it configured then the chances are you'd call the init 2 or 3 times for the various UART you want to use. You can't have the single call set all 4 UART into an "active" state.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Docara wrote:
Subsequently, I found that if I DIDN'T set the RXCIE3 bit for the unused port 4 (UCSR3B= 0x18, 0b00011000)  things would start working again as expected - interesting!!

 

Well sure.  I would expect this s well.

 

If you have nothing connected to the RX pin of an unused, but interrupt enabled serial port, then any ambient noise could cause the RX pin to change input state as it's a high impedance input.  THis will cause the interrupt to fire and the AVR to jump to a non existent ISR and then off to never never land.

 

If you MUST enable the Unused serial port AND its interrupt, then do one of two things....

 

1) Tie the RX pin through a 10k resistor to VCC

 

OR

 

2) enable the internal Pull-up resistor by writing a logic '1' to the PORT pin associated with he RCX pin

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi chaps thanks for the replies 

 

OK  so first off my USART Init  routine

 

void Usart_Init_Setup(void)
{
	// Basic 8,n,1 configuration of the 4x MCU ports of the AtMega2560 and enable Transmitting & Receiving
	// UCSRnC = 0x06	    8 Bit Data	  (UCSZn1 and UCSZn0 = 1)
	// TxRxEn =				Tx and Rx Enabled (0x18)  or 0x98 if RXCIEn  is set
	
	UCSR0B = TxRxEn;		// USART 0
	UCSR0C = UCSRnC;
	UCSR1B = TxRxEn;		// USART 1
	UCSR1C = UCSRnC;
	UCSR2B = TxRxEn;		// USART 2
	UCSR2C = UCSRnC;
	//UCSR3B = TxRxEn;		// USART 3
	//UCSR3C = UCSRnC;
	

	
}

I have a follow-on function that can be called at any time which uses Switch-Case, defines and an array to put get the correct value and load it into the UBBRnL register based on supplied parameters.

 

jgmdesign - No I don't have to set ISR I was being lazy by just modifying the TxRxEn value once in the defines during debugging my main code. My 'proper' code selectively enables the ISR via a function - 'ISR_Control(Port,On/Off)' to only enable the ISR only when I expect to receive data in response to a commands I send.

Also as soon as I read your reply " If you have nothing connected..........." It hit home my school boy error (feeling a bit silly TBH - I even  mentioned it in my original post doh!) I blame the Covid Lockdown!!!!

 

I think we both know what the outcome is going to be when I break out the resistors  - will mark as solved when verified

 

Thank you both again 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Show TxRxEn. You seem to be writing the same value to all 4 UART so if it enables an IE bit for one it enables it for all four.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes hence my lazy comment in my previous post.

 

In my original code the value for the register was set as 0x18 to just enable Tx and Rx. I enabled the ISR when required by a function using the toggling the RXCIE1 bit in the usual ways.

 

Some background:-

 

Everything was working fine as is (even with the floating USART3 pins) until I tried to debug a recursive function from a datasheet example code. I have knocked up an Arduino LCD shield on USART2, I was able to send data over and have it display perfectly and I was even able to send receive data to my driver chip on USART1 and have the date read via an Rx ISR to the LCD display. Ans lastly I was also able to send data sent debug data to the PC Terminal (USART0) with no issue. Then, like I said,  I just tried to send the odd byte or 3 out to see what was going on with the borrowed recursive function code and nothing worked - powercycle, resetting leaving off overnight nothing. I stripped everything back to barebones and still nothing worked. When I say nothing worked my LCD is 16 characters wide so if I sent 16 characters It would see perhaps 3 or 4 occasionally.

 

Even now when I tied the Rx pins high (as suggested), disable all ports not used I still don't get what I feel is reliable transfers. However I have to say after uploading to the 2560 the same code a couple of times now things 'seem' to have sorted themselves out.

In conclusion, I think tying the pins high is a valid suggestion and has helped - certainly this advise should be acknowledged for others to see and is good practice

 

So I will be marking the post as solved for this reason

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Docara wrote:
I think we both know what the outcome is going to be when I break out the resistors

 

Just turn on the AVR pull up resistors that are internal and you wont need to solder anything.

 

Jim

 

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user