// ============================================================================= // 功能: 启动串口发送,其目的是触发中断,用中断方式发送数据。 // 参数: 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; }
// ============================================================================= // 功能: 打印函数,直接写串口方式,目前主要由djy_printk独享,用于调试关键代码段 // 参数: 所需要发送的字符串,当然,前提是你提供的一定是字符串'\0'结束 // 返回: 发送的字节个数 // ============================================================================= u32 Uart_SendServiceDirectly(char *str) { u32 result=0,len,timeout=100*mS; tagUartReg *Reg; u32 BaseAddr,Port; if(!strcmp(gc_pCfgStddevName,"UART0") && (sUartInited & (0x01 << CN_UART0))) { BaseAddr = CN_UART0_BASE; Port = CN_UART0; } else if(!strcmp(gc_pCfgStddevName,"UART1")&& (sUartInited & (0x01 << CN_UART1))) { BaseAddr = CN_UART1_BASE; Port = CN_UART1; } else if(!strcmp(gc_pCfgStddevName,"USART0")&& (sUartInited & (0x01 << CN_USART0))) { BaseAddr = CN_USART0_BASE; Port = CN_USART0; } else if(!strcmp(gc_pCfgStddevName,"USART1")&& (sUartInited & (0x01 << CN_USART1))) { BaseAddr = CN_USART1_BASE; Port = CN_USART1; } else return 0; len = strlen(str); Reg = (tagUartReg *)BaseAddr; __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); //disable send INT for(result=0; result < len; result ++) { // 超时或者发送缓冲为空时退出 while((false == __UART_TxTranEmpty(Reg))&& (timeout > 0)) { timeout--; Djy_DelayUs(1); } if(timeout == 0) break; Reg->UART_THR = str[result]; } __UART_SendIntEnable(Reg,s_UART_DmaUsed[Port]); //enable send INT return result; }
// ============================================================================= // 功能:字符终端直接发送函数,采用轮询方式,直接写寄存器,用于printk,或者stdout // 没有初始化 // 参数:str,发送字符串指针 // len,发送的字节数 // 返回:0,发生错误;result,发送数据长度,字节单位 // ============================================================================= s32 Uart_PutStrDirect(const char *str,u32 len) { u32 result = 0,timeout = TxByteTime * len; u16 CR_Bak; CR_Bak = GetCharDirectReg->C2; //Save INT __UART_TxIntDisable(GetCharDirectReg); //disable send INT for(result=0; result < len+1; result ++) { // 超时或者发送缓冲为空时退出 while((false == __UART_TxTranEmpty(PutStrDirectReg))&& (timeout > 10)) { timeout -=10; Djy_DelayUs(10); } if( (timeout <= 10) || (result == len)) break; PutStrDirectReg->D = str[result]; } PutStrDirectReg->C2 = CR_Bak; //restore send INT return result; }
// ============================================================================= // 功能: 使用中断方式效率能够大大提升软件执行效率;包括接收、发送和异常等,接收到数据 // 后,调用通用接口模块,写入软件缓冲区;发送数据时,调用通用接口模块,从软件缓 // 冲区读出数据,写入硬件发送寄存器;此外,根据芯片,可通过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; }
// ============================================================================= // 功能: 这个是直接写串口函数,不会经过事件弹出 // 参数: Reg,UART的寄存器基址. // send_buf,被发送的缓冲数据 // len,发送的数据字节数 // timeout,超时时间,微秒 // 返回: 发送的个数 // ============================================================================= u32 __UART_SendDirectly(tagUartReg* Reg,u8 *send_buf,u32 len,u32 timeout) { u32 result,Port; switch((u32)Reg) { //UART0和UART1的FIFO深度为8,而其他的为1 case CN_UART0_BASE:Port = CN_UART0; break; case CN_UART1_BASE:Port = CN_UART1;break; case CN_USART0_BASE:Port = CN_USART0;break; case CN_USART1_BASE:Port = CN_USART1; break; default:return 0; } __UART_SendIntDisable(Reg,s_UART_DmaUsed[Port]); // __UART_half_duplex_send(Port);//硬件使能发送 if(s_UART_DmaUsed[Port] == false) { for(result=0; result < len; result ++) { while((0 == __UART_TxTranEmpty(Reg)) && (timeout > 0))//超时或者发送缓冲为空时退出 { timeout--; Djy_DelayUs(1); } if(timeout == 0) break; Reg->UART_THR = send_buf[result]; } // //等待发送完再将485通信转为接收 // while((0 == __UART_TxTranEmpty(Reg)) // && (timeout > 0))//超时或者发送缓冲为空时退出 // { // timeout--; // Djy_DelayUs(1); // } // if(timeout == 0) // result = 0; } else { Reg->UART_PTCR = (1<<9);//disable dma send first if((Reg->UART_TCR==0)&&(Reg->UART_TNCR==0)) { Reg->UART_TPR = (uint32_t)send_buf; Reg->UART_TCR = len; Reg->UART_PTCR = (1<<8);//dma tx enbale } else result = 0; //直接发送方式,采用阻塞的DMA发送 while((!__UART_TxTranEmpty(Reg)) && (timeout > 0)) { timeout--; Djy_DelayUs(1); } if(timeout == 0) result = 0; } __UART_SendIntEnable(Reg,s_UART_DmaUsed[Port]); // __UART_half_duplex_recv(Port);//硬件使能接收 return result; }