设备驱动开发实验教程(12)_RS485总线驱动

        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;

 

设备驱动开发实验教程(12)_RS485总线驱动_第1张图片

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

 

你可能感兴趣的:(嵌入式Linux,驱动实验)