整个系统的工作模式是做一个通信中转,将一个串口接收到的数据从另一个串口发送出去。 现遇到以下问题:单向的时候,即一个串口收,一个串口发时还是比较稳定地 当工作在全双工时,时间一长就会出问题,其中一个串口会接收不到数据 请问:中断处理上,和初始化上有什么需要注意的? 两个串口的程序差不多,
*/ /* * 初始串口0 */ void Usart0_init(void) { extern AT91S_PIO * pPIO ; unsigned long statu;
Com0RecBLengA = 0 ; Com0RecBLengB = 0 ; Com0RecOK = 0 ; /* Disable all interrupt */ pPIO->PIO_ASR = AT91C_PA5_RXD0|AT91C_PA6_TXD0; /* set rxd txd pin contral by pers A */ pPIO->PIO_BSR = 0 ; pPIO->PIO_PDR = AT91C_PA5_RXD0|AT91C_PA6_TXD0; /* Disable RXD and TXD pin controler by PIO */ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US0); /* enable the clock of the PIOA */
AT91C_BASE_US0->US_IDR = 0xf3fff; /* reset receive and transmitter, disable receive and transmitter */ AT91C_BASE_US0->US_CR = AT91C_US_RSTRX|AT91C_US_RSTTX|AT91C_US_RXDIS|AT91C_US_TXDIS ; AT91C_BASE_US0->US_RCR = 0 ; /* clear receive counter */ AT91C_BASE_US0->US_TCR = 0 ; /* clear transmit counter */ AT91C_BASE_US0->US_BRGR = AT91F_US_Baudrate(SYS_MCK, 57600) ; /* Define the baud rate divisor register */
/* Define the USART mode SYNC = 0 OVER = 0 baud = mck/div/16/BRGR */ AT91C_BASE_US0->US_MR = AT91C_US_USMODE_NORMAL /* normal */ |AT91C_US_CLKS_CLOCK /* mck/div */ |AT91C_US_CHRL_8_BITS /* 8 bit */ |AT91C_US_PAR_EVEN /* EVEN 奇检验 */ |AT91C_US_NBSTOP_1_BIT ; /* one stop bit */
AT91C_BASE_US0->US_TTGR = 0 ; /* Write the Timeguard Register */
//* Enable receiver and transmitter AT91C_BASE_US0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN ; AT91C_BASE_US0->US_RTOR= 0 ;
AT91C_BASE_US0->US_PTCR = AT91C_PDC_RXTDIS ; AT91C_BASE_US0->US_PTCR = AT91C_PDC_TXTDIS ; AT91C_BASE_US0->US_TNPR = 0 ; AT91C_BASE_US0->US_TNCR = 0 ; AT91C_BASE_US0->US_RNPR = 0 ; AT91C_BASE_US0->US_RNCR = 0 ; AT91C_BASE_US0->US_TPR = 0 ; AT91C_BASE_US0->US_TCR = 0 ; AT91C_BASE_US0->US_RPR = (unsigned int)Com0RecBufA ; Com0RecBufDex = 0 ; AT91C_BASE_US0->US_RCR = COM0_REC_BUFFER_LENGTH ; AT91C_BASE_US0->US_RTOR = 10 ; AT91C_BASE_US0->US_PTCR = AT91C_PDC_RXTEN ; AT91C_BASE_US0->US_PTCR = AT91C_PDC_TXTEN ;
/* USART IRQ open */ /* Global UART Interrupt: Mode and Vector with Highest Priority and Enable */ AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_US0); // enable interrupt AT91C_BASE_AIC->AIC_SMR[AT91C_ID_US0] = AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED | AT91C_AIC_PRIOR_HIGHEST; AT91C_BASE_AIC->AIC_SVR[AT91C_ID_US0] = (unsigned long) USART0_ISR; AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_US0); // enable interrupt AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_US0); // clear interrupt
statu = AT91C_BASE_AIC->AIC_IMR ; statu = AT91C_BASE_AIC->AIC_IPR ;
AT91C_BASE_US0->US_IER=AT91C_US_TIMEOUT|AT91C_US_RXBUFF; statu = AT91C_BASE_US0->US_IMR; }
int Usart0_send_frame (unsigned char * pbuffer, short bufsize ) { while((pUART0->US_CSR & US_ENDTX ) == 0) ; /* Wait for previous transfer finished */ pUART0->US_TPR = (unsigned int)pbuffer ; /* Store the address of the buffer */ pUART0->US_TCR = bufsize ; return TRUE ; }
void USART0_Handler(void) { unsigned long statu,length;
// *AT91C_AIC_EOICR = 0; /* End of Interrupt */ statu = pUART0->US_CSR ; /* get the channel status */
length = pUART0->US_RCR ; if ( statu & (AT91C_US_TIMEOUT|AT91C_US_RXBUFF)) { if(Com0RecBufDex == 0) { Com0RecBufDex = 1; pUART0->US_RPR = (unsigned int) Com0RecBufB; pUART0->US_RCR = COM0_REC_BUFFER_LENGTH; Com0RecBLengA = COM0_REC_BUFFER_LENGTH - length ; Com0RecOK = 1 ; } else { Com0RecBufDex = 0; pUART0->US_RPR = (unsigned int) Com0RecBufA; pUART0->US_RCR = COM0_REC_BUFFER_LENGTH; Com0RecBLengB = COM0_REC_BUFFER_LENGTH - length ; Com0RecOK = 1 ; } pUART0->US_CR = AT91C_US_STTTO; } pUART0->US_CR = AT91C_US_RSTSTA; }
USART0_ISR
sub r14, r14, #4 stmfd sp!, {r14} mrs r14, spsr stmfd sp!, {r0,r14} mrs r14, cpsr bic r14, r14, #I_Bit orr r14, r14, #Mode_SVC msr cpsr_cxsf, r14 stmfd sp!, { r0-r12, r14} bl USART0_Handler ldmia sp!, { r0-r12, r14} mrs r0, cpsr bic r0, r0, #Mode_SVC orr r0, r0, #I_Bit:OR:Mode_IRQ msr cpsr_cxsf, r0 ldr r0, =AIC_BASE str r0, [r0, #AIC_EOICR] ldmia sp!, {r0,r14} msr spsr_cxsf, r14 ldmia sp!, {pc}^ |