| 
 
| 先说一下环境:<br />lpc2220,模板是zlg网站上的最新版本。<br /><br /><br />概述:<br />我自己写了一个串口驱动,现在UART0自收自发,UART1自收自发都正常,UART0,UART1“接力”的时候会出现问题。<br />所谓的接力是指同时启用Uart0,Uart1,Uart0将自己收到的数据通过Uart1发送出去,同时,Uart1将自己收到的数据通过Uart0发送出去。<br /><br /><br />现象:<br />在我调试的时候发现,两个串口会正常工作一段时间,然后R14不知道什么样的原因被莫名其妙的修改,在下文所述的UART1_EnableTX(),以及于此类似的UART0_EnableTX(),函数返回时R14存储的值指向自身函数的入口,出现死循环的情况。<br /><br /><br />问题:<br />不知道各位有没有遇到过类似的情况?如果有,是什么样的原因造成的?<br />另外,有一个概念我一直没弄明白,假设当前程序正在Uart1的中断服务程序(低优先)中,然后这个时候产生了Uart0中断(高优先),程序会跳转到Uart0的中断服务程序中么?<br /><br /><br />供参考的资料:<br />void UART1_DisableTX()<br />{<br />    U1IER = U1IER & (~0x02);<br />}<br /><br />void UART1_EnableTX()<br />{<br />    U1IER = U1IER | 0x02;<br />}<br /><br />UART1_EnableTX的汇编代码如下:<br />80005a48    [0xe59f0114]   ldr      r0,0x80005b64 ; = #0xe000c000<br />80005a4c    [0xe5d00004]   ldrb     r0,[r0,#4]<br />80005a50    [0xe3800002]   orr      r0,r0,#2<br />80005a54    [0xe59f1108]   ldr      r1,0x80005b64 ; = #0xe000c000<br />80005a58    [0xe5c10004]   strb     r0,[r1,#4]<br />80005a5c    [0xe1a0f00e]   mov      pc,r14        <==    此处R14=0x80005a48,为函数的入口<br /><br />以下为串口驱动的代码:<br />其中队列部分参考了zlg的队列中间件,我的改动主要使其适合于前后台系统。<br /><br /><br />#define UART1_TXD_SEL        (1 << 16)        //P0.8<br />#define UART1_RXD_SEL        (1 << 18)        //P0.9<br />void UART1_InitTxdRxd(void)    { PINSEL0 |= UART1_TXD_SEL | UART1_RXD_SEL;}<br /><br />#define UART1_MODEMSEL        (1 << 20) | (1 << 22) | (1 << 24) | (1 << 26) | (1 << 28) | (1 << 30) <br />void UART1_InitModem(void)    { PINSEL0 |= UART1_MODEMSEL; }<br /><br />volatile uint8 acUart1RxBuff[UART1_RX_QUEUE_SIZE];<br />volatile uint8 acUart1TxBuff[UART1_TX_QUEUE_SIZE];<br />volatile struct _tag_Queue stUart1RxQueue;<br />volatile struct _tag_Queue stUart1TxQueue;<br /><br />void /*  __irq*/ IRQ_UART1(void)<br />{<br />    uint8 nState;<br />    nState = (U1IIR & 0x0E) >> 1;<br />    switch(nState)<br />    {<br />    case 0x06://字符超时<br />    case 0x02://接收<br />        {<br />            QueuePushOneChar(&stUart1RxQueue, U1RBR);<br />            break;<br />        }<br />    case 0x01://发送<br />        {<br />            if(QueuePullOneChar(&stUart1TxQueue, &nState) == 1)<br />                U1THR = nState;<br />            break;<br />        }<br />    case 0x00://MODEM中断<br />        {<br />            nState = U1MSR;<br />            break;<br />        }<br />    case 0x03://接受线状态<br />        {<br />            nState = U0LSR;<br />            nState = U0RBR;<br />            break;<br />        }<br />    }<br />    nEnterTimes1--;<br />    VICVectAddr = 0x00;                  // 中断处理结束    <br />}<br /><br />void UART1_Init(void)<br />{<br />    UART1_InitTxdRxd();<br />    QueueInit(acUart1RxBuff, UART1_RX_QUEUE_SIZE, &stUart1RxQueue);<br />    QueueInit(acUart1TxBuff, UART1_TX_QUEUE_SIZE, &stUart1TxQueue);<br /><br />    VICIntEnClr = 1 << 7;                //禁能中断<br />}<br /><br /><br />uint32 UART1_SetMode(const UARTMODE *pMode)<br />{<br />    extern void IRQ_Def(void);<br />    extern void UART1_Handler(void);<br />    uint32 i;<br />    uint8 nTemp;<br />    if(UartEx_IsModeValid(pMode) == 0)<br />        return 0;<br />    U1LCR = 0x80;                        // DLAB位置1<br /><br />    i = (Fpclk>>4) / pMode->nBaudRate;    // 设置串口波特率<br />    U1DLM = i >> 8;<br />    U1DLL = i & 0xFF;<br /><br />    nTemp = 0;<br />    nTemp |= (pMode->nDataLen - 5);                //数据长度<br />    nTemp |= (pMode->nStopBitLen - 1) << 2;        //停止位<br />    if(pMode->nParity != 0)                        //是否校验<br />        nTemp |= (pMode->nParity - 1) << 4;        //校验方式<br />    U1LCR = nTemp;<br /><br />    if(pMode->nFullSignal != 0)<br />        UART1_InitModem();<br /><br />    U1FCR = 0x01;                       // 使能FIFO,并设置触发点为1字节<br />    U1IER = 0x03;                        // 接收中断,发送中断<br /><br />    VICIntEnClr = 1 << 7;                //禁能中断<br /><br />    VICIntSelect &= (~(1 << 7));        //设置UART1中断分配为IRQ中断<br />    VICVectCntl2 = 0x20 | 7;            //UART1中断<br />    VICVectAddr2 = (int)UART1_Handler;    //设置UART1中断服务程序地址<br /><br />    VICDefVectAddr = (int)IRQ_Def;<br /><br />    VICIntEnable = 1 << 7;                //使能中断<br />    return 1;<br />}<br />void UART1_DisableRX()<br />{<br />    U1IER = U1IER & (~0x01);<br />}<br />void UART1_EnableRX()<br />{<br />    U1IER = U1IER | 0x01;<br />}<br />void UART1_DisableTX()<br />{<br />    U1IER = U1IER & (~0x02);<br />}<br />void UART1_EnableTX()<br />{<br />    U1IER = U1IER | 0x02;<br />}<br /><br />uint8  UART1_Send(const uint8 *pnData, uint8 nDataLen)<br />{<br />    volatile struct _tag_Queue *pstQueue = &stUart1TxQueue;<br />    uint8 nLen;<br />    uint8 temp;<br />    UART1_DisableTX();<br />    nLen = QueuePushIn(pstQueue, pnData, nDataLen);<br />    if ((U1LSR & 0x00000020) != 0)<br />    {                                               /* UART0发送保持寄存器空 */<br />        QueuePullOut(pstQueue, 1, &temp);             /* 发送最初入队的数据 */<br />        U1THR = temp;<br />    }<br />    UART1_EnableTX();<br />    return nLen;<br />}<br /><br />uint8 UART1_Receive(uint8 *pnData, uint8 nDataLen)<br />{<br />    volatile struct _tag_Queue *pstQueue = &stUart1RxQueue;<br />    uint8 nLen = 0;<br />    if(QueueGetSize(pstQueue) >= nDataLen)<br />    {<br />        UART1_DisableRX();<br />        QueuePullOut(pstQueue, nDataLen, pnData);<br />        UART1_EnableRX();<br />        nLen = nDataLen;<br />    }<br />    return nLen;<br />} | 
 |