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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> 2 USART под RS485 на ATMega162
vetalxh
сообщение Mar 15 2009, 20:31
Сообщение #1





Группа: Новичок
Сообщений: 13
Регистрация: 28-06-08
Пользователь №: 38 608



Здравия желаю всем !

Делаю устройство на Mega162 с двумя протоколами modbus.
USART0 - master, посылает всего 11 разных запросов. USART1 - slave, отвечает на эти 11 запросов с некоторыми корректировками. То есть устройство устанавливается между master и slave и общается с ними с нужными мне исправлениями.

В общем, сделал отдельно master и slave - работает, но когда все в целом, то работает только slave, а master зацикливается на 1-й посылке, иногда 2-я проскакивает.

Вроде проблема с прерываниями, т.к. slave постоянно принимает и отвечает, и не дает master работать. Игрался с запретом прерываний, но ничего не помогло.

Также делал чтобы slave принял, ответил, а потом master послал, принял, поочередно, но так теряется слейвом фреймы.

У кого могут быть какие идеи? Такое устройство возможно ли вообще?

Мега162, кварц - 3,6864... Параметры связи обоих 2400-О-1...
Go to the top of the page
 
+Quote Post
smac
сообщение Mar 15 2009, 21:09
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 149
Регистрация: 2-06-08
Из: Москва
Пользователь №: 38 003



Цитата(vetalxh @ Mar 15 2009, 23:31) *
...
У кого могут быть какие идеи? Такое устройство возможно ли вообще?
...

Устройство, понятное дело, возможно. Думаю стоит смотреть в сторону буферизации приемника слейва и уменьшения длительности выполнения обработчиков прерывания. А вообще стандартная фраза: Код в студию!
Go to the top of the page
 
+Quote Post
vetalxh
сообщение Mar 15 2009, 21:31
Сообщение #3





Группа: Новичок
Сообщений: 13
Регистрация: 28-06-08
Пользователь №: 38 608



Кода вообще много... Постараюсь основное. Сильно не пинайте, т.к. учусь уму разуму...
Это один из вариантов. Но не один из них корректно не работает


CODE
void StartTrans0(void)
{
DisableReceive0;
SetBit(PORTA,1);
TrCount0=0;
GoTrans0;
}

void StartTrans1(void)
{
SetBit(PORTA,0);
TrCount1=0;
GoTrans1;
}


interrupt [USART0_DRE] void usart0_udre_isr(void)
{
if (TrCount0<cNumTrByte0-1)
{
UDR0=cmTrBuf0[TrCount0];
TrCount0++;
}
else
{
UDR0=cmTrBuf0[cNumTrByte0-1];
StopTrans0;
TrCount0=0;
FinTrans=1;
}
}

interrupt [USART0_TXC] void usart0_tx_isr(void)
{
if (TrCount0<cNumTrByte0-1)
{
StopTrans0;
FinTrans=1;
ClrBit(PORTA,1);
EnableReceive0;
}

interrupt [USART0_RXC] void usart0_rx_isr(void) // USART0 I?a?uaaiea i?eaiieea IANOA?A
{
char status;
status=UCSR0A;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
if (StartRec0==0)
{
StartRec0=1;
RcCount0=0;
cmRcBuf0[RcCount0++]=UDR0;
TCCR1B=0x05;
TCNT1H=0xFF;
TCNT1L=0xEA;
}
else
{
cmRcBuf0[RcCount0++]=UDR0;
TCNT1H=0xFF;
TCNT1L=0xEA;
}
}
}

interrupt [USART1_RXC] void usart1_rx_isr(void)
{
char status,data;
status=UCSR1A;
data=UDR1;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
if (StartRec1==0)
{
StartRec1=1;
RcCount1=0;
cmRcBuf1[RcCount1++]=data;
TCNT0=0xE9;
TCCR0=0x05;
}
else
{
if (RcCount1<MaxLenghtRecBuf1)
{
cmRcBuf1[RcCount1++]=data;
}
else
{
cmRcBuf1[MaxLenghtRecBuf1-1]=data;
}
TCNT0=0xE9;
}
}
}

interrupt [USART1_DRE] void usart1_udre_isr(void) // USART1 I?a?uaaiea ia?aaao?eea IIA?EIAIIIAI
{
if (TrCount1<cNumTrByte1+1)
{
UDR1=cmTrBuf1[TrCount1];
TrCount1++;
}
else
{
StopTrans1;
//ClrBit(DDRA,0);
ClrBit(PORTA,0); //PA0 a 0 - ?aaioa a?aeaa?a 485 ia i?eai
//EnableReceive1;
TrCount1=0;
}
}

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

if (StartRec1==1)
{
StartRec1=0;
cNumRcByte1=RcCount1;
bModBus1=1;
TCCR0=0;
}
}

char ModBus0 (void)
{
int TempI;
if (cmRcBuf0[0]==0x01 && cmRcBuf0[1]==0x03 && cmRcBuf0[2]==0x02)
{
...
}
}

char ModBus2 (void)
{
switch (ModFlag)
{
case (1):
{
...
}
}
}


interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
if (StartRec0==1)
{
StartRec0=0;
cNumRcByte0=RcCount0;
bModBus0=1;
TCCR1B=0x00;
DisableReceive0;
}
else
{
TCCR1B=0x00;
TCNT2=0x00;
TCCR2=0x07;
DisableReceive0;
}
}

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
TrCount0=0;
cNumTrByte0=ModBus2();
StartTrans0();
TCCR2=0x00;
}

char ModBus1 (char NumByte)
{
...
}
}


void main(void)
{
Setup();
StartUART0();
StartUART1();
SetBit(DDRD,0);SetBit(PORTD,0);
ClrBit(DDRD,1);ClrBit(PORTD,1);
SetBit(PORTA,1);
ClrBit(DDRB,2);ClrBit(PORTB,2);
SetBit(DDRB,3);SetBit(PORTB,3);
EnableReceive1;
ClrBit(PORTA,0);
TCCR2=0x07;
TCNT2=0x00;
#asm("sei")
while (1)
{
#asm("cli")
if (bModBus0==1)
{
ModBus0();
bModBus0=0;
TCNT2=0x00;
TCCR2=0x07;
}
if (bModBus1==1)
{
cNumTrByte1=ModBus1(cNumRcByte1);
if (cNumTrByte1!=0) StartTrans1();
bModBus1=0;
}
#asm("sei")
}
}
Go to the top of the page
 
+Quote Post
vetalxh
сообщение Mar 15 2009, 22:38
Сообщение #4





Группа: Новичок
Сообщений: 13
Регистрация: 28-06-08
Пользователь №: 38 608



Цитата(smac @ Mar 16 2009, 01:09) *
Устройство, понятное дело, возможно. Думаю стоит смотреть в сторону буферизации приемника слейва и уменьшения длительности выполнения обработчиков прерывания. А вообще стандартная фраза: Код в студию!

Буфферизация приемника слейва, думАю, не поможет, т.к. мне нужно сразу же отвечать на запрос главного в течении времени 3.5 передачи символа, а обработку тоже старался сделать быструю с минимумом подсчетов...
Может проще все это сделать на 2х мегах8 и соединить их через spi? Не будет ли оно также конфликтовать?
Если в коде не понятны фукции какие-то, пишите..расскажу
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 15 2009, 22:43
Сообщение #5


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

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Не разбирался, но взглянул. Заметил такое: выключение передачи - StopTrans1- делается не по TXC, следовательно может подрезать последний байт (стоп-бит). Проверить подручными средствами этот момент проще, если убрать 485 и подключить UART-ы напрямую, но, ИМХО, и так видно. Не думаю, что это единственная проблемка.
Цитата
мне нужно сразу же отвечать на запрос главного в течении времени 3.5 передачи символа
это чего-то надуманное - минимальная пауза нужна как маркер пакета, а реально пауза может достигать сотен миллисекунд и более. В продвинутых реализация даже поддерживается ответ слейва типа "я занят, пинай позже"


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
vetalxh
сообщение Mar 15 2009, 22:57
Сообщение #6





Группа: Новичок
Сообщений: 13
Регистрация: 28-06-08
Пользователь №: 38 608



1) С работой слейва проблем не возникало. Смотрю модбас монитором. Но впринципе, спасибо, можно подправить...
2) Вопрос с 3.5 задержкой связан с готовым устройством (мастером), который при отсутствии ответа генерит ошибки в своей программе...На 2-й запрос - точно... Для "моего" то мастера можно и больше задержки делать..

Сообщение отредактировал vetalxh - Mar 15 2009, 23:00
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Mar 15 2009, 23:06
Сообщение #7


Гуру
******

Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588



Цитата(vetalxh @ Mar 15 2009, 20:31) *
Вроде проблема с прерываниями, т.к. slave постоянно принимает и отвечает, и не дает master работать. Игрался с запретом прерываний, но ничего не помогло.

Откажитесь от прерываний и сделайте опрос уартов в прерывании от таймера.
А вообще, если включить телепатию, я думаю, у вас грабли. Предположительно нет запрета прерываний от передатчика после того, как данные для передачи закончились.

Цитата(vetalxh @ Mar 15 2009, 20:31) *
Мега162, кварц - 3,6864... Параметры связи обоих 2400-О-1...

Так поднимимите кварц, раза в четыре. Хотя на 2400 нагрузка небольшая.
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Mar 15 2009, 23:06
Сообщение #8


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

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Вопрос с 3.5 задержкой связан с готовым устройством (мастером)

По спецификации Modbus_over_serial_line время 3.5 Тсимвола (точнее параметр описан там же) не задержка на начало ответа, а МИНИМАЛЬНАЯ ПАУЗА, позволяющая определить конец пакета


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
vetalxh
сообщение Mar 15 2009, 23:42
Сообщение #9





Группа: Новичок
Сообщений: 13
Регистрация: 28-06-08
Пользователь №: 38 608



sensor_ua, спасибо, буду думать...
А можно по-подробнее про "Откажитесь от прерываний и сделайте опрос уартов в прерывании от таймера" ?
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Mar 15 2009, 23:51
Сообщение #10


Гуру
******

Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588



Организуйте прерывание от таймера и проверяйте в нем готовность приемника и передатчика, наличие данных и места в буфере. Только так сможете управлять последовательностью обработки и приоритетами уартов. Кроме того, это позволит исключить затраты на вызовы уартовских прерываний.
Go to the top of the page
 
+Quote Post
vetalxh
сообщение Mar 16 2009, 00:11
Сообщение #11





Группа: Новичок
Сообщений: 13
Регистрация: 28-06-08
Пользователь №: 38 608



Цитата(Огурцов @ Mar 16 2009, 03:51) *
Организуйте прерывание от таймера и проверяйте в нем готовность приемника и передатчика, наличие данных и места в буфере. Только так сможете управлять последовательностью обработки и приоритетами уартов. Кроме того, это позволит исключить затраты на вызовы уартовских прерываний.

Спасибо...Подумаю над этим тоже
Go to the top of the page
 
+Quote Post
vetalxh
сообщение Mar 16 2009, 09:08
Сообщение #12





Группа: Новичок
Сообщений: 13
Регистрация: 28-06-08
Пользователь №: 38 608



В прерывании таймера проверять оба уарта? А если по прерыванию я попаду на середину фрейма? Если отказаться от прерываний уартов, то как данные попадут в буфер? Что-то туговато...А кусочком кода никто не поделится? Или алгоритмом хотябы...Спасибо
Go to the top of the page
 
+Quote Post
smac
сообщение Mar 16 2009, 19:37
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 149
Регистрация: 2-06-08
Из: Москва
Пользователь №: 38 003



Цитата(vetalxh @ Mar 16 2009, 12:08) *
В прерывании таймера проверять оба уарта? А если по прерыванию я попаду на середину фрейма?

Так там же буферизированный приемник, если TXC не установился - значит нет данных, если установился - значит есть, если при этом DOR сброшен, значит данные валидны.
Go to the top of the page
 
+Quote Post
vetalxh
сообщение Mar 16 2009, 22:26
Сообщение #14





Группа: Новичок
Сообщений: 13
Регистрация: 28-06-08
Пользователь №: 38 608



Короче, думал-думал...Решил обойти все это еще одним способом.

1. Разрешаю прием Slave.
2. Slave получил, обработал, ответил.
3. Slave опять получил, обработал, ответил
...
Так раза 3-4...
6. Запрещаю прием Slave и разрешаю посылку Master.
7. Master послал, принял, обработал.
И опять в начало "Разрешаю прием Slave"

В принципе, такое тоже должно меня устроить, но после того, как запретил прием Slave

CODE
UCSR1B&=~(1<<4); UCSR1B&=~(1<<7)


не могу заново разрешить его разрешить... help.gif
Делаю так

CODE
UCSR1B|=(1<<4); UCSR1B|=(1<<7)


Может нога RX повисла в левом состоянии.. Но я включал подтяжку для нее в начале программы (вместе для мастера и слейва)

CODE
void Setup(void)
{
PORTB=0x04;
DDRB=0x00;
PORTD=0x01;
DDRD=0x00;
}


И еще...Может ли камень уходить в рестарт?? Иногда модбас монитором замечаю, что идет цикл программы, а потом Мастер начинает посылку с 1й...По ходу выполнения программы такое не возможно, т.е. имхо или сброс, или хз что...
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 17 2009, 00:19
Сообщение #15


кекс
******

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



Цитата(vetalxh @ Mar 15 2009, 22:31) *
У кого могут быть какие идеи? Такое устройство возможно ли вообще?

А какие проблемы? далаете нормальный протоколо-независимый драйвер UART'а c буферизированным приемом и передачей.
Пишете две функции-задачи по очереди вызываемые в основном цикле программы, одна для обслуживания мастера, вторая для слейва. Никаких Delay_ms и прочий хлам не использовать!! Если слейв требует какого-то реалтайма для выдержки 3.5 символьного интервала, что организуется одним из таймеров, то modbus мастер - это совершенно неприхотливая задача. Выплевывать данные в UART и забирать ответ через скажем 100ms. Вот и вся ее суть.

Цитата
Мега162, кварц - 3,6864... Параметры связи обоих 2400-О-1...

Какой смысл ставить такой медленный кварц, и пользовать только ~20% производительности МК?
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th June 2025 - 23:16
Рейтинг@Mail.ru


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