4412 RS485

一、485硬件原理

  • 差分对传输数据的原理
    • IO数据的传输→差分对
  • rs232传输的距离在15米以下,RS485传输距离是几十米到1000米以上
  • 为什么485可以传输这么远
    • 差分对的机制可以降低电磁场的干扰
    • 衰减
  • 485传输距离和传输线有关系
    •  注意:双绞线和屏蔽线

二、485原理图

嵌入式上一般使用串口转485

分析芯片datasheet

串口的信号转化为485则:

  • D→(A,B),DE高电平,RE高电平

485信号转化为串口信号则:

  • (A,B),DE低电平,RD低电平

三、驱动

485驱动=串口驱动+GPIO的字符驱动

BUF_XURTS1高电平发送,低电平接收

串口驱动是drivers/char/max485_ctl.c   

  • 485驱动=串口驱动+GPIO的字符驱动
  • BUF_XURTS1高电平发送,低电平接收
  • (GPIO是GPA0_7,串口设备节点是ttySAC1)


驱动中只需要操作GPIO

  • 设备节点/dev/max485_ctl


应用中,控制GPIO和串口=类似led+串口的操作

  • ioctl是参数是1,则输出高电平,发送
  • ioctl是参数是0,则输出低电平,接收
  • 串口的节点/dev/ttySAC1


运行程序

  • 发送./test_485 /dev/ttySAC1 1
  • 接收./test_485 /dev/ttySAC1 0

测试程序发送的信息:iTOP-4412: max485 test app(times:%d)

 测试程序:

//#include <stdio.h>
#include <unistd.h>
//#include "uart.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>

#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
", 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
");
        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!

");
    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!
");

        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!
");
        
        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

";

    int i = 0;

    char *max485_ctl = "/dev/max485_ctl_pin";

    if(3 != argc)
        {
        printf("Usage:    test_485 [uart port] [type]
");
        printf("        type: 0--recv, 1--send
");
            
        return;
    }

    fd1 = open(argv[1], O_RDWR);
    if (fd1 == -1)
    {
        printf("Open %s faild
", argv[1]);
        exit(1);
    }

    nset1 = set_opt(fd1, 9600, 8, 'N', 1);
    if (nset2 == -1)
    {
        printf("Set uart faild
");
        exit(1);
    }

#ifdef MAX485_CONTROL
    if((fd2=open(max485_ctl, O_RDWR|O_NOCTTY|O_NDELAY))<0)
    {
        printf("Open %s faild
", 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<nread; i++)
                {
                    printf("%c", buf[i]);
            
                    if(buf[i] == 'q')
                        //break;
                        goto exit;
                }
            }
            //if(nread)
            //{
            //    printf("
");
            //}
            sleep(1);
        }
    }
    else    //send 
    {
#ifdef MAX485_CONTROL
        prepare_to_send(fd2);
#endif
        while(1)
        {
            printf("Send data, time:%d
", i);
            sprintf(buf, "iTOP-4412: max485 test app(times:%d)
", i++);
            //nread = write(fd1, "iTOP-4412: max485 test app
", strlen("iTOP-4412: max485 test app
"));
            nread = write(fd1, buf, strlen(buf));
            sleep(1);
#if 0
            nread = read(fd1, buf, 100);
                        if (nread > 0)
                        {
                                for(i=0; i<nread; i++)
                                {
                                        printf("%c", buf[i]);

                                        if(buf[i] == 'q')
                                                //break;
                                                goto exit;
                                }
                        }
                        if(nread)
                        {
                                printf("
");
                        }
#endif
        }
    }
exit:
    close(fd1);

        return;
}
测试程序
原文地址:https://www.cnblogs.com/ch122633/p/9505219.html