Проблема с UART в контроллере Atiny167

Я пытаюсь получить данные через uart Attiny167 в режиме прерывания со скоростью 57600 бод, но когда я отлаживаю программу, я получаю только CR & LF, я не получаю данных, почему это происходит в этом контроллере. Ниже приведен мой код:

#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();

    }

пожалуйста помоги.


person pranjal khanduri    schedule 08.11.2017    source источник
comment
Разве все маскируемые прерывания не блокируются автоматически ЦП при вызове прерывания? Так обычно работают микроконтроллеры, я не верю, что AVR чем-то отличается?   -  person Lundin    schedule 08.11.2017
comment
То, что вы получаете только CR / LF, может быть вызвано несоответствием скорости передачи. То, что вы получаете только CR&LF, может быть вызвано проблемами со скоростью передачи данных. Проверьте: 1. Если частота периферийных устройств составляет 8 МГц. 2. Что вы записываете короткое int (16 бит) в регистр LINBRR с битами [15:12], замаскированными до 0 3. Что вы действительно читаете регистр LINDAT в переменную типа char без знака 4 . Возможно, также зарегистрируйте LIN_ERR_vect и проверьте, есть ли у вас ошибки периферийного устройства.   -  person fisehara    schedule 09.11.2017


Ответы (1)


Вы забыли упомянуть очень важную вещь в своем вопросе. Когда ваш ISR называется? Вы указали прерывания для входящих или исходящих символов, но вы не сказали, вызывается ли этот ISR при чтении или записи в буфер, это действительно помогло бы дать вам несколько предложений.

Тем не менее, если предположить, что ISR предназначена для печати символа, проблема, похоже, здесь:

buff[i]=LINDAT;

когда вы, вероятно, имели в виду обратное:

LINDAT=buff[i];

так как это будет записывать байт в регистр, и крошечный должен автоматически пересылать его на uart (переключение некоторых битов, таких как LBUSY, во время операции, чтобы помочь вам не переполнить буфер)

Тем не менее, я был бы удивлен, если вы вообще что-нибудь увидите напечатанным, поскольку этот расчет:

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

Выдает много ошибок округления. Вы не устанавливаете здесь точное значение скорости передачи (обычно я вычисляю значение на бумаге и вводю точное число напрямую), это может быть вашей следующей точкой, чтобы проверить, видите ли вы распечатанный мусор (это означает, что uart не синхронно с часами приемника). Помимо этого, скорость передачи данных, тактовая частота и количество отсчетов на бит (которое уже по умолчанию равно 8, если я правильно помню) не очень часто меняются, и сложно реализовать программное обеспечение с избыточной (недостаточной) синхронизацией процессора или uart, это вообще нужно. В таблице должна быть формула для расчета LINBRR на основе ваших часов.

Напоследок несколько личных замечаний. 57600 бод - довольно высокая частота, вы уверены, что ресивер с этим справится? Быстрая скорость заставляет все работать очень быстро, но вы также можете потерять некоторых персонажей по пути. Также старайтесь не назначать значения таким образом:

DRA=0x02;

Обычно это лучшая альтернатива:

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

Это делает код более читаемым и удобным в обслуживании, чтобы точно знать, какие биты вы устанавливаете и для чего они предназначены (вы можете #def DDA1 & DDA0).

PS Если вы хотите уменьшить масштаб до 19200, вы можете:

LINBRRL = 0x000C;

В моем случае это сработало, и я также работаю на частоте 8 МГц.

person Giuseppe Cotugno    schedule 11.12.2017