⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.c

📁 基于ARM的UART串口驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
                case MSR_DELTA_CTS:
                    if(IO0PIN & (1 << 11))  //CTS1 Modem -> ARM
                    {
                        WR_UREG(NET_HANDLE->base, TER, TER_DIS_TXEN);
                    }
                    else
                    {
                        WR_UREG(NET_HANDLE->base, TER, TER_EN_TXEN);
                    }
                    break;

                default:
                    break;
            }
            
        default:
            break;
    }
    
    VICVectAddr = 0x00;
}

/*******************************************************************************
* 名称:uart_usr_auto_baud()
* 功能:用户口速率自适应
* 参数:无
* 返回:true    表示成功检测到波特率并设置好波特率
	    false   自动波特率检测失败
*******************************************************************************/

u8 uart_usr_auto_baud(void)
{
	u8 err;
	
	auto_baud_state__ = FIRST_HIGH;	//状态机初始化
	Timer0_Init();	//初始化定时器0为捕捉模式	
	
	//RXD引脚选为普通输入脚
	PINSEL0 &= 0xFFFFFFF3;
	IO0DIR &= 0xFFFFFFFD;
	CTS0_LOW();
	OSSemPend(auto_baud_sem__, AUTO_FAILED_TIME, &err);
	
    //禁止定时器0,禁止捕捉中断
    T0CCR = 0;
    T0TCR = TIMER_DISABLE;
	
    if (err != OS_NO_ERR)	//超时
	{
		return FALSE;
	}
	CTS0_HIGH();
	return auto_baud_ok;
}

/*******************************************************************************
* 名称:optimize__()
* 功能:计算最优分频系数
* 参数:tmp_div	用于比较的分频系数
* 返回:div	    最佳分频系数
*******************************************************************************/
static uf32 optimize__(uf32 tmp_div)
{
	const uf32 divpool[8] = {Fpclk/(16 * 1200),  Fpclk/(16 * 2400),  \
	                        Fpclk/(16 * 4800),  Fpclk/(16 * 9600),  \
	                        Fpclk/(16 * 19200), Fpclk/(16 * 38400), \
	                        Fpclk/(16 * 57600), Fpclk/(16 * 115200)};
	uf32 div = FALSE, i;
	
	tmp_div /= 32;
	for(i = 0; i < 8; i++)
	{
		if( tmp_div > (divpool[i] - divpool[i] / 8) &&   \
		    tmp_div < (divpool[i] + divpool[i] / 8))
		{
			div = divpool[i];
			break;
		}
	}
	return div;
}

/*******************************************************************************
* 名称:cap_isr__()
* 功能:串口捕捉中断
* 参数:无
* 返回:无
*******************************************************************************/
void cap_isr__(void)
{
    uf32 tmp;
    uf32 first_low_cnt=0,sec_high_cnt=0,sec_low_cnt=0,stop_high_cnt=0;
    
	auto_baud_ok = 0;
	auto_baud_state__ = FIRST_HIGH; 
	CTS0_HIGH();
	VICIntEnClr = EN_IRQ_TIMER0;
	T0TCR = TIMER_RST;
	T0TCR = TIMER_EN;
	//配置捕获引脚为IO脚
	PINSEL0 &= 0xFFFFFFCF;
	IO0DIR &= (~0x00000004);
	while(T0TC < 0x60000)
	{
	    switch(auto_baud_state__)
	    {
		    case FIRST_HIGH:
				if(IO0PIN & 0x00000004)
				{
					T0TCR = TIMER_RST;
					T0TCR = TIMER_EN;	
					auto_baud_state__ = FIRST_LOW;
				}
				break;
	    	case FIRST_LOW:
	    		if(!(IO0PIN & 0x00000004))
	    		{
	    			first_low_cnt = T0TC;
	    			auto_baud_state__ = SEC_HIGH;
	    		}
	    		break;
	    	case SEC_HIGH:
	    		if(IO0PIN & 0x00000004)
	    		{
	    			sec_high_cnt = T0TC;
	    			auto_baud_state__ = SEC_LOW;
	    		}
	    		break;
	    	case SEC_LOW:
	    		if(!(IO0PIN & 0x00000004))
	    		{
	    			sec_low_cnt = T0TC;
	    			auto_baud_state__ = STOP_HIGH;    	
	    		}
	    		break;
	    	case STOP_HIGH:
	    		if(IO0PIN & 0x00000004)
	    		{
	    			stop_high_cnt = T0TC;
	    			auto_baud_ok = 1;
	    		}
	    		break;
	    	default :
	    		break;
	    }
	    if(auto_baud_ok) break;
	}
	if(auto_baud_ok)
	{
		if((sec_high_cnt-sec_high_cnt/10) <first_low_cnt*5 && \
			first_low_cnt*5	<(sec_high_cnt+sec_high_cnt/10)&& \
			(sec_low_cnt-sec_low_cnt/10) <first_low_cnt*7  && \
			first_low_cnt*7 <(sec_low_cnt+sec_low_cnt/10)  && \
			(stop_high_cnt-stop_high_cnt/10) <first_low_cnt*8 && \
			first_low_cnt*8<(stop_high_cnt+stop_high_cnt/10))
		{
			auto_baud_ok=3;
		}
		if((sec_high_cnt-sec_high_cnt/10) <first_low_cnt*6 && \
			first_low_cnt*6 <(sec_high_cnt+sec_high_cnt/10)&& \
			(sec_low_cnt-sec_low_cnt/10) <first_low_cnt*7  && \
			first_low_cnt*7<(sec_low_cnt+sec_low_cnt/10)   && \
			(stop_high_cnt-stop_high_cnt/10) <first_low_cnt*8 && \
			first_low_cnt*8<(stop_high_cnt+stop_high_cnt/10))
		{
			auto_baud_ok=4;
		}
		tmp = 0;
		if(auto_baud_ok==3 || auto_baud_ok==4)tmp = optimize__(first_low_cnt*2);
		else auto_baud_ok = 0;
		if(tmp)
	    {
	            //设置用户口波特率
	            U0LCR |= LCR_EN_DIV;
	            U0DLM = tmp >> 8;
	            U0DLL = tmp & 0xff;
	            U0LCR &= 0xFFFFFF7F;
	            
	            //设置网络口波特率
	            U1LCR |= LCR_EN_DIV;
	            U1DLM = tmp >> 8;
	            U1DLL = tmp & 0xff;
	            U1LCR &= 0xFFFFFF7F;
	            
	            //将P0.1由I/O口改为RXD口
	           	PINSEL0 = (PINSEL0 & 0xFFFFFFF3) | RXD0;
	           	PINSEL0 |= 0x00000004;
				IO0DIR |= 0x00000002;
	           	OSSemPost(auto_baud_sem__);	         	
	    }		
	}      
}

/*******************************************************************************
* 名称:rts0_eint2()
* 功能:RTS0流控中断服务程序
* 参数:无
* 返回:无
*******************************************************************************/
void rts0_eint2(void)
{
    if(RTS0_STATUS())
    {
        WR_UREG(USR_HANDLE->base, TER, TER_DIS_TXEN);
        EXTPOLAR &= 0xFB;   //改为下降沿触发
    }
    else
    {
        WR_UREG(USR_HANDLE->base, TER, TER_EN_TXEN);
        EXTPOLAR |= 0x04;   //改为上升沿触发
    }
    
    EXTINT = CLR_IRQ_EINT2;
	VICVectAddr = 0x00;
}

/*******************************************************************************
* 名称:init__()
* 功能:初始化串口
* 参数:hnd     串口句柄
* 返回:无
*******************************************************************************/
static void init__(handle_t hnd)
{
    extern void uart_usr_handler(void);
    extern void uart_net_handler(void);
    extern void rts0_eint2_handler(void);
    
    if (hnd == USR_HANDLE)
    {
    	CTS0_HIGH();    //给PC流控  
    	  
        PINSEL0 |= TXD0;  //TXD0作为发送引脚,RXD0作为接收脚
        //PINSEL0 |= (TXD0 | RXD0);  
	    
        //初始化模拟流控信号
        if(PCB_VERSION)  //新版本
        {
	        IO0DIR |= CTS0 ; //
	    	IO0DIR &= ~RTS0;// 	
        }
    	else			//老版本
    	{
    		IO0DIR |= CTS0 ;
    		IO0DIR &= ~RTS0;
    	}
		
    	//初始化串口寄存器
        hnd->base = USR_BASE;
        WR_UREG(hnd->base, IER, IER_RBR | IER_THRE);
        WR_UREG(hnd->base, FCR, FCR_FIFO | FCR_RX_8_TOUCH);
        WR_UREG(hnd->base, LCR, LCR_DATA_8BITS | LCR_EN_DIV);
        WR_UREG(hnd->base, LCR, LCR_DATA_8BITS);
	    
        //初始化流控中断
        PINSEL0 |= RTS0_EINT2;  //P0.7=>EINT2
        EXTMODE |= 0x04;

        //根据RTS0来决定发送的使能
        if(RTS0_STATUS())
        {
            WR_UREG(hnd->base, TER, TER_DIS_TXEN);
            EXTPOLAR &= 0xFB;
        }
        else
        {
            WR_UREG(hnd->base, TER, TER_EN_TXEN);
            EXTPOLAR |= 0x04;
        }
        
        VICVectCntl8 = EN_IRQ | IRQ_EINT2;
        VICVectAddr8 = (u32)rts0_eint2_handler;
        EXTINT = CLR_IRQ_EINT2;
        VICIntEnable |= EN_IRQ_EINT2;
        
        //初始化用户口中断
    	VICVectCntl5 = EN_IRQ | IRQ_UART0;
    	VICVectAddr5 = (u32)uart_usr_handler;
    	VICIntEnable |= EN_IRQ_UART0;
    }
    else if (hnd == NET_HANDLE)
    {
        //UART1引脚功能选择
        PINSEL0 |= (TXD1 | RXD1);
        //RTS1、DSR1和DTR1作为IO脚
        if(PCB_VERSION)
        {
	        IO0DIR |= U1RTS1 ;
	        RTS1_HIGH();    //给MODEM流控     	
        }
        else
        {
	        IO0DIR |= U1RTS1;
	        
	        RTS1_HIGH();    //给MODEM流控
        }
        
        //初始化串口寄存器
        hnd->base = NET_BASE;
        WR_UREG(hnd->base, IER, IER_RBR | IER_THRE | IER_MODEM_STATUS);
        WR_UREG(hnd->base, FCR, FCR_FIFO | FCR_RX_8_TOUCH);
        WR_UREG(hnd->base, LCR, LCR_DATA_8BITS | LCR_EN_DIV);
        WR_UREG(hnd->base, LCR, LCR_DATA_8BITS);
	    
        //根据CTS1来决定发送的使能
        if(CTS1_STATUS())
        {
            WR_UREG(hnd->base, TER, TER_DIS_TXEN);
        }
        else
        {
            WR_UREG(hnd->base, TER, TER_EN_TXEN);
        }
        PINSEL0 |= CTS1;

        //初始化网络口中断
        VICVectCntl4 = EN_IRQ | IRQ_UART1;
        VICVectAddr4 = (u32)uart_net_handler;
        VICIntEnable = EN_IRQ_UART1;
    }
   // else
   //{
   //    assert(0);
   //}
    
    hnd->tx_sem = OSSemCreate(1);
    hnd->rx_sem = OSSemCreate(0);
    hnd->rx_buf_ptr = NULL;
    hnd->rx_buf_len = 0;
    hnd->wr_buf_ptr = 0;
    hnd->rd_buf_ptr = 0;
    hnd->rx_buf_cnt = 0;
}

/*******************************************************************************
* 名称:uart_usr_init()
* 功能:初始化用户口(UART0)
* 参数:无
* 返回:无
*******************************************************************************/
void uart_usr_init(void)
{    
    init__(USR_HANDLE);
    auto_baud_sem__ = OSSemCreate(0);
    
}

/*******************************************************************************
* 名称:uart_net_init()
* 功能:初始化网络口(UART1)
* 参数:无
* 返回:无
*******************************************************************************/
void uart_net_init(void)
{
    init__(NET_HANDLE);
    
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -