RS-485采用平衡发送和差分接收,因此具有抑制共模干扰的能力。RS232传输的距离在15米以下,RS485传输距离是几十米到1000米以上。
嵌入式系统上一般使用串口转485,本文以如下原理图为例,讲解RS485总线驱动。
485驱动=串口驱动+GPIO的字符驱动,串口驱动一般都用系统提供的,不需要自己写,需要自己写的只有GPIO字符驱动,并在应用程序中调用GPIO字符驱动及串口驱动。
BUF_XURTS1高电平发送,低电平接收。当然,由于主板采用3.3V供电,核心板采用1.8V供电,是需要经过一颗电平转换芯片的。
主板BUF_XuRXD1信号(经过电平转换芯片→)主板XuRXD1信号(板对板连接器→)核心板处理器GPA0_4;
主板BUF_XuTXD1信号(经过电平转换芯片→)主板XuTXD1信号(板对板连接器→)核心板处理器GPA0_5;
主板BUF_XURTS1信号(经过电平转换芯片→)主板XURTS1信号(板对板连接器→)核心板处理器GPA0_7;
GPIO字符驱动如下:
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include //cwp, PMIC interafce
//#include "gps.h"
#include
#define GPS_DEBUG
#ifdef GPS_DEBUG
#define DPRINTK(x...) printk("MAX485_CTL DEBUG:" x)
#else
#define DPRINTK(x...)
#endif
#define DRIVER_NAME "max485_ctl"
int max485_ctl_open(struct inode *inode,struct file *filp)
{
DPRINTK("Device Opened Success!\n");
return nonseekable_open(inode,filp);
}
int max485_ctl_release(struct inode *inode,struct file *filp)
{
DPRINTK("Device Closed Success!\n");
return 0;
}
int max485_ctl_pm(bool enable)
{
int ret = 0;
printk("firecxx debug: GPS PM return %d\r\n" , ret);
return ret;
};
long max485_ctl_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
printk("firecxx debug: max485_ctl_ioctl cmd is %d\n" , cmd);
switch(cmd)
{
case 1:
if(gpio_request(EXYNOS4_GPA0(7) ,"GPA0_7"))
{
DPRINTK("max485_ctl GPIO err!\r\n");
}
else
{
gpio_direction_output(EXYNOS4_GPA0(7), 1);
DPRINTK("max485_ctl Set High!\n");
gpio_free(EXYNOS4_GPA0(7));
mdelay(100);
}
break;
case 0:
if(gpio_request(EXYNOS4_GPA0(7) ,"GPA0_7"))
{
DPRINTK("max485_ctl GPIO err!\r\n");
}
else
{
gpio_direction_output(EXYNOS4_GPA0(7),0);
DPRINTK("max485_ctl Set Low!\n");
gpio_free(EXYNOS4_GPA0(7));
mdelay(100);
}
break;
default:
DPRINTK("max485_ctl COMMAND ERROR!\n");
return -ENOTTY;
}
return 0;
}
static struct file_operations max485_ctl_ops = {
.owner = THIS_MODULE,
.open = max485_ctl_open,
.release= max485_ctl_release,
.unlocked_ioctl = max485_ctl_ioctl,
};
static struct miscdevice max485_ctl_dev = {
.minor = MISC_DYNAMIC_MINOR,
.fops = &max485_ctl_ops,
.name = "max485_ctl_pin",
};
static int max485_ctl_probe(struct platform_device *pdev)
{
int err = 0;
int ret;
char *banner = "max485_ctl Initialize\n";
printk(banner);
err = gpio_request(EXYNOS4_GPA0(7), "GPA0_7");
if (err) {
printk(KERN_ERR "failed to request GPA0_7 for "
"max485_ctl control\n");
return err;
}
gpio_direction_output(EXYNOS4_GPA0(7), 1);
s3c_gpio_cfgpin(EXYNOS4_GPA0(7), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPA0(7));
ret = misc_register(&max485_ctl_dev);
if(ret<0)
{
printk("max485_ctl:register device failed!\n");
goto exit;
}
return 0;
exit:
misc_deregister(&max485_ctl_dev);
return ret;
}
static int max485_ctl_remove (struct platform_device *pdev)
{
misc_deregister(&max485_ctl_dev);
return 0;
}
static int max485_ctl_suspend (struct platform_device *pdev, pm_message_t state)
{
DPRINTK("max485_ctl suspend:power off!\n");
return 0;
}
static int max485_ctl_resume (struct platform_device *pdev)
{
DPRINTK("max485_ctl resume:power on!\n");
return 0;
}
static struct platform_driver max485_ctl_driver = {
.probe = max485_ctl_probe,
.remove = max485_ctl_remove,
.suspend = max485_ctl_suspend,
.resume = max485_ctl_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
static void __exit max485_ctl_exit(void)
{
platform_driver_unregister(&max485_ctl_driver);
}
static int __init max485_ctl_init(void)
{
return platform_driver_register(&max485_ctl_driver);
}
module_init(max485_ctl_init);
module_exit(max485_ctl_exit);
MODULE_LICENSE("Dual BSD/GPL");
应用程序如下:
//#include
#include
//#include "uart.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX485_CONTROL
//#include "uart.c"
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;
if ( tcgetattr( fd,&oldtio) != 0) {
perror("SetupSerial 1");
return -1;
}
bzero( &newtio, sizeof( newtio ) );
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch( nEvent )
{
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E':
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
printf("Baund Rate: %d\n", nSpeed);
switch( nSpeed )
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
break;
case 921600:
printf("Rate:921600\n");
cfsetispeed(&newtio, B921600);
cfsetospeed(&newtio, B921600);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if( nStop == 1 )
newtio.c_cflag &= ~CSTOPB;
else if ( nStop == 2 )
newtio.c_cflag |= CSTOPB;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
// printf("set done!\n\r");
return 0;
}
int prepare_to_send(int fd)
{
int ret;
ret = ioctl(fd, 1, 0);
if(ret<0)
{
printf("max485 set ctl to high failed!\r\n");
return -1;
}
else
{
return 0;
}
}
int prepare_to_recv(int fd)
{
int ret;
ret = ioctl(fd, 0, 0);
if(ret<0)
{
printf("max485 set ctl to low failed!\r\n");
return -1;
}
else
{
return 0;
}
}
void main(int argc, char* argv[])
{
unsigned char ucTmp;
int fd1,fd2,nset1,nset2,nread;
char buf[100];
//char buf1[1];
//char *buff = "Hello\n\r";
int i = 0;
char *max485_ctl = "/dev/max485_ctl_pin";
if(3 != argc)
{
printf("Usage: test_485 [uart port] [type]\r\n");
printf(" type: 0--recv, 1--send\r\n");
return;
}
fd1 = open(argv[1], O_RDWR);
if (fd1 == -1)
{
printf("Open %s faild\n", argv[1]);
exit(1);
}
nset1 = set_opt(fd1, 9600, 8, 'N', 1);
if (nset2 == -1)
{
printf("Set uart faild\n");
exit(1);
}
#ifdef MAX485_CONTROL
if((fd2=open(max485_ctl, O_RDWR|O_NOCTTY|O_NDELAY))<0)
{
printf("Open %s faild\n", max485_ctl);
close(fd1);
exit(1);
}
#endif
if(0 == atoi(argv[2])) //recv
{
#ifdef MAX485_CONTROL
prepare_to_recv(fd2);
#endif
while(1)
{
nread = read(fd1, buf, 100);
if (nread > 0)
{
for(i=0; i 0)
{
for(i=0; i