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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Параллельное использование нескольких USART, Как настроить прерывания?
wmakc
сообщение Jan 31 2011, 10:33
Сообщение #1


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



AT91C_BASE_US0->US_IER = AT91C_US_RXRDY; // 1
AT91C_BASE_US0->US_IER = AT91C_US_RXBUFF; // 2

1. Как я понял это прерывание срабатывает при появлении данных
2. А это при заполнении буфера

Если обмен данных идет по другому usart, то при первом случае прерывание не срабатывает, пока не закончится обмен. А при втором, прерывание вызывается всегда, даже когда нет обмена с этим usartом.

Мне нужно организовать передачу по 4 usartам.
1)По одному идет обмен с устройством. Для него должен быть минимальный приоритет.
2)По второму обмен с датчиком. При срабатывании датчика, должен происходить обмен с ним. У него максимальный приоритет.
3)По последним двум проводится ретрансляция данных.

Забыл написать контроллер Atmel At91sam9g20.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 31 2011, 10:49
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(wmakc @ Jan 31 2011, 13:33) *
Если обмен данных идет по другому usart, то при первом случае прерывание не срабатывает, пока не закончится обмен. А при втором, прерывание вызывается всегда, даже когда нет обмена с этим usartом.

Это, скажем так, взаимоисключающие прерывания: первое используется при работе без PDC, второе - наоборот.
USART'ы и их прерывания совершенно независимы. Если вы не зависаете зачем-то в обработчике прерывания
одного из них, то никаких проблем с параллельной работой быть не может.
Go to the top of the page
 
+Quote Post
wmakc
сообщение Feb 1 2011, 08:06
Сообщение #3


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



Цитата(aaarrr @ Jan 31 2011, 13:49) *
Это, скажем так, взаимоисключающие прерывания: первое используется при работе без PDC, второе - наоборот.
USART'ы и их прерывания совершенно независимы. Если вы не зависаете зачем-то в обработчике прерывания
одного из них, то никаких проблем с параллельной работой быть не может.

дело в том, что по одному usartу контроллер постоянно опрашивает датчик, а при появлении данных на другом, он должен прерваться, обработать их. Но этого не происходит. Он как висит на датчике, так и продолжает висеть.
Go to the top of the page
 
+Quote Post
Aaron
сообщение Feb 1 2011, 08:23
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



1. если у вас прямо так жёстко надо прервать обработку одного прерывания и войти в другое - у вас должна быть реализована вложенность прерываний. и приоритетом задать - которые прерывания важнее.
2. у вас после обработки прерывания с датчика запускается обработкик с другого UARTа? или вообще не запускается никогда? возможно у вас слишком долго обрабатывается прерывание с датчика, и к моменту выхода из обработчика там уже висит новое прерывание. вот и залипает?
Go to the top of the page
 
+Quote Post
wmakc
сообщение Feb 1 2011, 08:37
Сообщение #5


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



Дело в том, что с датчиком просто идет обмен данными и никакие прерывания не используются. Прерывания должны обрабатываться по другому usartу.
Go to the top of the page
 
+Quote Post
Aaron
сообщение Feb 1 2011, 09:04
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



поподробнее опишите, что ли. что и как используется - и что из этого не срабатывает и в каком месте. а пока такое впечатление что настройка прерываний неверная.
Go to the top of the page
 
+Quote Post
wmakc
сообщение Feb 1 2011, 09:58
Сообщение #7


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



Вот код main, здесь только инициализация Uartoв производится и постоянный опрос камеры.

CODE
int main(void)
{

// -- Заполняем массив состояний камер значениями 0x04(Камера выключена) --------
for(i=1; i<6; i++)
{
Status[i] = 0x04;
}
// ------------------------------------------------------------------------------

ConfigureUsartDirect(); // Конфигурация Usart, ретранслирующего от ПЭВМ к БЛВС и ВК
ConfigureUsartReverse(); // Конфигурация Usart, ретранслирующего от ВК, БЛВС к ПЭВМ
ConfigureUsartVk(); // Конфигурация Usart для работы с ВК
ConfigureUsartAlarm(); // Конфигурация Usart для работы со средством обнаружения

USART_DIRECT->US_IER = AT91C_US_RXRDY; // Включение прерываний по USART_DIRECT
USART_REVERSE->US_IER = AT91C_US_RXBUFF; // Включение прерываний по USART_REVERSE
USART_VK->US_IER = AT91C_US_RXRDY; // Включение прерываний по USART_VK
USART_ALARM->US_IER = AT91C_US_RXRDY; // Включение прерываний по USART_ALARM

unsigned char CountVK = 1; // Счетчик номера опрашиваемой камеры

// Основной цикл программы
while(1)
{
if(CountVK==6) //Сбрасываем счетчик, когда опрошено 5 камер
{
CountVK=1;
}
Query(NumBLVS, CountVK);

CountVK++; // Увеличение счетчика номера камеры
}



А это инициализация одного из Usartoв.

CODE
void ConfigureUsartReverse(void)
{
#define MODE_ASYNCHRONOUS (AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT)

const Pin pinsUsart[] = {USART_REVERSE_TXD, USART_REVERSE_RXD};

PIO_Configure(pinsUsart, PIO_LISTSIZE(pinsUsart));

PMC_EnablePeripheral(USART_REVERSE_ID);

USART_Configure(USART_REVERSE, MODE_ASYNCHRONOUS, 115200, BOARD_MCK);

// Configure the interrupt
AIC_ConfigureIT(USART_REVERSE_ID, AT91C_AIC_PRIOR_HIGHEST, ISR_UsartReverse);
AIC_EnableIT(USART_REVERSE_ID);

// Enable receiver & transmitter
USART_SetReceiverEnabled(USART_REVERSE, 1);
USART_SetTransmitterEnabled(USART_REVERSE, 1);
}


Правда я думаю я в прерываниях не до конца разобрался, поэтому так и выходит, что либо они все время срабатывают, либо не работают.

Еще возник вопрос, думаю сделать ретрансляцию через PDC, чтобы не загружать процессор. Правда в даташите на контроллер немного написано, да и примеров для работы с PDC под этот контроллер нет. Может кто посоветует пример для другого какого, чтобы я мог разобраться?

Сообщение отредактировал IgorKossak - Mar 3 2011, 15:18
Go to the top of the page
 
+Quote Post
wmakc
сообщение Feb 2 2011, 16:31
Сообщение #8


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



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

Для первоначальной настройки этого хватит?
CODE
void ConfigurePDC()
{
AT91F_PDC_Open (AT91C_BASE_PDC_US5);
AT91F_PDC_SetNextRx (AT91C_BASE_PDC_US5, Buf2, 1);
AT91F_PDC_SetNextTx (AT91C_BASE_PDC_US5, Buf2, 1);
AT91F_PDC_SetRx (AT91C_BASE_PDC_US5, Buf1, 1);
AT91F_PDC_SetTx (AT91C_BASE_PDC_US5, Buf1, 1);
}


Взял функции для At91rm9200, но как понял они для моего контроллера тоже подходят, так как регистры не поменялись. Решил в прерывания по Usart добавить функции PDC:
AT91F_PDC_ReceiveFrame (AT91C_BASE_PDC_US5, Buf1, 1, Buf2, 1);
AT91F_PDC_SendFrame (AT91C_BASE_PDC_US5, Buf1, 1, Buf2, 1);
Только когда проверяю буферы, они остаются пустыми.
Go to the top of the page
 
+Quote Post
Aaron
сообщение Feb 3 2011, 11:55
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



я сам PDC не использую, потому как ещё не было такого, чтобы потоки данных просто тупо переправлялись в другой канал без обработки. Но вообще, у вас должно быть что-то типа такого в инициализации:
Код
    AT91C_BASE_US0->US_PTCR = AT91C_PDC_TXTEN; //tx transfers enable  (PDC channels can send data)
    AT91C_BASE_US0->US_PTCR = AT91C_PDC_RXTEN; //rx transfers enable  (PDC channels can read data)

если вы говорите, что буфер пустой, а данные по UART'у точно поступают - значит у вас PDC не включается, не всё инициализируется.
Go to the top of the page
 
+Quote Post
wmakc
сообщение Feb 3 2011, 17:42
Сообщение #10


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



Разобрался в инициализации PDC. Завтра выложу, что получилось.

Так у меня не только перенаправление из канала в канал, но и еще прослушивание линнии. Поэтому pdc и требуется, чтобы все успевать
Go to the top of the page
 
+Quote Post
wmakc
сообщение Feb 8 2011, 15:18
Сообщение #11


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



Сделал PDC для всех используемых USARTов. Немного переделал функции от AT91RM9200.

Вот примерный алгоритм

1) Сначала открываем для каждого USARTa.
CODE
// --Конфигурация PDC ------------------------
void ConfigurePDC()
{
AT91F_PDC_Open (AT91C_BASE_PDC_US0); // Настройка PDC для USART_DIRECT
AT91F_PDC_Open (AT91C_BASE_PDC_US5);
AT91F_PDC_Open (AT91C_BASE_PDC_US2);
AT91F_PDC_Open (AT91C_BASE_PDC_US3);
}
// -------------------------------------------


2) Для приема, передачи написал такие функции

2.1) Ретрансляция из порта в порт
CODE
unsigned int PDC_ReceiveWrite (
AT91PS_PDC pPDCRecive,
AT91PS_PDC pPDCWrite,
char *pBuffer,
unsigned int szBuffer)
{
if (AT91F_PDC_IsRxEmpty(pPDCRecive)) {
//* Buffer and next buffer can be initialized
AT91F_PDC_SetRx(pPDCRecive, pBuffer, szBuffer);
AT91F_PDC_SetTx(pPDCWrite, pBuffer, szBuffer);
return 1;
}
else {
return 0;
}
}


При срабатывании прерывания у меня данные сразу ретранслируются. Можно и буфер отслеживать.

2.2) Передача в порт
CODE
unsigned int PDC_Send(
AT91PS_PDC pPDC,
char *pBuffer,
unsigned int szBuffer)
{
if (AT91F_PDC_IsTxEmpty(pPDC)) {
//* Buffer and next buffer can be initialized
AT91F_PDC_SetTx(pPDC, pBuffer, szBuffer);
return 2;
}
else {
//* All buffer are in use...
return 0;
}
}

Использую один буфер, так как мне его хватает.

Возникла только проблема с самими прерываниями. Не всегда срабатывают.
В чем отличие AT91C_US_RXRDY от AT91C_US_ENDRX ?
Go to the top of the page
 
+Quote Post
DmitryM
сообщение Feb 8 2011, 18:01
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 583
Регистрация: 7-06-06
Из: Таганрог
Пользователь №: 17 840



Цитата(wmakc @ Feb 8 2011, 18:18) *
Возникла только проблема с самими прерываниями. Не всегда срабатывают.
В чем отличие AT91C_US_RXRDY от AT91C_US_ENDRX ?


Дык, либо первое либо второе. RXRDY - прием символа, ENDRX - заполнение одного из буферов PDC. Декремент счетчика PDC как раз по RXRDY.
Go to the top of the page
 
+Quote Post
wmakc
сообщение Feb 9 2011, 17:51
Сообщение #13


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



Разобрался, прерывания нормально работают. Проблема в том, что у меня на одном UARTе висит камера, которую нужно постоянно опрашивать. Примерно раз в 10 секунд. Интерфейс 485, поэтому либо передача либо прием. С другого USARTа приходят команды управления камерой, поэтому когда они приходят, их нужно перенаправлять на нее. После этого камера отсылает ответ. Так вот ответ работает по прерыванию. Проблема возникает как я понимаю из-за того, что камера иногда может отсылать посылки с задержками, при этом контроллер, так как нет прерывания возвращается в функцию опроса. Мне бы сделать так, чтобы после обработки прерывания он возвращался не в точку, где закончил выполнение программы, а куда-нибудь в другое место.

CODE
int main(void)
{
// -- Заполняем массив состояний камер значениями 0x04(Камера выключена) --------
for(i=1; i<6; i++)
{
Status[i] = 0x04;
}
// ------------------------------------------------------------------------------
// Status[1] = 0x01;
GetNumberBLVS(); // Получение номера БЛВС
PIO(); // Включаем порты управления передатчиками и приемниками


ConfigureUsartDirect(); // Конфигурация Usart, ретранслирующего от ПЭВМ к БЛВС и ВК
ConfigureUsartReverse(); // Конфигурация Usart, ретранслирующего от ВК, БЛВС к ПЭВМ
ConfigureUsartVk(); // Конфигурация Usart для работы с ВК
ConfigureUsartAlarm(); // Конфигурация Usart для работы со средством обнаружения

ConfigurePDC(); // Конфигурация PDC

USART_DIRECT->US_IER = AT91C_US_RXRDY; // Включение прерываний по USART_DIRECT
USART_REVERSE->US_IER = AT91C_US_RXRDY; //AT91C_US_ENDRX;//AT91C_US_RXBUFF;
// Включение прерываний по USART_REVERSE
USART_VK->US_IER = AT91C_US_RXRDY;//AT91C_US_RXRDY; // Включение прерываний по USART_VK
USART_ALARM->US_IER = AT91C_US_ENDRX;//AT91C_US_RXRDY; // Включение прерываний по USART_ALARM

unsigned char CountVK = 1; // Счетчик номера опрашиваемой камеры

while(1)
{
CommandVk = 0x00;

if(CountVK==6) //Сбрасываем счетчик, когда опрошено 5 камер
{
CountVK=1;
}

USART_VK->US_IDR = AT91C_US_RXRDY;
Query(NumBLVS, CountVK); //В этой функции проводится опрос камер
USART_VK->US_IER = AT91C_US_RXRDY; //А сюда мне бы надо попасть после обработки ответа от камеры

CountVK++; // Увеличение счетчика номера камеры
}
}
Go to the top of the page
 
+Quote Post
wmakc
сообщение Feb 25 2011, 19:18
Сообщение #14


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



Продолжаю писать программу, столкнулся с такой проблемой:
Контроллер общается по UART с компьютером. При получении тревоги от средства обнаружения, должен ответить этому средству не прекращая общаться с компьютером.
Проблема в том, что если ставить приоритет прерываний от компьютера выше, то контроллер не всегда будет реагировать на тревогу, если на оборот, то будут теряться сообщения от компьютера.

Так то он вродебы чаще всего успевает, но видимо из-за того что используются функции при обращении с Uart, то контроллер ждет появления данных на порту прежде чем их считать и если данные передаются по двум портам одновременно, то он обработает по одному. При использовании PDC может получиться так что в буфер данные еще не считались, и при проверке, контроллер может не обработать сообщение.
Объясните как правильно организовать алгоритм или направьте куда-нибудь где можно об этом почитать.
Go to the top of the page
 
+Quote Post
wmakc
сообщение Mar 3 2011, 15:14
Сообщение #15


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

Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768



Сделал так чтобы контроллер реагировал на прерывания от нескольких источников. Просто сохраняю все данные в буферы по прерываниям, при появлении нужной комбинации отправляю ответ с помощью функции PDC_Send(), которую описал выше, получилось, что контроллер на данную функцию тратит около 140-200 мс на передачу 10 байт при скорости 19200. Разве при использовании PDC контроллер не должен просто инициализировать регистры для передачи по PDC, а потом дальше выполнять работу?
Go to the top of the page
 
+Quote Post

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

 


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


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