AVR - uart - błąd w działaniu

Odpowiedz Nowy wątek
2017-03-12 01:45
0

Szanowni koledzy i koleżanki,

Zwracam się z prośbą o wyjaśnienie dlaczego mój program zaczyna poprawnie dopiero działać po około 30 sekundach po resecie.
Bezpośrednio po resecie zachowuje się tak jakby dane ładowane do rejestru nadawczego UDR0 były równe 0xFF + ten jeden dodatkowy bit.
Ten dodatkowy (9-ty bit) wysyłany jest poprawny, gorzej z tymi ośmioma. Na początku wysyłane jest 0xFF+jeden dodatkowy podczas gdy ja ciągle ładuję to samo tam (0xAA). Najlepsze jest to że po pewnym czasie (zawsze po około 65 sekundach) procek zaczyna wysyłać dokładnie to co chcę czyli 0xAA + jeden dodatkowy bit. Za chiny nie potrafię dojść do tego skąd te felerne opóźnienie. Pracuję na atmedze 2560 w arduino.
Dodam tylko że chodzi o samo wysyłanie danych asynchronicznie (9600/9/N/1), na razie powiedzmy nie interesuje mnie odbiór ani inne rzeczy.
Pomocy!

Kod poniżej:
plik main.c:

 #include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
#include "uart.h"
#include "config.h"

int main(void)
{
    /* initialization */
    init();

    /* UART0 initialization */
    uart_init();

    /* global interrupt enable */
    sei();

    while (TRUE)
    {
        _delay_ms(1000);

        /* led blink */
        PORTB ^= (1<<PB0);

        if ( uart_transmit_char(0xAA) )
            while(1);
    }
}

plik uart.h:

 /*
 * uart.h
 *
 *  Created on: 25 maj 2016
 *      Author: Adam
 */

#ifndef SRC_DRIVERS_UART_H_
#define SRC_DRIVERS_UART_H_

#include <avr/io.h>

/* receive buffer size */
#define UART_RX_BUF_SIZE 64

/* transmit buffer size */
#define UART_TX_BUF_SIZE 64

/* baud rate */
#define BAUD 9600

/* UBRR register calculate for UART */
#define MYUBRR (FOSC/16/BAUD - 1)

/* mask register for cyclic transmit UART buffer */
#define UART_TX_BUF_MASK (UART_TX_BUF_SIZE - 1)

/* transmitter enable */
#define UART_TX_ENABLE (UCSR0B |= (1 << TXEN0))

/* transmitter disable */
#define UART_TX_DISABLE (UCSR0B &= ~(1 << TXEN0))

/* interrupt enable from empty transmit data register */
#define UART_UDRE_INT_ENABLE (UCSR0B |= (1 << UDRIE0))

/* interrupt disable from empty transmit data register */
#define UART_UDRE_INT_DISABLE (UCSR0B &= ~(1 << UDRIE0))

/* interrupt enable from transmission complete */
#define UART_TX_COMPLETE_INT_ENABLE (UCSR0B |= (1 << TXCIE0))

/* interrupt disable from transmission complete */
#define UART_TX_COMPLETE_INT_DISABLE (UCSR0B &= ~(1 << TXCIE0))

/* initialization UART0 */
extern void uart_init();

/* send exported char function - function returns zero when no error */
extern uint8_t uart_transmit_char(uint8_t data);

#endif /* SRC_DRIVERS_UART_H_ */

plik uart.c:

 #include <avr/interrupt.h>
#include "uart.h"
#include "config.h"

volatile uint8_t flag = RESET;

/* transmit buffer definition in RAM */
volatile char uart_tx_buf[UART_TX_BUF_SIZE];

/* transmit head index definition in RAM */
volatile uint8_t uart_tx_head = RESET;

/* transmit tail index definition in RAM */
volatile uint8_t uart_tx_tail = RESET;

void uart_init()
{
    /* TxD0 on output on port E pin number 1 will overwrite normal port operation */

    /* baud rate register assignment */
    UBRR0H = ((uint16_t)(MYUBRR)) >> 8;
    UBRR0L = (uint16_t)(MYUBRR);

    /* configuration on asynchronous UART, 9 data bits, non parity, one stop bit */
    UCSR0C |= (1<<UCSZ00)|(1<<UCSZ01);
    UCSR0B |= (1<<UCSZ02);

    /* enable transmitter */
    UART_TX_ENABLE;
}

/* interrupt from transmit data register empty */
ISR(USART0_UDRE_vect)
{
    /* check if the transmit buffer is not empty */
    if (uart_tx_head != uart_tx_tail)
    {
        /* calculate new tail index and put char into the UDR */
        uart_tx_tail = (uart_tx_tail + 1) & UART_TX_BUF_MASK;

        /* copy additional bit as ninth bit in frame (must be write before low bits of UDR0 */
        if (flag)
            UCSR0B |= (1 << TXB80);
        else
            UCSR0B &= ~(1 << TXB80);

        flag = !flag;

        /* copy byte to UDR0 */
        UDR0 = uart_tx_buf[uart_tx_tail];
    }
    else
    {
        /* disable interrupt from empty transmit buffer */
        UART_UDRE_INT_DISABLE;
    }
}

/* interrupt from transmit complete - used only in half-duplex for change from transmit to receive */
//ISR(USART0_TX_vect)
//{
//    /* disable interrupt from transmit complete */
//    UART_TX_COMPLETE_INT_DISABLE;
//}

uint8_t uart_transmit_char(uint8_t data)
{
    /* local variable with new head index */
    uint8_t temp = (uart_tx_head + 1) & UART_TX_BUF_MASK;

    /* check if the transmit buffer is full */
    if (uart_tx_tail == temp)
        return TX_OVF_ERROR;
    else
    {
        /* put char into the transmit buffer */
        uart_tx_buf[uart_tx_head] = data;

        /* set new head index */
        uart_tx_head = temp;

        /* enable interrupt from empty transmit buffer */
        UART_UDRE_INT_ENABLE;

        return NO_ERROR;
    }
}
edytowany 1x, ostatnio: Adamos19, 2017-03-12 01:47

Pozostało 580 znaków

2017-03-12 02:00
0

No i chyba mam rozwiązanie. Przed chwileczką wywaliłem tego "delay_ms" i troszkę przerobiłem żeby nie zawieszał jak jest błąd tylko żeby po prostu nic wówczas nie robił. No i zaczęło działać poprawnie a ja dalej z tego nic nie rozumiem bo przecież jak się wejdzie do definicji tego delay'a to to tak jest napisane że procek kręci się w pętli przez określoną ilość czasu i nic poza przerwaniami nie jest w stanie go z tej pętli przed upływem określonego czasu wyciągnąć. Więc dlaczego może to mieć wpływ na takie zachowanie programu.....? Pomocy.

Pozostało 580 znaków

2017-03-13 15:13

Pierwsze pytanie: Czemu nie wklejasz tego kodu w odpowiednich znacznikach?

W kodzie masz bląd: Zapisujesz dane pod adres x, a odczytujesz z pod adresu x + 1. Stąd po 65 sekundach bufor o rozmiarze 64 zostaje zapełniony twoimi danymi, i potem masz wrażenie, że działa poprawnie.

Usunięcie delay, sprawiło, że nie widzisz tej zwłoki, zapewne zapełniasz bufor szybciej, niż jesteś w stanie wysłać.

Pozostało 580 znaków

2017-03-13 15:15
0

Bardzo Ci dziękuję za dokonaną analizę i rzetelną odpowiedź i przepraszam za niedopatrzenie. To się już nie powinno powtórzyć.
Mam jedno dodatkowe pytanie jeśli mogę. Jak na to wpadłeś powiedz szczerze... ?

PS. Dosłownie przed chwilką poprawiłem błędy - błąd miałem zarówno w procedurze wysyłania jak i odczytu której nie przedstawiałem i pięknie zaczęło działać, aż miło popatrzeć.

edytowany 2x, ostatnio: Adamos19, 2017-03-13 15:44

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0