// ============================================================================= // 功能: 启动串口发送,其目的是触发中断,用中断方式发送数据。 // 参数: PrivateTag,被操作的串口设备指针数值. // 返回: 发送的个数 // ============================================================================= static u32 __UART_SendStart (tagUartReg *Reg,u32 timeout) { u8 fifodep=1,num,ch[8],port; switch((u32)Reg) { //UART0和UART1的FIFO深度为8,而其他的为1 case CN_UART0_BASE: port = CN_UART0; fifodep = 8; break; case CN_UART1_BASE: port = CN_UART1; fifodep = 8; break; case CN_UART2_BASE: port = CN_UART2; break; case CN_UART3_BASE: port = CN_UART3; break; case CN_UART4_BASE: port = CN_UART4; break; case CN_UART5_BASE: port = CN_UART5; break; default:return 0; } __UART_TxIntDisable(Reg); if(__UART_TxTranEmpty(Reg)) { fifodep = UART_PortRead(pUartCB[port],ch,fifodep,0);// UART的FIFO大小为8字节 for(num = 0; num < fifodep; num++) { Reg->D = ch[num]; } } __UART_TxIntEnable(Reg); return num; }
// ============================================================================= // 功能: 使用中断方式效率能够大大提升软件执行效率;包括接收、发送和异常等,接收到数据 // 后,调用通用接口模块,写入软件缓冲区;发送数据时,调用通用接口模块,从软件缓 // 冲区读出数据,写入硬件发送寄存器;此外,根据芯片,可通过DMA方式发送 // 参数: 中断号. // 返回: 0. // ============================================================================= uint32_t UART_ISR(ufast_t IntLine) { static struct tagUartCB *UCB; tagUartReg *Reg; uint32_t timeout = 1000,num; uint8_t ch,*puart_dma_send_buf,*puart_dma_recv_buf; uint32_t IIR=0,Port,DmaBufLen,DmaRcvLen; switch(IntLine) { case CN_INT_LINE_UART0: Port = CN_UART0; UCB = pUartCB[Port]; Reg = (tagUartReg *)CN_UART0_BASE; DmaBufLen = UART0_DMA_BUF_LEN; DmaRcvLen = s_UART0_DmaRcvLen; puart_dma_send_buf = (uint8_t*)UART0_DmaSendBuf; puart_dma_recv_buf = (uint8_t*)UART0_DmaRecvBuf; break; case CN_INT_LINE_UART1: Port = CN_UART1; UCB = pUartCB[Port]; Reg = (tagUartReg *)CN_UART1_BASE; DmaBufLen = UART1_DMA_BUF_LEN; DmaRcvLen = &s_UART1_DmaRcvLen; puart_dma_send_buf = (uint8_t*)UART1_DmaSendBuf; puart_dma_recv_buf = (uint8_t*)UART1_DmaRecvBuf; break; case CN_INT_LINE_USART0: Port = CN_USART0; UCB = pUartCB[Port]; Reg = (tagUartReg *)CN_UART1_BASE; DmaBufLen = USART0_DMA_BUF_LEN; DmaRcvLen = &s_USART0_DmaRcvLen; puart_dma_send_buf = (uint8_t*)USART0_DmaSendBuf; puart_dma_recv_buf = (uint8_t*)USART0_DmaRecvBuf; break; case CN_INT_LINE_USART1: Port = CN_USART1; UCB = pUartCB[Port]; Reg = (tagUartReg *)CN_UART1_BASE; DmaBufLen = USART1_DMA_BUF_LEN; DmaRcvLen = &s_USART1_DmaRcvLen; puart_dma_send_buf = (uint8_t*)USART1_DmaSendBuf; puart_dma_recv_buf = (uint8_t*)USART1_DmaRecvBuf; break; default: return 0; } IIR = Reg->UART_SR; if(s_UART_DmaUsed[Port] == cn_dma_unused)//非DMA方式发送和接收 { if((IIR & (1<<0)) && (Reg->UART_IMR &(1<<0)))//rxrdy int { ch = Reg->UART_RHR; num = UART_PortWrite(UCB,&ch,1,0); if(num != 1) { UART_ErrHandle(UCB,CN_UART_BUF_OVER_ERR); } } //tx empty int if((IIR &(1<<9)) && (Reg->UART_IMR &(1<<9))) { num = UART_PortRead(UCB,&ch,1,0); while((!__UART_TxTranEmpty(Reg)) && (timeout-- > 0)); if(num != 0) Reg->UART_THR = ch; else { __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); } } } else //DMA方式发送和接收 { if((IIR & (1<<3)) && (Reg->UART_IMR &(1<<3)))//endrx int { if(DmaRcvLen > DmaBufLen) //计算从DMA BUF中读多少数据 num = DmaBufLen; else num = DmaRcvLen; UART_PortWrite(UCB,puart_dma_recv_buf,num,0); DmaRcvLen = DmaRcvLen - num; if(DmaRcvLen > DmaBufLen) //计算下次DMA接收数据量 Reg->UART_RCR = DmaBufLen; else if(DmaRcvLen > 1) Reg->UART_RCR = DmaRcvLen; else //接收DMA最少为1 { Reg->UART_RCR = 1; DmaRcvLen = 1; } Reg->UART_RPR = (vu32)puart_dma_recv_buf; } if((IIR & (1<<11)) && (Reg->UART_IMR &(1<<11)))//txbufe int { while(!(Reg->UART_SR & (1<<9)));//wait for empty num = UART_PortRead(UCB,puart_dma_send_buf, DmaBufLen,0); if(num > 0) { Reg->UART_PTCR = (1<<9);//diable dma tx if((Reg->UART_TCR==0)&&(Reg->UART_TNCR==0)) { // num = UART_PortRead(UCB,puart_dma_send_buf, // DmaBufLen,0); Reg->UART_TPR = (uint32_t)puart_dma_send_buf; Reg->UART_TCR = num; } Reg->UART_PTCR = (1<<8);//enable dma tx } else { //是否需禁止 dma tx int while(!__UART_TxTranEmpty(Reg)); __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); } } } if(IIR &(0xE0)) //其他中断 { UART_ErrHandle(UCB,CN_UART_HARD_COMM_ERR); } return 0; }
// ============================================================================= // 功能: UART的中断服务函数,包括发送空、接收、错误三种中断。 // 1.接收中断,从接收FIFO中读数据,并调用UART_PortWrite写入接收缓冲区中; // 2.发送中断,调用UART_PortRead读发送缓冲区中数据,并写入发送FIFO; // 3.错误中断,弹出错误事件 // 参数: 中断线号. // 返回: 0. // ============================================================================= static u32 UART_ISR(ptu32_t IntLine) { struct UartCB *UCB; volatile tagUartReg *Reg; u32 i,fifodep=1,num=0; u8 ch[16]; switch(IntLine) { case CN_INT_LINE_UART0_RX_TX: case CN_INT_LINE_UART0_ERR: UCB = pUartCB[CN_UART0]; Reg = tg_UART_Reg[CN_UART0]; fifodep = 8; break; case CN_INT_LINE_UART1_RX_TX: case CN_INT_LINE_UART1_ERR: UCB = pUartCB[CN_UART1]; Reg = tg_UART_Reg[CN_UART1]; fifodep = 8; break; case CN_INT_LINE_UART2_RX_TX: case CN_INT_LINE_UART2_ERR: UCB = pUartCB[CN_UART2]; Reg = tg_UART_Reg[CN_UART2]; break; case CN_INT_LINE_UART3_RX_TX: case CN_INT_LINE_UART3_ERR: UCB = pUartCB[CN_UART3]; Reg = tg_UART_Reg[CN_UART3]; break; case CN_INT_LINE_UART4_RX_TX: case CN_INT_LINE_UART4_ERR: UCB = pUartCB[CN_UART4]; Reg = tg_UART_Reg[CN_UART4]; break; case CN_INT_LINE_UART5_RX_TX: case CN_INT_LINE_UART5_ERR: UCB = pUartCB[CN_UART5]; Reg = tg_UART_Reg[CN_UART5]; break; default:return 0; } if(Reg->S1 & UART_S1_RDRF_MASK) //接收中断标志 { for(num = 0; num < fifodep; num++) { if(!(Reg->SFIFO & UART_SFIFO_RXEMPT_MASK)) ch[num] = Reg->D; else break; } UART_PortWrite(UCB,ch,num,0); } if(Reg->S1 & UART_S1_TDRE_MASK) //发送中断标志 { num = UART_PortRead(UCB,ch,fifodep,0); if(num>0) { for(i = 0; i < num; i++) Reg->D = ch[i++]; } else { __UART_TxIntDisable(Reg); } } if(Reg->S1 & (UART_S1_FE_MASK | UART_S1_PF_MASK)) //硬件错误 { UART_ErrHandle(UCB,CN_UART_HARD_COMM_ERR); } return 0; }