LCD reset every time set UDR0

I know there is good serial build-in lib but I try learning by doing.

I am using ATMega2560

My problem is after

  1. Disable USART0_UDRE_vect interrupt UCSR0B &= ~(1<<UDRIE0)
  2. Enable USART0_UDRE_vect interrupt UCSR0B |= (1<<UDRIE0)
  3. Write to UDR0
    4.Connected LCD do reset to info set in lcdInit() ->123
  4. Serial console still receives UDR0 byte

why LCD reset every time i did 1->3 ???
Is it LCD just reset one in Serial connection open time?
Is it mean toggle interrupt make connection reset? If that is why console still can receive byte send before reset?

SerialController mySerial;

//use ulity/setBaud.h
void serialInit(){

    mySerial.init(UBRRL_VALUE,UBRRH_VALUE,USE_2X);
}

 // initialize us LiquidCrystal_I2C.h
void lcdInit(){
    lcd.init();                     
    // Print a message to the LCD.
    lcd.backlight();
    lcd.setCursor(16,0);
    lcd.autoscroll();
    lcd.print("123");
    
}
void setup(){
    serialInit();
    lcdInit();
}
volatile char c;
void loop(){
    
    c = serial.readBuffer();
    if(c != '\0'){
        serial.writeBuffer(c); //after add this line LCD turn light off then on again but Serial console 
                                             //still print c char
        lcd.print(c); //this line work well for read from UDR0 ,for example I type 'a' in Serial console 
                            //it will show "123a" in LCD
        c = '\0';
    }
    
    
}
ISR(USART0_UDRE_vect){
    mySerial.write(); // write data to UDR0
} 
ISR(USART0_RX_vect){
    mySerial.read(); //read data form UDR0
    
} 
//some of SerialController
bool SerialController::writeBuffer(uint8_t dat){
    bool result = false;
    if(txBuffer.capacity() > 0){
        txBuffer.enQueue(dat);
    }
    if(_txStatus =='t'){
        turnDataRegisterEmpty(true); //set enable interrupt
    }
    return result;
}
void SerialController::turnDataRegisterEmpty(bool flag){
    if(flag == true){
        UCSR0B |= (1<<UDRIE0);
        _txStatus = 'a';
    }else{
        UCSR0B &= ~(1<<UDRIE0);
        _txStatus = 't'; //stop interrupt flag
    }
}
void SerialController::write(){
    if(txBuffer.isEmpty()){
        if( _txStatus == 'a') turnDataRegisterEmpty(false);
    }
    else{

        UDR0 = txBuffer.deQueue();
    }
}

That code won't compile. Experience shows that most often the error is in that part of the code people are hiding from us.

I thought it is good behavious when I try to make thing simple so that other cant point out problem easier.

Good behavior: provide a short example that compiles, runs, and demonstrates the problem.

There are multi files , i putted it in GitHub.

GithubRepo

volatile char c;

c doesn't have to be volatile.

But your serial variable should be volatile!

int arrSize = *(&dat + 1) - dat; //this work becasue dat is constant pointer to uint8_t array.

That doesn't really work. It might work in some circumstances but it heavily depends on the actual stack status at that moment. You should never use such constructs!

Even that code doesn't compile. For example, USE_2X isn't defined.

I guess that there are other hacks I haven't found yet, that produces memory corruption and the Arduino resets. Also the TX interrupt is activated sometimes but the corresponding handler isn't defined, that also resets the Arduino (default handler is reset).

Serial variable is instance of class, so I thought it reference variable. Is it needs to be copied every time by set volatile?

USE_2X

is define on

ulti/setbaud.h

You can find it somewhere in the Arduino installed folder. I think. I was successful in building and wrote to Arduino. so maybe just problem of env setup.

int arrSize = *(&dat + 1) - dat;

Any improvement suggestions for this line?

Also the TX interrupt is activated sometimes
What is TX vector you mention?
5.
I will find out about memory overflow.

The keyword "volatile" doesn't copy the variable, it simply tells the compiler that this variable must not be optimized away. That's necessary if a variable is used in the main code (loop) and in interrupt handlers.

No, provide the length in a separate parameter or use just C strings (NULL terminated).

Forget that, I was wrong, you have that handler in the main code.

It doesn't have to be an overflow. But as you do stuff like pointer address calculations for stack content, corruption is quite likely, although I haven't found the actual code piece yet.

Forget that I was wrong, you have that handler in the main code.

No, you were pointing in the right direction. I was missing

USART0_TX_vect

Just add it in main then no reset at all.

Maybe, I need to improve Queue class by using ATOMIC_BLOCK

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.