0
votes

i am trying to get an data over uart of Attiny167,in interrupt mode at baud rate of 57600 but when i debug the programme i only receive CR & LF no data i am receiving why is it happening in this controller below is my code:

#define CPU_CLOCK_FREQ 8000000UL
#define SAMPLES_PER_BIT 8
#define BAUD_RATE 57600
     ISR(LIN_TC_vect)
    {
       cli();
       temp=LINDAT;

           buff[i]=temp;
           i++;


       sei();

    }
    void USARTInit()
    {

        DDRA = 0x02; // Port A Rx / Tx as input / output for PIN0 and PIN1

        /* Set PORTB as input from FACS MAin BOX on PIN0 and PIN1 , initially high */
        DDRB = 0x00;
        PORTB= 0xFF;

        /* Set samples per bit and UART baud */
        LINBTR = (1 << LDISR) | SAMPLES_PER_BIT;
        LINBRR = (((CPU_CLOCK_FREQ) / SAMPLES_PER_BIT) / BAUD_RATE) - 1;

        /* Configure LIN UART in UART mode */
        LINCR  = (1 << LENA) | (1 << LCMD0) | (1 << LCMD1) | (1 << LCMD2);
        // enable transmit and recieve interrupts for LIN/UART transfer
        LINENIR = (1 << LENRXOK);

        sei();

    }

please help.

1
Isn't all maskable interrupts automatically blocked by the CPU when an interrupt is called? That's how microcontrollers usually work, I don't believe AVR is any different?Lundin
That you only receive CR/LF could be caused by a baud rate mismatch. That you receive only CR&LF could be caused by baud rate issues. Check: 1. If peripheral clock is 8MHz 2. That you write an short int (16Bit) into the LINBRR register with the Bits [15:12] masked to 0 3. That you really read the LINDAT register into a unsigned char variable 4. Maybe register the LIN_ERR_vect as well and check if you get errors of the peripheralfisehara

1 Answers

0
votes

You forgot to mention a very important thing in your question. When your ISR is called? You specified interrupts on incoming or outgoing characters, but you didn't say if that ISR is called when reading or writing on the buffer, this would really help in giving you some suggestions.

That said, assuming that the ISR is for printing a character, the problem seems to be here:

buff[i]=LINDAT;

when you probably meant the opposite:

LINDAT=buff[i];

as this will write a byte on the register and the tiny should automatically forward it on the uart (toggling some bits, like the LBUSY one, during the operation to help you not to overflow the buffer)

That said, I would be surprised if you will see anything printed at all, since this calculation:

LINBRR = (((CPU_CLOCK_FREQ) / SAMPLES_PER_BIT) / BAUD_RATE) - 1;

Is giving you a good lot of rounding errors. You are not setting the baud rate to a precise value here (I normally calculate the value on paper and input the precise number directly), this might be your next point to check if you see garbage printed out (it means that the uart is not in sync with the clock of the receiver). Besides this, the baud rate, the clock frequency and the samples per bit (which already default to 8 if I remember correctly) are not changing very frequently and is difficult to implement a software over(under)clocking of the processor or the uart, it at all needed. The datasheet should have the formula to calculate LINBRR based on you clock.

Lastly, a few personal remarks. 57600 bauds is quite a high frequency, are you sure the receiver is able to cope with that? Being very fast make everything running very quickly but you might also lose some characters on the way. Also try to avoid to assign values in this way:

DRA=0x02;

Normally, this is a better alternative:

DDRA= (1<< DDA1) | (1<< DDA0 );

It makes the code much more readable and maintainable to know exactly which bits you are setting and what they are meant to do (you could #def DDA1 & DDA0).

PS If you are willing to scale down to 19200, you could do:

LINBRRL = 0x000C;

It did work in my case, and I am also clocking at 8MHz