
Господа, интересная фишка с UARTами 2 и 3 получается. В проекте используются UART0,2,3 (2400-19200, n, 8, 1, FIFO-1байт).
Задача: от ПК приходит запрос по Modbus. МК обрабатывает запрос и пересылает в ответ массив данных.
Реализация: после первого принятого по UART байта начинается отсчет времени тишины в линии (задействован, например, Timer2). Как только время тишины > времени передачи 4.5 символов, прерывания UARTа блокируются, выполняется обработка запроса и посылается ответ. После отправки последнего байта - прерывания UARTа возобновляются.
Так вот, при использовании UART0 – все пучком, нареканий никаких нет, при работе с UART2,UART3 флаги прерываний IER_THRE, IER_RLS, IER_RBR не работают, хотя в отладчике (Peripherals->UART2,3) флаги снимаются/устанавливаются. Что получается: запрещаю все прерывания UART2,3, отправляю n байт, восстанавливаю прерывания, разрешаю прием очередного пакета, и тут начинают сыпаться прерывания по приему байта, причем данные не что иное, а эхо отсылаемых перед этим данных.
Как лечил: после отправки n байт тупо выжидал время, необходимое для их отправки, а затем разрешал THRE, RLS, RBR и прием очередной посылки. Если и были какие то прерывания по приему, то они проигнорированы программно.
Какие у кого есть комменты????
Глюк ли это, или я что-то не так сделал.… Хотя при использовании UART0 – все в порядке.
Более подробно разбираться – времени нет. Попочка уже горит…
p.s. Надо бы еще проверить передачу байт в прерывании какого-нибудь таймера, а не в main. Не будет ли конфликта. А с аппаратной отправкой массива байт по флагу THRE, наверное, полный облом… (то есть отправляем первый байт откуда угодно, а при срабатывании прерывания THRE загоняем очередной байт и так до окончания массива).
Код
//Keil uVision 3.53 (mdk3.11+crk), отладчик ULINK2.
//#######################################################
int main (void)
{
PINSEL0 = 0x00500050; // UART0 – P0.2,P0.3, UART2 – P0.10,P0.11
PINSEL1 = 0x15400022;
PINSEL8 = 0x00; // UART3 – P4.28,P4.29
PINSEL9 = 0x0F000000;
//#########################################################
// Timer 0
//#########################################################
T0MR0 = 14999; // Interval
T0MCR = 3; // Interrupt and Reset on MR0
T0TCR = 1; // Enable Timer0
VICIntEnClr = 1 << 4; // Disable Interrupt
VICVectAddr4 = (unsigned long)Timer0Handler; // TC0 Interrupt -> Vector 4
VICVectCntl4 = 0x06; // TC0 Interrupt -> Priority 6
VICIntEnable = 1 << 4; // Enable TC0 Interrupt
//#######################################################
//#######################################################
// Timer 1
//#######################################################
T1MR0 = 5000; // Interval
T1MCR = 3; // Interrupt and Reset on MR1
T1TCR = 1; // Enable Timer1
VICIntEnClr = 1 << 5; // Disable Interrupt
VICVectAddr5 = (unsigned long)Timer1Handler; // TC1 Interrupt -> Vector 5
VICVectCntl5 = 0x03; // TC1 Interrupt -> Priority 3
VICIntEnable = 1 << 5; // Enable TC1 Interrupt
//#######################################################
PCONP |= (1 << 22); // Включаем питание Timer2
//#######################################################
// Timer 2
//#######################################################
T2MR0 = 5000; // Interval
T2MCR = 3; // Interrupt and Reset on MR2
T2TCR = 1; // Enable Timer2
VICIntEnClr = 1 << 26; // Disable Interrupt
VICVectAddr26 = (unsigned long)Timer2Handler; // TC2 Interrupt -> Vector 26
VICVectCntl26 = 0x04; // TC2 Interrupt -> Priority 4
VICIntEnable = 1 << 26; // Enable TC1 Interrupt
//#######################################################
PCONP |= (1 << 24); // Включаем питание UART2 и UART3
PCONP |= (1 << 25);
//########################################################
// UART 0
//########################################################
U0LCR = 0x83; // 8 bits, no Parity, 1 Stop bit
U0DLL = 0xC2; // 4800
U0LCR = 0x03; // DLAB = 0
U0FCR = 0x07; // Enable and reset TX and RX FIFO.
VICVectAddr6 = (unsigned long)UART0Handler; // UART0 Interrupt -> Vector 6
VICVectCntl6 = 0x05; // UART0 Interrupt -> Priority 5
VICIntEnable = 1 << 6; // Enable UART0 Interrupt
U0IER = IER_RBR | IER_THRE | IER_RLS; // Enable UART0 interrupt
//########################################################
// UART 2
//########################################################
U2LCR = 0x83; // 8 bits, no Parity, 1 Stop bit
U2DLL = 0xC2; // 4800
U2LCR = 0x03; // DLAB = 0
U2FCR = 0x07; // Enable and reset TX and RX FIFO.
VICVectAddr28 = (unsigned long)UART2Handler; // UART2 Interrupt -> Vector 28
VICVectCntl28 = 0x02; // UART2 Interrupt -> Priority 2
VICIntEnable = 1 << 28; // Enable UART2 Interrupt
U2IER = IER_RBR | IER_THRE | IER_RLS; // Enable UART2 interrupt
//########################################################
// UART 3
//########################################################
U3LCR = 0x83; // 8 bits, no Parity, 1 Stop bit
U3DLL = 0xC2; // 4800
U3LCR = 0x03; // DLAB = 0
U3FCR = 0x07; // Enable and reset TX and RX FIFO.
VICVectAddr29 = (unsigned long)UART3Handler; // UART3 Interrupt -> Vector 29
VICVectCntl29 = 0x01; // UART3 Interrupt -> Priority 1
VICIntEnable = 1 << 29; // Enable UART3 Interrupt
U3IER = IER_RBR | IER_THRE | IER_RLS; // Enable UART3 interrupt
…
…
…
…
// Таймер оттикал положенное количество времени, и дал добро на обработку принятого пакета и передачи ответа
// Пришла пора отправлять ответ – из main()
U2IER = 0; // Запрещаю прерывания
Bit_Priem = 1; // Запрещаю прием посылок
// Здесь типа обработали пакет и подготовили ответ
// Отправляю
for (fff=0; fff<40; fff++)// Например, 40 байт
{
while ( !(U2LSR & 0x20) );// Проверяем 5-й бит - Transmitter Holding Register Empty
U2THR = 0x40+fff; // Что-то передаю
}
for (fff=0; fff<Sch_Receive; fff++){UART2Buffer[fff]=0xFF;} // Очищаю буфер (просто так)
Delay(120000); // Тупая задержка (типа for (i=0; i<120000; i++){} )
U2IER = IER_THRE | IER_RLS | IER_RBR; // Re-enable Int
Bit_Priem = 0; // Разрешаю прием посылок
…
…
…
…
}
//Обработчк прерывания – взят из примера UART0
// Остальные обработчики – копия этого (только другие переменные)
//#########################################################################
void UART2Handler (void) __irq
{
BYTE IIRValue, LSRValue;
BYTE Dummy;
IIRValue = U2IIR;
IIRValue >>= 1; // skip pending bit in IIR
IIRValue &= 0x07; // check bit 1~3, interrupt identification
if ( IIRValue == IIR_RLS ) // Receive Line Status
{
LSRValue = U2LSR;
// Receive Line Status
if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
{
// There are errors or break interrupt
// Read LSR will clear the interrupt
UART2Status = LSRValue;
Dummy = U2RBR; // Dummy read on RX to clear interrupt, then bail out
VICVectAddr = 0; // Acknowledge Interrupt
return;
}
if ( LSRValue & LSR_RDR ) // Receive Data Ready
{
// If no error on RLS, normal ready, save into the data buffer.
// Note: read RBR will clear the interrupt
UART2Buffer[UART2Count] = U2RBR;
UART2Count++;
if ( UART2Count == BUFSIZE )
{
UART2Count = 0; // buffer overflow
}
}
}
else if ( IIRValue == IIR_RDA ) // Получаем данные (Receive Data Available)
{
if (Bit_Priem == 0)// Разрешено принимать данные
{
Flag_Nach = 1;// Есть начало передачи
UART2Buffer[Sch_Receive2] = U2RBR; // Записываем в буфер принятый код
Sch_Receive2++;
if (Sch_Receive2 > BUFSIZE)
{
Sch_Receive2 = 0; // Начинаем с нуля
}
Pause_After_Symbol = 0;
}
else {Dummy = U2RBR;} // Подтверждаем прием байта
}
else if ( IIRValue == IIR_CTI ) // Character timeout indicator
{
// Character Time-out indicator
UART2Status |= 0x100; // Bit 9 as the CTI error
}
else if ( IIRValue == IIR_THRE ) // THRE, transmit holding register empty
{
// THRE interrupt
LSRValue = U2LSR; // Check status in the LSR to see if valid data in U0THR or not
if ( LSRValue & LSR_THRE ){ UART2TxEmpty = 1; }
else{UART2TxEmpty = 0; }
}
VICVectAddr = 0; // Acknowledge Interrupt
}// End Interrupt