先说一下环境:<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 />} |
|