打印

AT91SAM7S64大量数据传输时的中断问题?求助

[复制链接]
2381|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
边城浪子|  楼主 | 2008-4-16 20:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
armecos| | 2008-4-16 21:12 | 只看该作者

是不是处理不过来了?按理几个全双工串口同时工作也不会

使用特权

评论回复
板凳
边城浪子|  楼主 | 2008-4-16 23:28 | 只看该作者

把程序贴出来,多位有时间的话帮看看,搞不定了!

   整个系统的工作模式是做一个通信中转,将一个串口接收到的数据从另一个串口发送出去。
      现遇到以下问题:单向的时候,即一个串口收,一个串口发时还是比较稳定地
                      当工作在全双工时,时间一长就会出问题,其中一个串口会接收不到数据
      请问:中断处理上,和初始化上有什么需要注意的?
             两个串口的程序差不多,    

*/
/*
*   初始串口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}^        

使用特权

评论回复
地板
边城浪子|  楼主 | 2008-4-16 23:30 | 只看该作者

应该处理得过来,AT91SARM7S64就干这一点事

两边大约都是每200mS发送20来个byte

使用特权

评论回复
5
xhtxzxw| | 2008-4-17 01:56 | 只看该作者

嘿嘿

调用AT91F_US_Baudrate(SYS_MCK, 57600)设置波特率,系统主时钟SYS_MCK的频率和USx的波特率57600是否匹配啊?
给回来的值要设置给US_BRGR寄存器的,如果误差大了,就容易出错的。

使用特权

评论回复
6
xhtxzxw| | 2008-4-17 02:09 | 只看该作者

??

为啥不把USART0_Handler(void)直接设置成中断服务函数?为啥还要从汇编码子里跳一下啊?

使用特权

评论回复
7
边城浪子|  楼主 | 2008-4-17 11:31 | 只看该作者

。。

波特率应该是对的,汇编主要是为了保存寄存器。

清中断有无问题?如果一个串口进入中断,另一个串口的中断来了,会不会出问题?

使用特权

评论回复
8
armecos| | 2008-4-17 13:47 | 只看该作者

写得太乱了,看不下去,

ecos里有AT91的串口驱动源码,中断驱动源码也有,你可以参考一下。

串口和中断都是非常成熟的技术,你参加一次我们的基础培训就全明白了,光这么回复其实没什么用,因为你的代码本身结构就差,很多细节没有注意到,也许根本就不知道,在这个基础上修补没意义。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

15

帖子

0

粉丝