|
Проблема с приемом данных USART в ATtiny2313 |
|
|
|
Oct 29 2008, 09:28
|

Участник

Группа: Участник
Сообщений: 20
Регистрация: 28-10-08
Из: Москва
Пользователь №: 41 264

|
Помогите, плиз, разобраться с проблемой!
Спаял схему, в которой данные в МК должны поступать по протоколу Модбас через ADM1485. В CodeVisionAVR создаю проект, в котором настраиваю все параметры МК. Снизу часть сгенерированного текста, относящаяся к обработке прерывания:
// USART Receiver interrupt service routine interrupt [USART_RXC] void usart_rx_isr(void) { char status,data; status= UCSRA; data=UDR; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) ...
Все вроде бы собрано правильно, но МК не хочет воспринимать данные. Для проверки срабатывания прерывания я включил в текст строку:
// USART Receiver interrupt service routine interrupt [USART_RXC] void usart_rx_isr(void) { char status,data; status= UCSRA; data=UDR; PORTB.7=1; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) ...
После прихода на МК посылки, PORTB.7 меняет свое состояние, что говорит об срабатывании прерывания. Но если я включаю строчку после проверки if:
// USART Receiver interrupt service routine interrupt [USART_RXC] void usart_rx_isr(void) { char status,data; status= UCSRA; data=UDR; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) PORTB.7=1; ...
, то МК перестает реагировать на пакеты. Скорость передатчика и приемника выставлены одинаковыми. Я пробывал с разными скоростями. Пробывал и от внешнего кварца и от внутреннего генератора. Где-то я прочел, что в этом условии проверяется наличие аппаратной ошибки. Получается, что МК плохой? Или еще какая-то другая причина может быть?
|
|
|
|
|
Oct 29 2008, 10:11
|

Участник

Группа: Участник
Сообщений: 20
Регистрация: 28-10-08
Из: Москва
Пользователь №: 41 264

|
Текст программы я не приводил, так как она мало отличается от сгенерированной CodeVisionAVR.
Красным выделены те строки, которые я добавляю. Они мне нужны для того, чтобы понять, что прием хотя бы начался (я не говорю уж о правильности полученной информации).
#include <tiny2313.h> #include <stdio.h> #include <delay.h>
#define RXB8 1 #define TXB8 0 #define UPE 2 #define OVR 3 #define FE 4 #define UDRE 5 #define RXC 7
#define FRAMING_ERROR (1<<FE) #define PARITY_ERROR (1<<UPE) #define DATA_OVERRUN (1<<OVR) #define DATA_REGISTER_EMPTY (1<<UDRE) #define RX_COMPLETE (1<<RXC)
// USART Receiver buffer #define RX_BUFFER_SIZE 8 char rx_buffer[RX_BUFFER_SIZE];
#if RX_BUFFER_SIZE<256 unsigned char rx_wr_index,rx_rd_index,rx_counter; #else unsigned int rx_wr_index,rx_rd_index,rx_counter; #endif
// This flag is set on USART Receiver buffer overflow bit rx_buffer_overflow;
USART Receiver interrupt service routine interrupt [USART_RXC] void usart_rx_isr(void) { char status,data; status=UCSRA; data=UDR; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) {
PORTB.7=1; delay_ms(100); PORTB.7=0;
rx_buffer[rx_wr_index]=data; if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; if (++rx_counter == RX_BUFFER_SIZE) { rx_counter=0; rx_buffer_overflow=1; }; }; }
#ifndef _DEBUG_TERMINAL_IO_ // Get a character from the USART Receiver buffer #define _ALTERNATE_GETCHAR_ #pragma used+ char getchar(void) { char data; while (rx_counter==0); data=rx_buffer[rx_rd_index]; if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0; #asm("cli") --rx_counter; #asm("sei") return data; } #pragma used- #endif
// Standard Input/Output functions #include <stdio.h>
// Declare your global variables here
void main(void) { // Declare your local variables here
// Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=0x80; CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif
PORTA=0x00; DDRA=0x00;
PORTB=0x00; DDRB=0x80;
PORTD=0x00; DDRD=0x04;
// USART initialization // Communication Parameters: 8 Data, 2 Stop, No Parity // USART Receiver: On // USART Transmitter: Off // USART Mode: Asynchronous // USART Baud Rate: 9600 UCSRA=0x00; UCSRB=0x90; UCSRC=0x0E; UBRRH=0x00; UBRRL=0x33;
ACSR=0x80;
// Global enable interrupts #asm("sei")
while (1) { // Place your code here
}; }
|
|
|
|
|
Oct 29 2008, 10:49
|
Участник

Группа: Участник
Сообщений: 21
Регистрация: 2-12-04
Пользователь №: 1 296

|
1. Если данные передаются непрерывно, то задержка 100 мс внутри прерывания может вызвать переполнение (DATA_OVERRUN). 2. Могут быть банально перепутаны A и B проводники 485 - тогда ошибка кадрирования(FRAMING_ERROR) IMHO
|
|
|
|
|
Oct 29 2008, 11:47
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Прораб счастья @ Oct 29 2008, 12:28)  После прихода на МК посылки, PORTB.7 меняет свое состояние, что говорит об срабатывании прерывания. Но если я включаю строчку после проверки if:, то МК перестает реагировать на пакеты. Найдите какая именно ошибка возникает: Код if (status & FRAMING_ERROR) PORTB.7 = 1; if (status & PARITY_ERROR) PORTB.6 = 1; if (status & DATA_OVERRUN) PORTB.5 = 1; от этого дальше будем плясать. Цитата По моему разумению, даже если установлены разные скорости обмена или(и) разная длина пакета в настройках, условие после if должно быть истина в любом случае при отсутствии аппаратной ошибки (если это она проверяется в условии). По моему разумению если возникает ошибка - то первым делом надо ее идентифицировать и потом искать способы ее устранения. Ошибка это не значит "что МК плохой?" Цитата У меня параметры приема и передачи идентичны. Это ничем не подтвержденный факт. Раз не работает - значит есть проблема, в том числе параметры приема-передачи могут отличаться.
|
|
|
|
|
Oct 29 2008, 11:48
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Цитата(Прораб счастья @ Oct 29 2008, 13:19)  Подключение А и В я неоднократно проверял. Насчет первого есть вопрос: прерывание вызывается единожды при начале приема пакета или каждый принятый бит вызывает прерывание? Или каждый принятый байт? Задержка 100 мс стоит после того, как в регистр что-то записалось (видимо в UDR), т.е. то что записалось должно пройти проверку if-ом. Поправьте меня если я не прав! Прерывание в документе обозначается USART0, Rx Complete и вызывается, соответственно, после окончания приема всего байта. Насколько я понмю, в CodeVision запрещаются прерывания после вызова прерывания (хотя и в самой архитектуре AVR при входе в прерывание дальнейший вызов прерывания по умолчанию также блокируеся), так что задержки такой величины в прерываниях - это очень плохой тон, скорее всего, Вы пропускаете данные, на что потом и указывает DATA_OVERRUN. Чем вызвана первая ошибка - видимо, ошибкой формата пакета.
|
|
|
|
|
Oct 29 2008, 11:52
|

Чайник, 1 литр
   
Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168

|
Цитата(Прораб счастья @ Oct 29 2008, 14:19)  ...прерывание вызывается... каждый принятый байт. Ага. Управляете ADM1485 правильно? Для приёма на RE и DE надо выставить низкий уровень (в коде этого момента не видать без схемы). Кварц 8 МГц?
|
|
|
|
|
Oct 29 2008, 12:09
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Прораб счастья @ Oct 29 2008, 10:11)  UCSRC=0x0E; Вполне возможно, что эта строчка в инициализации приводит к ошибке. Для записи в UCSRC надо старший бит установить в 1, т.е. UCSRC=0x8E. В прерывании вы зачем-то проверяете паритет, а этой строчкой вы паритет запрещаете. Тогда получается, что МК получает байты с паритетом, но интерпретирует бит паритета, как стоп-бит, отсюда могут возникать ошибки FE - Frame Error.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Oct 29 2008, 12:19
|

Участник

Группа: Участник
Сообщений: 20
Регистрация: 28-10-08
Из: Москва
Пользователь №: 41 264

|
Цитата(Polaris @ Oct 29 2008, 14:48)  Прерывание в документе обозначается USART0, Rx Complete и вызывается, соответственно, после окончания приема всего байта. Насколько я понмю, в CodeVision запрещаются прерывания после вызова прерывания (хотя и в самой архитектуре AVR при входе в прерывание дальнейший вызов прерывания по умолчанию также блокируеся), так что задержки такой величины в прерываниях - это очень плохой тон, скорее всего, Вы пропускаете данные, на что потом и указывает DATA_OVERRUN. Чем вызвана первая ошибка - видимо, ошибкой формата пакета. По этой логике получается: после приема одного байта идет первая проверка на корректность приема именно одного первого байта (if ((status &.......). Значит задержка в 100 мс еще не была задействована и условие (при правильном приеме) должно быть истина! Цитата(SysRq @ Oct 29 2008, 14:52)  Управляете ADM1485 правильно? Для приёма на RE и DE надо выставить низкий уровень (в коде этого момента не видать без схемы). Кварц 8 МГц? На входах RE и DE у меня выставлен 0 постоянно. ADM принимает данные - проверенно логическим анализатором. Я пробывал с 10МГц-овым кварцем и с внутренним генератором 8МГц. Фьюз деления частоты на 8 отключен. Конечно настройки в передатчике соответствовали настройкам приемника. Цитата(=GM= @ Oct 29 2008, 15:09)  Вполне возможно, что эта строчка в инициализации приводит к ошибке. Для записи в UCSRC надо старший бит установить в 1, т.е. UCSRC=0x8E. В прерывании вы зачем-то проверяете паритет, а этой строчкой вы паритет запрещаете. Тогда получается, что МК получает байты с паритетом, но интерпретирует бит паритета, как стоп-бит, отсюда могут возникать ошибки FE - Frame Error. Это сгенерированный CodeVisionAVR текст. Ничего, кроме строчек выделенных красным цветом я не добавлял и не менял.
|
|
|
|
|
Oct 29 2008, 12:52
|

Чайник, 1 литр
   
Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168

|
Цитата(=GM= @ Oct 29 2008, 15:09)  Для записи в UCSRC надо старший бит установить в 1... Увы, нет. Цитата(=GM= @ Oct 29 2008, 15:09)  ...получается, что МК получает байты с паритетом, но интерпретирует бит паритета, как стоп-бит, отсюда могут возникать ошибки FE - Frame Error. Цитирую datasheet: "If Parity Check is not enabled the UPE bit will always be read zero." Остается пока теоретически возможность грешить на 10% нестабильность внутренного RC-генератора и неточность установки baudrate при кварце 10 МГц...
|
|
|
|
|
Oct 29 2008, 13:16
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Прораб счастья @ Oct 29 2008, 12:19)  Это сгенерированный CodeVisionAVR текст. Ничего, кроме строчек выделенных красным цветом я не добавлял и не менял CodeVisionAVR тоже человек писал, Павел Гайдук, мог ошибиться(:-). Повторюсь Цитата(=GM= @ Oct 29 2008, 12:09)  Вполне возможно, что эта строчка в инициализации приводит к ошибке. В прерывании вы зачем-то проверяете паритет, а этой строчкой вы паритет запрещаете. Тогда получается, что МК получает байты с паритетом, но интерпретирует бит паритета, как стоп-бит, отсюда могут возникать ошибки FE - Frame Error. С <7> битом UCSRC я ошибся, я всё время с ним ошибаюсь (просто у меня старая, но удобная книжка по авр с описанием процов, жалко выбрасывать). Шут с ним, с седьмым битом, не в нём дело, а дело в том, что при инициализации вы ЗАПРЕЩАЕТЕ паритет как класс, тем не менее, в своей программе вы проверяете бит паритета, спрашивается за каким шутом проверять, если вы его запретили принимать? Повторю ещё раз, если внешнее устройство передаёт вам биты с паритетом, а вы его запретили, то МК рассматривает переданные биты паритета как следующие за ними стоп-биты, а это приводит к ошибке FE, если конкретный бит паритета равен 0. Ответьте себе на вопрос, вы на МК передаёте биты с паритетом или нет?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|