|
Параллельное использование нескольких USART, Как настроить прерывания? |
|
|
|
Jan 31 2011, 10:49
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(wmakc @ Jan 31 2011, 13:33)  Если обмен данных идет по другому usart, то при первом случае прерывание не срабатывает, пока не закончится обмен. А при втором, прерывание вызывается всегда, даже когда нет обмена с этим usartом. Это, скажем так, взаимоисключающие прерывания: первое используется при работе без PDC, второе - наоборот. USART'ы и их прерывания совершенно независимы. Если вы не зависаете зачем-то в обработчике прерывания одного из них, то никаких проблем с параллельной работой быть не может.
|
|
|
|
|
Feb 1 2011, 08:06
|
Частый гость
 
Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768

|
Цитата(aaarrr @ Jan 31 2011, 13:49)  Это, скажем так, взаимоисключающие прерывания: первое используется при работе без PDC, второе - наоборот. USART'ы и их прерывания совершенно независимы. Если вы не зависаете зачем-то в обработчике прерывания одного из них, то никаких проблем с параллельной работой быть не может. дело в том, что по одному usartу контроллер постоянно опрашивает датчик, а при появлении данных на другом, он должен прерваться, обработать их. Но этого не происходит. Он как висит на датчике, так и продолжает висеть.
|
|
|
|
|
Feb 1 2011, 09:58
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
Feb 2 2011, 16:31
|
Частый гость
 
Группа: Участник
Сообщений: 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); Только когда проверяю буферы, они остаются пустыми.
|
|
|
|
|
Feb 3 2011, 11:55
|

Местный
  
Группа: Свой
Сообщений: 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 не включается, не всё инициализируется.
|
|
|
|
|
Feb 8 2011, 15:18
|
Частый гость
 
Группа: Участник
Сообщений: 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 ?
|
|
|
|
|
Feb 9 2011, 17:51
|
Частый гость
 
Группа: Участник
Сообщений: 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++; // Увеличение счетчика номера камеры } }
|
|
|
|
|
Feb 25 2011, 19:18
|
Частый гость
 
Группа: Участник
Сообщений: 111
Регистрация: 2-03-10
Пользователь №: 55 768

|
Продолжаю писать программу, столкнулся с такой проблемой: Контроллер общается по UART с компьютером. При получении тревоги от средства обнаружения, должен ответить этому средству не прекращая общаться с компьютером. Проблема в том, что если ставить приоритет прерываний от компьютера выше, то контроллер не всегда будет реагировать на тревогу, если на оборот, то будут теряться сообщения от компьютера.
Так то он вродебы чаще всего успевает, но видимо из-за того что используются функции при обращении с Uart, то контроллер ждет появления данных на порту прежде чем их считать и если данные передаются по двум портам одновременно, то он обработает по одному. При использовании PDC может получиться так что в буфер данные еще не считались, и при проверке, контроллер может не обработать сообщение. Объясните как правильно организовать алгоритм или направьте куда-нибудь где можно об этом почитать.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|