485串口与232串口的不用之处在于,485串口有一个换向引脚,通过相应的电平信号,完成串口控制器的收发操作。
1 在发送完成之后,将引脚拉低,以便准备接受,操作如下:
在8250_port.c文件中
serial8250_handle_irq->serial8250_tx_chars->__stop_tx(up)->__stop_tx_rs485->__do_stop_tx_rs485->serial8250_em485_rts_after_send(p);添加如下代码,nca9555为gpio控制芯片,是一个i2c设备。
static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p)
{
unsigned char mcr = serial8250_in_MCR(p);
if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND){
pr_info("serial8250_em485_rts_after_send pin to 0\n");
mcr |= UART_MCR_RTS;
//I2cSetSlave(NODE0_I2C0_BASE,NCA9555_I2C_ADDR_WR);
//I2cInitSetFreq(NODE0_I2C0_BASE,CPU_I2C_CLOCK,250000,0x3a);
I2cCtlWrite (NODE0_I2C0_BASE, NCA9555_I2C_ADDR_WR, REGISTER_0_CONFIGURATION_PORT, 2, &setBuff[0]);
I2cCtlWrite (NODE0_I2C0_BASE, NCA9555_I2C_ADDR_WR, REGISTER_0_OUTPUT_PORT, 2, &setBuff[0]);
}else{
// pr_info("serial8250_em485_rts_after_send end\n");
}
//else{
// mcr &= ~UART_MCR_RTS;
// I2cSetSlave(NODE0_I2C0_BASE,NCA9555_I2C_ADDR_WR);
// I2cInitSetFreq(NODE0_I2C0_BASE,CPU_I2C_CLOCK,250000,0x3a);
// I2cCtlWrite (NODE0_I2C0_BASE, NCA9555_I2C_ADDR_WR, REGISTER_0_CONFIGURATION_PORT, 2, &setBuff[0]);
// I2cCtlWrite (NODE0_I2C0_BASE, NCA9555_I2C_ADDR_WR, REGISTER_0_OUTPUT_PORT, 2, &setBuff[0]);
//}
serial8250_out_MCR(p, mcr);
}
2在8250_core.c文件中
serial8250_register_8250_port中添加如下代码
memset((void *)&up->port.rs485, 0, sizeof(up->port.rs485));
up->port.rs485_config = serial8250_rs485_config;
实现rs485_config接口,此举是为了在应用层使用ioctl函数进行rs485_config。
接口实现如下,在使能485时,将引脚拉低。
int serial8250_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
struct uart_8250_port *p= container_of(port,struct uart_8250_port,port);
//serial8250_em485_init(p);
if (rs485->flags & SER_RS485_ENABLED) {
// pr_info("enable 485 set pin to 0\n");
//I2cSetSlave(NODE0_I2C0_BASE,NCA9555_I2C_ADDR_WR);
I2cInitSetFreq(NODE0_I2C0_BASE,CPU_I2C_CLOCK,250000,0x3a);
I2cCtlWrite (NODE0_I2C0_BASE, NCA9555_I2C_ADDR_WR, REGISTER_0_CONFIGURATION_PORT, 2, &setBuff[0]);
I2cCtlWrite (NODE0_I2C0_BASE, NCA9555_I2C_ADDR_WR, REGISTER_0_OUTPUT_PORT, 2, &setBuff[0]);
serial8250_em485_init(p);
//gpio_485_set_direction(true);
//gpio_485_set_value(false);
//tasklet_init(&s485_tasklet, serial8250_485_do_tasklet, (unsigned long)&up->port);
}
else {
// printk(KERN_INFO "uart %d set 485 offn", port->line);
}
memcpy(&port->rs485, rs485, sizeof(*rs485));
return 0;
}
485串口基本修改如上。