提高至 32 組裝置,僅並定義必要的電子特性,並沒有定義傳輸介面,
所以你會看到有人用普通的單芯線直接連接,或是RJ45/DMX之類的接頭
來做485的傳輸,亦可以混用不同介面在同一個RS-485網路中。
RS485與RS232最大的不同在於它是半雙工,也就是同一時間只能傳送或是接收,RS-485網路中只有同時間有1個以上裝置在發送資料就會出現干擾,所以還會透過Modbus之類的協定來搭配實際的應用。
RS-485是依靠A/B二端的電壓差做為判定1或是0 ,只要A/B之間壓差大於0.2V特,
即判定訊號為1,否則為0 ,RS-485可以接受的電壓範圍比較大,在-7~+12V。
一般的MCU若需要加入RS-485傳輸,則可以透過UART轉RS485 Chip,例如MX232/SP3485等等,透過控制DE/RE腳來控制目前為發送或接收狀態。
程式碼,在AR9331中測試過,DE為PIN 7 ,RE為PIN 13
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <string.h> #include <time.h> #include <errno.h> #include <termios.h> #define GPIO_ADDR 0x18040000 // base address #define GPIO_BLOCK 48 // memory block size char *portname = "/dev/ttyATH0"; volatile unsigned long *gpioAddress; int set_interface_attribs (int fd, int speed, int parity) { struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) { printf("error %d from tcgetattr", errno); return -1; } cfsetospeed (&tty, speed); cfsetispeed (&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars // disable IGNBRK for mismatched speed tests; otherwise receive break // as \000 chars tty.c_iflag &= ~IGNBRK; // disable break processing tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= parity; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr (fd, TCSANOW, &tty) != 0) { printf ("error %d from tcsetattr", errno); return -1; } return 0; } void set_blocking (int fd, int should_block) { struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) { printf ("error %d from tggetattr", errno); return; } tty.c_cc[VMIN] = should_block ? 1 : 0; tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout if (tcsetattr (fd, TCSANOW, &tty) != 0) printf ("error %d setting term attributes", errno); } int gpioRead(int gpio) { unsigned long value = *(gpioAddress + 1); //printf("value =%d\n",value); //printf("(1<<gpio) =%d",(1 << gpio)); return (value & (1 << gpio)); } // "1" (output) or "0" (input) void gpioDirection(int gpio, int direction) { unsigned long value = *(gpioAddress + 0); // obtain current settings if (direction == 1) { value |= (1 << gpio); // set bit to 1 } else { value &= ~(1 << gpio); // clear bit } *(gpioAddress + 0) = value; } void gpioSet(int gpio, int data) { unsigned long value = *(gpioAddress + 2); // obtain current settings if (data == 1) { value |= (1 << gpio); // set bit to 1 } else { value &= ~(1 << gpio); // clear bit } *(gpioAddress + 2) = value; } /*void gpioSet(int gpio, int value) { if (value == 0) { *(gpioAddress + 4) = (1 << gpio); } else { *(gpioAddress + 3) = (1 << gpio); } }*/ int gpioSetup() { int m_mfd; if ((m_mfd = open("/dev/mem", O_RDWR)) < 0) { return -1; } gpioAddress = (unsigned long*)mmap(NULL, GPIO_BLOCK, PROT_READ|PROT_WRITE, MAP_SHARED, m_mfd, GPIO_ADDR); close(m_mfd); if (gpioAddress == MAP_FAILED) { return -2; } return 0; } int main(int argc, char **argv) { int rs485_de=7; int rs485_re=13; gpioSetup(); gpioDirection(rs485_de,1);//set pin output gpioDirection(rs485_re,1);//set pin output int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { printf ("error %d opening %s: %s", errno, portname, strerror (errno)); return -1; } set_interface_attribs (fd, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity) set_blocking (fd, 0); // set no blocking //get Model Name int cmd_len=7; char w_buff[8]; w_buff[0]=0x01; w_buff[1]=0x02; w_buff[2]=0x03; w_buff[3]=0x04; w_buff[4]=0x05; w_buff[5]=0x06; w_buff[6]=0x07; w_buff[7]='\0'; for (int t=0;t<20;t++) { gpioSet(rs485_de,1); //Set RS485 to Send Mode gpioSet(rs485_re,1); usleep (100); write (fd, w_buff, cmd_len); usleep (cmd_len*100); // sleep enough to transmit the command date gpioSet(rs485_de,0); // Set RS485 to Receive Mode gpioSet(rs485_re,0); usleep (10 * 1000); //wait a little time before read data char buf [100]; int n = read (fd, buf, sizeof buf); // read up to 100 characters if ready to read printf("rec:%d bytes\n",n); for (int i=0;i<n;i++) { printf("%d\t",buf[i]); } printf("\n"); } }