2015-07-11 46 views
0

我在at91sam7x256上使用帶有DMA的USART來讀寫數據。 因爲我沒有成功,我開始創建一個簡單的例子,但問題已經存在。 主要問題是,第一次中斷程序剛剛被觸發,第一次無法接收來自USART的數據!AT91sam7x 256:中斷只運行一次

#include "at91sam7x256.h" 

char   Buffer[10];    // holds received characters 
unsigned long nChars = 0;    // counts number of received chars 
char   *pBuffer = &Buffer[0]; // pointer into Buffer 

void Usart0IrqHandler (void); 
void USART0Setup(void); 

int main(void) 
{ 
    unsigned long j; 
    unsigned int IdleCount = 0; 

    // set up USART0 
    USART0Setup(); 

    // ***************************** 
    // * endless blink loop  * 
    // ***************************** 
    while (1) { 
     for (j = 1000000; j != 0; j--);    // wait 1 second 1000000 

     IdleCount++;         // count # of times through the idle loop 

     for (j = 1000000; j != 0; j--);    // wait 1 second 1000000 
    } 

} 
//////// 



void Usart0IrqHandler (void) { 
    volatile AT91PS_USART pUsart0 = AT91C_BASE_US0; // create a pointer to USART0 structure 
    if ((pUsart0->US_CSR & AT91C_US_ENDRX) == AT91C_US_ENDRX) { 
     // we have a end-of-receive interrupt (ENDRX) 
     pUsart0->US_RCR = 10; // restore the receive count - clears ENDRX flag 
    } 
} 


void USART0Setup(void) { 
    volatile AT91PS_USART pUSART0 = AT91C_BASE_US0;  // create a pointer to USART0 structure 
    volatile AT91PS_AIC pAIC = AT91C_BASE_AIC;   // pointer to AIC data structure 
    volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;   // pointer to PIO data structure 

    volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;   // pointer to PMC data structure 
    pPMC->PMC_PCER = (1<<AT91C_ID_US0);     // enable usart0 peripheral clock 
    pPIO->PIO_PDR = AT91C_PA0_RXD0 | AT91C_PA1_TXD0; // enable peripheral control of PA0 and PA1 (RXD0 and TXD0) 
    pPIO->PIO_ASR = AT91C_PIO_PA0 | AT91C_PIO_PA1;  // assigns the 2 I/O lines to peripheral A function 
    pPIO->PIO_BSR = 0;         // peripheral B function set to "no effect" 

    pUSART0->US_CR = AT91C_US_RSTRX |  // reset receiver 
         AT91C_US_RSTTX |  // reset transmitter 
         AT91C_US_RXDIS |  // disable receiver 
         AT91C_US_TXDIS;   // disable transmitter 

    pUSART0->US_MR = AT91C_US_PAR_NONE |  // no parity 
         0x3 << 6;    // 8-bit characters 

    pUSART0->US_IER = 0x00;      // no usart0 interrupts enabled (no effect) 
    pUSART0->US_IDR = 0xFFFF;     // disable all USART0 interrupts 

    pUSART0->US_BRGR = 0x139;  // CD = 0x139 (313 from above calculation for 9600 baud) 
            // FP=0 (not used) 

    pUSART0->US_RTOR = 0;      // receiver time-out (disabled) 

    pUSART0->US_TTGR = 0;      // transmitter timeguard (disabled) 

    pUSART0->US_RPR = (unsigned int)Buffer;  // address of DMA input buffer 

    pUSART0->US_RCR = 10;      // we'll read in 10 chars via DMA 

    pUSART0->US_TPR = (unsigned int)0;   // address of DMA output buffer (use same one) 

    pUSART0->US_TCR = 0;      // we'll transmit 0 chars via DMA 

    pUSART0->US_RNPR = (unsigned int)0;   // next DMA receive buffer address 
               // if set to zero, it is not used 

    pUSART0->US_RNCR = (unsigned int)0;   // next DMA receive counter 
               // if set to zero, it is not used 

    pUSART0->US_TNPR = (unsigned int)0;   // next DMA transmit buffer address 
               // if set to zero, it is not used 

    pUSART0->US_TNCR = (unsigned int)0;   // next DMA transmit counter 
               // if set to zero, it is not used 

    pUSART0->US_PTCR = AT91C_PDC_RXTEN | // enable receive transfer, 
         AT91C_PDC_TXTDIS; // disable transmit transfer 

    // Disable USART0 interrupt in AIC Interrupt Disable Command Register 
    pAIC->AIC_IDCR = (1<<AT91C_ID_US0);     
    // Set the USART0 IRQ handler address in AIC Source 
    pAIC->AIC_SVR[AT91C_ID_US0] =      
     (unsigned int)Usart0IrqHandler;     // Vector Register[6] 
    // Set the interrupt source type and priority 
    pAIC->AIC_SMR[AT91C_ID_US0] =      
     (AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 0x4);  // in AIC Source Mode Register[6] 
    // Enable the USART0 interrupt in AIC Interrupt Enable Command Register 
    pAIC->AIC_IECR = (1<<AT91C_ID_US0);     

    // enable the USART0 receiver and transmitter 
    pUSART0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; 

    // enable the USART0 end-of-receive interrupt 
    pUSART0->US_IER = AT91C_US_ENDRX;     // enable ENDRX usart0 end-of-receive interrupt 
    pUSART0->US_IDR = ~AT91C_US_ENDRX;     // disable all interrupts except ENDRX 

} 

//------------------ 
// end of file 
//------------------ 
+0

標準警告;使用'stdint.h'固定寬度類型而不是標準類型。 – Olaf

回答

0

當時有兩輛問題:
1,因爲我用的Keil uVision我需要使用__irq定義中斷服務程序! 2-令人驚訝的是,中斷的結束未被解僱!所以使用: *AT91C_AIC_EOICR = 0;

void __irq Usart0IrqHandler (void) {  
volatile AT91PS_USART pUsart0 = AT91C_BASE_US0; // create a pointer to USART0 structure 
    if ((pUsart0->US_CSR & AT91C_US_ENDRX) == AT91C_US_ENDRX) { 
     pUsart0->US_RPR = (unsigned int)Buffer; // we have a end-of-receive interrupt (ENDRX) 
     pUsart0->US_RCR = 10;     // restore the receive count - clears ENDRX flag 
    } 
     *AT91C_AIC_EOICR = 0;     // end of interrupts 
} 
0

此前在中斷設置計數(US_RCR),你需要重新初始化接收指針:

pUSART0->US_RPR = (unsigned int)Buffer; 

您的設備可能是由於斷層的PDC被寫入緩衝區之外。

+0

Ooops :)我忘了重置緩衝區,但這不是相對於問題。我找到了原因並將其作爲答案發布 – osyan