C AT91sam7x 256:中断仅运行一次

C AT91sam7x 256:中断仅运行一次,c,arm,embedded,interrupt,keil,C,Arm,Embedded,Interrupt,Keil,我在at91sam7x256上使用带DMA的USART读取和写入数据。 由于我没有成功,我开始创建一个简单的示例,但问题已经存在。 主要问题是中断程序第一次启动,第一次启动后我无法从USART接收数据 #include "at91sam7x256.h" char Buffer[10]; // holds received characters unsigned long nChars = 0; // counts num

我在at91sam7x256上使用带DMA的USART读取和写入数据。 由于我没有成功,我开始创建一个简单的示例,但问题已经存在。 主要问题是中断程序第一次启动,第一次启动后我无法从USART接收数据

#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
//------------------
#包括“at91sam7x256.h”
字符缓冲区[10];//保存接收到的字符
无符号长nChars=0;//统计收到的字符数
char*pBuffer=&Buffer[0];//指向缓冲区的指针
无效Usart0IrqHandler(无效);
作废USART0Setup(作废);
内部主(空)
{
无符号长j;
无符号整数IdleCount=0;
//设置USART0
USART0Setup();
// *****************************
//*无休止的闪烁循环*
// *****************************
而(1){
对于(j=1000000;j!=0;j--);//等待1秒1000000
IdleCount++;//通过idle循环的次数
对于(j=1000000;j!=0;j--);//等待1秒1000000
}
}
////////
void Usart0IrqHandler(void){
volatile AT91PS_USART pUsart0=AT91C_BASE_US0;//创建指向USART0结构的指针
如果((pUsart0->US_CSR&AT91C_US_ENDRX)==AT91C_US ENDRX){
//我们有一个接收端中断(ENDRX)
pUsart0->US_RCR=10;//恢复接收计数-清除ENDRX标志
}
}
作废USART0Setup(作废){
volatile AT91PS_USART pUSART0=AT91C_BASE_US0;//创建指向USART0结构的指针
volatile AT91PS_AIC pAIC=AT91C_BASE_AIC;//指向AIC数据结构的指针
volatile AT91PS_PIO pPIO=AT91C_BASE_PIOA;//指向PIO数据结构的指针
易失性AT91PS_PMC pPMC=AT91C_BASE_PMC;//指向PMC数据结构的指针
pPMC->PMC_PCER=(1PIO_ASR=AT91C_PIO_PA0 | AT91C_PIO_PA1;//将两条I/O线分配给外设功能
pPIO->PIO_BSR=0;//外围B功能设置为“无效”
pUSART0->US_CR=AT91C_US_RSTRX |//重置接收机
AT91C_US_RSTTX |//重置变送器
AT91C_US_RXDIS |//禁用接收器
AT91C_US_TXDIS;//禁用变送器
pUSART0->US_MR=AT91C_US_PAR_NONE |//无奇偶校验
0x3 US_IER=0x00;//未启用usart0中断(无效果)
pUSART0->US_IDR=0xFFFF;//禁用所有USART0中断
pUSART0->US_BRGR=0x139;//CD=0x139(根据上述9600波特的313计算)
//FP=0(未使用)
pUSART0->US\u RTOR=0;//接收器超时(禁用)
pUSART0->US_TTGR=0;//变送器时间保护(禁用)
pUSART0->US_RPR=(unsigned int)Buffer;//DMA输入缓冲区的地址
pUSART0->US_RCR=10;//我们将通过DMA读取10个字符
pUSART0->US_TPR=(unsigned int)0;//DMA输出缓冲区的地址(使用相同的地址)
pUSART0->US_TCR=0;//我们将通过DMA传输0个字符
pUSART0->US_RNPR=(unsigned int)0;//下一个DMA接收缓冲区地址
//如果设置为零,则不使用
pUSART0->US_RNCR=(unsigned int)0;//下一个DMA接收计数器
//如果设置为零,则不使用
pUSART0->US_TNPR=(unsigned int)0;//下一个DMA传输缓冲区地址
//如果设置为零,则不使用
pUSART0->US_TNCR=(unsigned int)0;//下一个DMA传输计数器
//如果设置为零,则不使用
pUSART0->US_PTCR=AT91C_PDC_RXTEN |//启用接收传输,
AT91C_PDC_TXTDIS;//禁用传输
//在AIC中断禁用命令寄存器中禁用USART0中断
pAIC->AIC_IDCR=(1AIC_SMR[AT91C_ID_US0]=
(AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 0x4);//在AIC源模式寄存器中[6]
//在AIC中断启用命令寄存器中启用USART0中断
pAIC->AIC_IECR=(1US_IER=AT91C_US_ENDRX;//启用ENDRX usart0接收中断结束
pUSART0->US_IDR=~AT91C_US_ENDRX;//禁用除ENDRX之外的所有中断
}
//------------------
//文件结束
//------------------

在设置中断中的计数(US\u RCR)之前,您需要重新初始化接收指针:

pUSART0->US_RPR = (unsigned int)Buffer;
您的设备可能出现故障,因为PDC正在缓冲区外写入数据。

有两个问题:
1-当我使用Keil uVision时,我需要使用
\uu irq
来定义中断服务例程!
2-令人惊讶的是,中断结束时没有触发!因此使用:
*AT91C\U AIC\U 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
}

标准警告;使用
stdint.h
固定宽度类型而不是标准类型。Ooops:)我忘记重置缓冲区,但这与问题无关。我找到了原因并将其作为答案发布