您的位置:首页 > 其它

海思3518c普通串口更换RS485通讯

2017-11-14 08:53 405 查看
源:http://blog.csdn.net/edw200/article/details/52251385?readlog

方案需求:

3518c串口1(uart1)有三个管脚,tx、rx和rtsn收发控制端口。在使用普通的串口时,rtsn管脚是没有用的的,但是485需要用到,这里因暂时不知道海思底层是否有自动设置rtsn管脚功能,所以这里先将该管脚设置为普通gpio管脚用来手动控制高低电平,以实现我们需要的485工作模式。

这里遇到一个问题,就是当我们发送完数据后,就是往UART01x_DR数据寄存器写数据,并判断UART_FR寄存器标准为是否发送完成(海思文档是这么写的),确实,数据通过FIFO发送完成后完成标志会置位,但是实际的管脚还在工作(常态为低电平,当发送标志位置位后,rtsn管脚还是搞电平,需要一段时间才变成低电平),异步工作。

所以我们就需要设计一个延时机制,当tx管脚还在工作时,rtsn必须高电平,当tx完成发送时,rtsn为低电平。

程序设计:

海思是使用amba架构,所以在amba-pl011.c中:

1.发送中启动rtsn管脚,pl011_start_tx函数中添加:

[cpp] view
plain copy

<pre name="code" class="cpp">static void pl011_start_tx(struct uart_port *port)  

{  

    struct uart_amba_port *uap = (struct uart_amba_port *)port;  

    if (!pl011_dma_tx_start(uap)) {  

        uap->im |= UART011_TXIM;  

        writew(uap->im, uap->port.membase + UART011_IMSC);  

    }  

    if(uap->port.line == 1) 判断为串口1方式  

    {     

        writel(0xFF, IO_ADDRESS(0x20160010));设置rtsn高电平  

        txdatafirsttimens =  local_clock(); //获取基准时间  

    }  

      

}  



2.发送停止中处理延时清除rtsn管脚电平,pl011_stop_tx函数:

[cpp] view
plain copy

unsigned long txdatecount = 0;  //定义发送数据字节数。  

unsigned long long txdatafirsttimens =0;//定义发送数据基准时间。  

static void pl011_stop_tx(struct uart_port *port)  

{  

    struct uart_amba_port *uap = (struct uart_amba_port *)port;  

    uap->im &= ~UART011_TXIM;  

    writew(uap->im, uap->port.membase + UART011_IMSC);  

    pl011_dma_tx_stop(uap);  

  

    if(uap->port.line == 1 )  

    {     

        unsigned long long txdatalocaltimens= 0; //定义数据发送当前时间(纳秒)  

        unsigned int txdatalocaltimeus= 0; //定义数据发送当前时间(微秒)  

        unsigned int txdateusetime = 0; //定义数据发送时间需要时间  

  

        /* 平均100发送一百个字节需要占用52毫秒(硬件控制管脚) 

            这里机制是在发送函数获取一个基准时间,并在停止函数中获取当前时间 

            与所发字节需要时间对比判断。 

        */  

        txdateusetime = txdatecount * 520;  

        txdatecount = 0;  

          

        while(1)  

        {  

            txdatalocaltimens= local_clock(); //获取当前时间  

            txdatalocaltimeus= (txdataendtimens - txdatafirsttimens);  

            txdatalocaltimeus= txdatalocaltimeus/ 1000;  

              

            if(txdateusetime <= txdatalocaltimeus) //当前时间超过实际需要时间  

                break;  

            udelay(10);//10微秒级别  

        }  

        udelay(50);//这里是为一个拉低管脚缓冲时间,防止过早拉低。  

        writel(0, IO_ADDRESS(0x20160010));  

        //printk("txdateusetime:%d,txdatausetimeus:%d\n",txdateusetime,txdatausetimeus);  

    }  

}  

3.计算发送字节,pl011_tx_chars

在该函数中添加:

[cpp] view
plain copy

do {  

        writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);  

        xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);  

        uap->port.icount.tx++;  

  

        if(uap->port.line == 1)  

        {  

            txdatecount++;  

        }  

          

        if (uart_circ_empty(xmit))  

            break;  

    } while (--count > 0);  

4.初始化函数pl011_init

[cpp] view
plain copy

static int __init pl011_init(void)  

{  

    int ret;  

    printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");  

  

    /* 

     * 添加RTSN收发控制。 

     */  

    unsigned int u32Temp;  

    u32Temp = readl(IO_ADDRESS(0x200F0020));      

    printk("GPIO_RTSN is %02x\n",u32Temp);  

    writel(0x00, IO_ADDRESS(0x200F0020));  

      

    u32Temp = readl(IO_ADDRESS(0x20160400));      

    u32Temp |= (1 << 2);    

    writel(u32Temp, IO_ADDRESS(0x20160400));  

    writel(0, IO_ADDRESS(0x20160010));  

  

    ret = uart_register_driver(&amba_reg);  

    if (ret == 0) {  

        ret = amba_driver_register(&pl011_driver);  

        if (ret)  

            uart_unregister_driver(&amba_reg);  

    }  

    return ret;  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  海思 UART RS485