Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Параллельное использование нескольких USART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
wmakc
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.
aaarrr
Цитата(wmakc @ Jan 31 2011, 13:33) *
Если обмен данных идет по другому usart, то при первом случае прерывание не срабатывает, пока не закончится обмен. А при втором, прерывание вызывается всегда, даже когда нет обмена с этим usartом.

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

дело в том, что по одному usartу контроллер постоянно опрашивает датчик, а при появлении данных на другом, он должен прерваться, обработать их. Но этого не происходит. Он как висит на датчике, так и продолжает висеть.
Aaron
1. если у вас прямо так жёстко надо прервать обработку одного прерывания и войти в другое - у вас должна быть реализована вложенность прерываний. и приоритетом задать - которые прерывания важнее.
2. у вас после обработки прерывания с датчика запускается обработкик с другого UARTа? или вообще не запускается никогда? возможно у вас слишком долго обрабатывается прерывание с датчика, и к моменту выхода из обработчика там уже висит новое прерывание. вот и залипает?
wmakc
Дело в том, что с датчиком просто идет обмен данными и никакие прерывания не используются. Прерывания должны обрабатываться по другому usartу.
Aaron
поподробнее опишите, что ли. что и как используется - и что из этого не срабатывает и в каком месте. а пока такое впечатление что настройка прерываний неверная.
wmakc
Вот код 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 под этот контроллер нет. Может кто посоветует пример для другого какого, чтобы я мог разобраться?
wmakc
Вот начал переделывать программу, чтобы использовался 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);
Только когда проверяю буферы, они остаются пустыми.
Aaron
я сам 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 не включается, не всё инициализируется.
wmakc
Разобрался в инициализации PDC. Завтра выложу, что получилось.

Так у меня не только перенаправление из канала в канал, но и еще прослушивание линнии. Поэтому pdc и требуется, чтобы все успевать
wmakc
Сделал 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 ?
DmitryM
Цитата(wmakc @ Feb 8 2011, 18:18) *
Возникла только проблема с самими прерываниями. Не всегда срабатывают.
В чем отличие AT91C_US_RXRDY от AT91C_US_ENDRX ?


Дык, либо первое либо второе. RXRDY - прием символа, ENDRX - заполнение одного из буферов PDC. Декремент счетчика PDC как раз по RXRDY.
wmakc
Разобрался, прерывания нормально работают. Проблема в том, что у меня на одном 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++; // Увеличение счетчика номера камеры
}
}
wmakc
Продолжаю писать программу, столкнулся с такой проблемой:
Контроллер общается по UART с компьютером. При получении тревоги от средства обнаружения, должен ответить этому средству не прекращая общаться с компьютером.
Проблема в том, что если ставить приоритет прерываний от компьютера выше, то контроллер не всегда будет реагировать на тревогу, если на оборот, то будут теряться сообщения от компьютера.

Так то он вродебы чаще всего успевает, но видимо из-за того что используются функции при обращении с Uart, то контроллер ждет появления данных на порту прежде чем их считать и если данные передаются по двум портам одновременно, то он обработает по одному. При использовании PDC может получиться так что в буфер данные еще не считались, и при проверке, контроллер может не обработать сообщение.
Объясните как правильно организовать алгоритм или направьте куда-нибудь где можно об этом почитать.
wmakc
Сделал так чтобы контроллер реагировал на прерывания от нескольких источников. Просто сохраняю все данные в буферы по прерываниям, при появлении нужной комбинации отправляю ответ с помощью функции PDC_Send(), которую описал выше, получилось, что контроллер на данную функцию тратит около 140-200 мс на передачу 10 байт при скорости 19200. Разве при использовании PDC контроллер не должен просто инициализировать регистры для передачи по PDC, а потом дальше выполнять работу?
Aaron
тут вопрос даже не в том, тратит PDC ресурс МК (нет, не тратит) или нет, а в том, что 1920 бит за 100мс это 192 байта, но никак не 10!!! ищите программные ошибки, ну никак не может всё настолько сильно тормозить.
wmakc
Цитата(Aaron @ Mar 5 2011, 13:03) *
тут вопрос даже не в том, тратит PDC ресурс МК (нет, не тратит) или нет, а в том, что 1920 бит за 100мс это 192 байта, но никак не 10!!! ищите программные ошибки, ну никак не может всё настолько сильно тормозить.


Как оказалось, контроллер не виноват, задержки вносил преобразователь интерфейсов Moxa, который использовался для тестирования(Один из портов оказался подпорченным). После замены все заработало, никаких задержек)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.