реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Проблема с приемом данных USART в ATtiny2313
Прораб счастья
сообщение Oct 29 2008, 09:28
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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;
...


, то МК перестает реагировать на пакеты.
Скорость передатчика и приемника выставлены одинаковыми. Я пробывал с разными скоростями. Пробывал и от внешнего кварца и от внутреннего генератора.
Где-то я прочел, что в этом условии проверяется наличие аппаратной ошибки. Получается, что МК плохой? Или еще какая-то другая причина может быть?
Go to the top of the page
 
+Quote Post
Vladimir_J
сообщение Oct 29 2008, 09:39
Сообщение #2


Участник
*

Группа: Свой
Сообщений: 74
Регистрация: 9-01-07
Из: Украина
Пользователь №: 24 228



Доброе время суток !!!
1. После условия if есть открывающаяся { скобка - "Но если я включаю строчку после проверки .. то МК перестает реагировать на пакеты"
2. Посмотрите в настройках UART: длина пакета 8 или 9 бит, к-во стоповых бит и т.д.
Скорее в этом трабл.

С Уважением, Владимир.
Go to the top of the page
 
+Quote Post
Прораб счастья
сообщение Oct 29 2008, 09:51
Сообщение #3


Участник
*

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



Скобка - { есть, просто здесь я ее забыл поставить.

Длина пакета 8 бит установлена и на передающей и на принимающей стороне. Кол-во стоповых битов 2, но помоему они (стоповые биты) не должны влиять на начало приема.

По моему разумению, даже если установлены разные скорости обмена или(и) разная длина пакета в настройках, условие после if должно быть истина в любом случае при отсутствии аппаратной ошибки (если это она проверяется в условии).
У меня параметры приема и передачи идентичны.
Go to the top of the page
 
+Quote Post
GDI
сообщение Oct 29 2008, 09:56
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Вы бы привели код полностью, чтоб никто не гадал, где вы там забыли или поленились скобку поставить.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
Прораб счастья
сообщение Oct 29 2008, 10:11
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 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

};
}
Go to the top of the page
 
+Quote Post
IVANS
сообщение Oct 29 2008, 10:49
Сообщение #6


Участник
*

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



1. Если данные передаются непрерывно, то задержка 100 мс внутри прерывания может вызвать переполнение (DATA_OVERRUN).
2. Могут быть банально перепутаны A и B проводники 485 - тогда ошибка кадрирования(FRAMING_ERROR)
IMHO
Go to the top of the page
 
+Quote Post
Прораб счастья
сообщение Oct 29 2008, 11:19
Сообщение #7


Участник
*

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



Подключение А и В я неоднократно проверял.
Насчет первого есть вопрос: прерывание вызывается единожды при начале приема пакета или каждый принятый бит вызывает прерывание? Или каждый принятый байт?
Задержка 100 мс стоит после того, как в регистр что-то записалось (видимо в UDR), т.е. то что записалось должно пройти проверку if-ом. Поправьте меня если я не прав!
Go to the top of the page
 
+Quote Post
defunct
сообщение Oct 29 2008, 11:47
Сообщение #8


кекс
******

Группа: Свой
Сообщений: 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 должно быть истина в любом случае при отсутствии аппаратной ошибки (если это она проверяется в условии).

По моему разумению если возникает ошибка - то первым делом надо ее идентифицировать и потом искать способы ее устранения. Ошибка это не значит "что МК плохой?"

Цитата
У меня параметры приема и передачи идентичны.

Это ничем не подтвержденный факт. Раз не работает - значит есть проблема, в том числе параметры приема-передачи могут отличаться.
Go to the top of the page
 
+Quote Post
Polaris
сообщение Oct 29 2008, 11:48
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964



Цитата(Прораб счастья @ Oct 29 2008, 13:19) *
Подключение А и В я неоднократно проверял.
Насчет первого есть вопрос: прерывание вызывается единожды при начале приема пакета или каждый принятый бит вызывает прерывание? Или каждый принятый байт?
Задержка 100 мс стоит после того, как в регистр что-то записалось (видимо в UDR), т.е. то что записалось должно пройти проверку if-ом. Поправьте меня если я не прав!

Прерывание в документе обозначается USART0, Rx Complete и вызывается, соответственно, после окончания приема всего байта. Насколько я понмю, в CodeVision запрещаются прерывания после вызова прерывания (хотя и в самой архитектуре AVR при входе в прерывание дальнейший вызов прерывания по умолчанию также блокируеся), так что задержки такой величины в прерываниях - это очень плохой тон, скорее всего, Вы пропускаете данные, на что потом и указывает DATA_OVERRUN. Чем вызвана первая ошибка - видимо, ошибкой формата пакета.
Go to the top of the page
 
+Quote Post
Прораб счастья
сообщение Oct 29 2008, 11:51
Сообщение #10


Участник
*

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



defunct:

Спасибо! Сегодня посмотрю smile.gif

Сообщение отредактировал Прораб счастья - Oct 29 2008, 11:53
Go to the top of the page
 
+Quote Post
SysRq
сообщение Oct 29 2008, 11:52
Сообщение #11


Чайник, 1 литр
****

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



Цитата(Прораб счастья @ Oct 29 2008, 14:19) *
...прерывание вызывается... каждый принятый байт.

Ага.

Управляете ADM1485 правильно? Для приёма на RE и DE надо выставить низкий уровень (в коде этого момента не видать без схемы).
Кварц 8 МГц?
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 29 2008, 12:09
Сообщение #12


Ambidexter
*****

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



Цитата(Прораб счастья @ Oct 29 2008, 10:11) *
UCSRC=0x0E;

Вполне возможно, что эта строчка в инициализации приводит к ошибке. Для записи в UCSRC надо старший бит установить в 1, т.е. UCSRC=0x8E. В прерывании вы зачем-то проверяете паритет, а этой строчкой вы паритет запрещаете. Тогда получается, что МК получает байты с паритетом, но интерпретирует бит паритета, как стоп-бит, отсюда могут возникать ошибки FE - Frame Error.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Прораб счастья
сообщение Oct 29 2008, 12:19
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 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 текст. Ничего, кроме строчек выделенных красным цветом я не добавлял и не менял.
Go to the top of the page
 
+Quote Post
SysRq
сообщение Oct 29 2008, 12:52
Сообщение #14


Чайник, 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 МГц...
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 29 2008, 13:16
Сообщение #15


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. Ответьте себе на вопрос, вы на МК передаёте биты с паритетом или нет?


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Прораб счастья
сообщение Oct 29 2008, 13:30
Сообщение #16


Участник
*

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



Сегодня вечером заменю кварц на 7.3728МГц, проверю что вызывает ошибку (по совету defunct), ну и с этим паритетом покопаюсь...
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 29 2008, 15:22
Сообщение #17


Ambidexter
*****

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



Цитата(SysRq @ Oct 29 2008, 12:52) *
Цитирую datasheet: "If Parity Check is not enabled the UPE bit will always be read zero."

Бит чётности читается 0, всё правильно, но если он физически передаётся другой стороной, то МК принимает его за стоп-бит, поскольку его инициализировали не принимать бит чётности.

На последовательности бит отлично видно, бит чётности передаётся, START-B0-B1-B2-B3-B4-B5-B6-B7-P-STOP1-STOP2, а МК думает, что уже идёт первый бит STOP1.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
SysRq
сообщение Oct 29 2008, 15:40
Сообщение #18


Чайник, 1 литр
****

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



Цитата(=GM= @ Oct 29 2008, 18:22) *
Бит чётности читается 0, всё правильно, но если он физически передаётся другой стороной, то МК принимает его за стоп-бит, поскольку его инициализировали не принимать бит чётности.

Вы правы, я прочитал начало фразы, а основную вашу мысль почему-то не воспринял. Решил, что автор все же занает что и как он передает. И написал о своем :)
Go to the top of the page
 
+Quote Post
Прораб счастья
сообщение Oct 30 2008, 07:30
Сообщение #19


Участник
*

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



Я, в общем-то, знаю что я передаю smile.gif
Посылка у меня без паритета. После проверки оказалось, что ошибка - FRAMING_ERROR. Пробывал менять местами А и В, но результат тот же...
Go to the top of the page
 
+Quote Post
SysRq
сообщение Oct 30 2008, 08:46
Сообщение #20


Чайник, 1 литр
****

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



Попробуйте отправить неразрывно два байта: [0xFF][любой_байт_данных]. Если стартовый бит не всегда ловится, то здесь должен пойматься у второго байта четко.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 30 2008, 10:01
Сообщение #21


Ambidexter
*****

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



Цитата(Прораб счастья @ Oct 30 2008, 07:30) *
Посылка у меня без паритета. После проверки оказалось, что ошибка - FRAMING_ERROR

Если посылка без паритета, зачем тогда вы этот паритет проверяете?

Вы уверены, что правильно определяете ошибку приёма? ПМСМ, лучше вместо красного фрагмента в вашей программе, который даёт солидную задержку в прерывании,
Цитата(Прораб счастья @ Oct 29 2008, 10:11) *
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
PORTB.7=1;
delay_ms(100);
PORTB.7=0;

rx_buffer[rx_wr_index]=data;
};

поставить одну инструкцию PINB.7=1;, которая просто инвертирует пин Б7 при приёме текущего байта.

Если же у вас всё же появляется ошибка FE, то проверяйте скорости передачи приёма прямым измереним. Для начала можно соединить выход передатчика с входом приёмника.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
IVANS
сообщение Oct 30 2008, 10:13
Сообщение #22


Участник
*

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



GM
может так?
PORTB.7=~PINB.7

Попробуй включить передатчик тиньки (и драйвер 485 на передачу), постоянно что-нибудь передавать и смотреть компутером. Т.о. будет ясно правильно ли выставлена скорость.
Go to the top of the page
 
+Quote Post
SysRq
сообщение Nov 1 2008, 18:28
Сообщение #23


Чайник, 1 литр
****

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



Цитата(IVANS @ Oct 30 2008, 13:13) *
GM
может так?
PORTB.7=~PINB.7

Восстанавливаю (исчезла из-за падения форума) весьма полезную информацию от =GM= касательно особенностей упоминаемого в теме МК:
"Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn."

Сообщение отредактировал SysRq - Nov 1 2008, 18:30
Go to the top of the page
 
+Quote Post
=GM=
сообщение Nov 1 2008, 20:50
Сообщение #24


Ambidexter
*****

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



Цитата(SysRq @ Nov 1 2008, 18:28) *
Восстанавливаю (исчезла из-за падения форума) весьма полезную информацию от =GM= касательно особенностей упоминаемого в теме МК:"Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn"

Вы знаете, эта особенность в настоящее время распространилась почти на все атмеловские МК, не только на этот. Для уточнения смотрите на описание портов конкретного МК, ну и ещё можно почитать про описание функции Read-Modify-Write.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 12:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.01596 секунд с 7
ELECTRONIX ©2004-2016