全志R40 串口485 控制操作

   485与串口的打开,读写操作一样,唯一的区别是485多了一个控制脚。控制脚低电平有效。

    因为485是半双工工作模式,同一时间只能读或者只能写,所以设计之初就是当需要进行发送数据时,将控制引脚拉低,当发送完后需要立刻拉高,处于接收状态。 这里面临一个问题,发送完,控制脚拉高快了会导致对方数据接收不完全,如果控制脚拉高慢了,又会导致接收数据不完全。所以在应用层来控制这个脚非常不合适,只能在驱动里面修改。下面是驱动里面的修改方式:

static void sw_uart_stop_tx(struct uart_port *port)

{

struct sw_uart_port *sw_uport = UART_TO_SPORT(port);

 

if (sw_uport->ier & SUNXI_UART_IER_THRI) {

sw_uport->ier &= ~SUNXI_UART_IER_THRI;

SERIAL_DBG("stop tx, ier %x\n", sw_uport->ier);

serial_out(port, sw_uport->ier, SUNXI_UART_IER);

}

        if(0 == strcmp("uart2", sw_uport->name))

        {

            char pin_name[8] = {0};

            unsigned long config_set = 0;

    unsigned long config_get = 0;

            printk("sw_uart_stop_tx\n");

            //msleep(5);  

            //__gpio_set_value(41,1);

            int val=__gpio_get_value(41);

            printk("value is %d\n",val);

            //sunxi_gpio_to_name(GPIOB(9), pin_name);

            //config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC,1);

            //pin_config_set(SUNXI_PINCTRL,pin_name,config_set);

    //config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT,1);

    //pin_config_set(SUNXI_PINCTRL,pin_name,config_set);

//config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT,0XFFFF);

//pin_config_get(SUNXI_PINCTRL,pin_name,&config_get); //取GPIO值

//printk("     [%s] pin value: %ld\n",pin_name,SUNXI_PINCFG_UNPACK_VALUE(config_get));

        }

}

 

static void sw_uart_start_tx(struct uart_port *port)

{

struct sw_uart_port *sw_uport = UART_TO_SPORT(port);

        if(0 == strcmp("uart2", sw_uport->name))

        {

            char pin_name[8] = {0};

            unsigned long config_set = 0;

    unsigned long config_get = 0;

            printk("sw_uart_start_tx\n");

            __gpio_set_value(41,0);

            int val=__gpio_get_value(41);

            printk("value is %d\n",val);

            //sunxi_gpio_to_name(GPIOB(9), pin_name);

            //config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC,1);

            //pin_config_set(SUNXI_PINCTRL,pin_name,config_set);

    //config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT,0);

    //pin_config_set(SUNXI_PINCTRL,pin_name,config_set);

//config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT,0XFFFF);

//pin_config_get(SUNXI_PINCTRL,pin_name,&config_get); //取GPIO值

//printk("     [%s] pin value: %ld\n",pin_name,SUNXI_PINCFG_UNPACK_VALUE(config_get));

        }

if (!(sw_uport->ier & SUNXI_UART_IER_THRI)) {

sw_uport->ier |= SUNXI_UART_IER_THRI;

SERIAL_DBG("start tx, ier %x\n", sw_uport->ier);

serial_out(port, sw_uport->ier, SUNXI_UART_IER);

}

}

 

static void sw_uart_handle_tx(struct sw_uart_port *sw_uport)

{

struct circ_buf *xmit = &sw_uport->port.state->xmit;

int count;

 

if (sw_uport->port.x_char) {

serial_out(&sw_uport->port, sw_uport->port.x_char, SUNXI_UART_THR);

sw_uport->port.icount.tx++;

sw_uport->port.x_char = 0;

#ifdef CONFIG_SW_UART_DUMP_DATA

sw_uport->dump_buff[sw_uport->dump_len++] = sw_uport->port.x_char;

SERIAL_DUMP(sw_uport, "Tx");

#endif

return;

}

if (uart_circ_empty(xmit) || uart_tx_stopped(&sw_uport->port)) {

sw_uart_stop_tx(&sw_uport->port);

        if(0 == strcmp("uart2", sw_uport->name))   // 此处只有接收到数据才会执行,猜测是处理接收的,这里还没有进一步测试

        {

            printk("sw_uart_handle_tx 1\n");

            __gpio_set_value(41,1);

            int val=__gpio_get_value(41);

            printk("value is %d\n",val);

        }

return;

}

count = sw_uport->port.fifosize / 2;

do {

#ifdef CONFIG_SW_UART_DUMP_DATA

sw_uport->dump_buff[sw_uport->dump_len++] = xmit->buf[xmit->tail];

#endif

serial_out(&sw_uport->port, xmit->buf[xmit->tail], SUNXI_UART_THR);

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

sw_uport->port.icount.tx++;

if (uart_circ_empty(xmit)) {

break;

}

} while (--count > 0);

 

SERIAL_DUMP(sw_uport, "Tx");

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {

spin_unlock(&sw_uport->port.lock);

uart_write_wakeup(&sw_uport->port);

spin_lock(&sw_uport->port.lock);

}

if (uart_circ_empty(xmit))

        {

sw_uart_stop_tx(&sw_uport->port);

        if(0 == strcmp("uart2", sw_uport->name)) //此处是关键

        {

           udelay(400);

            printk("sw_uart_handle_tx 2\n");

            __gpio_set_value(41,1);

            int val=__gpio_get_value(41);

            printk("value is %d\n",val);

        }

        }

}

经过测试在stop里面操作控制脚会导致数据发送不完整。所以改到sw_uart_handle_tx 这里面去操作。

 

备注:在stop里面加入msleep 或者使用SUNXI_PINCTRL的方式操作控制脚都会出现内核错误。

如果同时开启多个485串口,同时操作的时候仍然会偶尔出现数据发送不完全的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值