从现在开始分析BACnet协议栈了,版本号是bacnet-stack-0.7.1。
目录是bacnet-stack-0.7.1\ports\linux\rs485.crs485.c文件主要要解决在物理层发送和接收数据的作用。
不同的开发板需要移植该文件。
#include <errno.h>#include <stddef.h>#include <stdint.h>#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h>/* Linux includes */#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <unistd.h>#include <sched.h>/* Local includes */#include "mstp.h"#include "rs485.h"#include "fifo.h"#include <sys/select.h>#include <sys/time.h>/* Posix serial programming reference:/~mike/serial/serial.html *//* Use ionice wrapper to improve serial performance:$ sudo ionice -c 1 -n 0 ./bin/bacserv 12345*//* handle returned from open() */static int RS485_Handle = -1;/* baudrate settings are defined in <asm/termbits.h>, which isincluded by <termios.h> */static unsigned int RS485_Baud = B38400;//波特率选择38400 bps/* serial port name, /dev/ttyS0,/dev/ttyUSB0 for USB->RS485 from B&B Electronics USOPTL4 */static char *RS485_Port_Name = "/dev/ttyUSB0"; /*系统默认是通过USB转485的,根据需要设置,若你的开发板用485接口,则用static char *RS485_Port_Name = "/dev/ttyS0";代替*//* some terminal I/O have RS-485 specific functionality */#ifndef RS485MOD#define RS485MOD 0#endif/* serial I/O settings */static struct termios RS485_oldtio;/* Ring buffer for incoming bytes, in order to speed up the receiving. */ static FIFO_BUFFER Rx_FIFO;/* buffer size needs to be a power of 2 */static uint8_t Rx_Buffer[4096];#define _POSIX_SOURCE 1 /* POSIX compliant source *//********************************************************************** DESCRIPTION: Configures the interface name* RETURN: none* ALGORITHM: none* NOTES: none*********************************************************************/void RS485_Set_Interface(char *ifname){/* note: expects a constant char, or char from the heap */if (ifname) {RS485_Port_Name = ifname;}}/********************************************************************** DESCRIPTION: Returns the interface name* RETURN: none* ALGORITHM: none* NOTES: none*********************************************************************/const char *RS485_Interface(void){return RS485_Port_Name;}/***************************************************************************** DESCRIPTION: Returns the baud rate that we are currently running at * RETURN: none* ALGORITHM: none* NOTES: none*****************************************************************************/ uint32_t RS485_Get_Baud_Rate(void){uint32_t baud = 0;switch (RS485_Baud) {case B0:baud = 0;break;case B50:baud = 50;break;case B75:baud = 75;break;case B110:baud = 110;break;case B134:baud = 134;break;case B150:baud = 150;break;case B200:baud = 200;break;case B300:baud = 300;break;case B600:baud = 600;break;case B1200:baud = 1200;break;case B1800:baud = 1800;break;case B2400:baud = 2400;break;case B4800:baud = 4800;break;case B9600:baud = 9600;break;case B19200:baud = 19200;break;case B38400:baud = 38400;break;case B57600:baud = 57600;break;case B115200:baud = 115200;break;case B230400:baud = 230400;break;default:baud = 9600;}return baud;}/**************************************************************************** * DESCRIPTION: Sets the baud rate for the chip USART* RETURN: none* ALGORITHM: none* NOTES: none*****************************************************************************/ bool RS485_Set_Baud_Rate(uint32_t baud){bool valid = true;switch (baud) {case 0:RS485_Baud = B0;break;case 50:RS485_Baud = B50;break;case 75:RS485_Baud = B75;break;case 110:RS485_Baud = B110;break;case 134:RS485_Baud = B134;break;case 150:RS485_Baud = B150;break;case 200:RS485_Baud = B200; break;case 300:RS485_Baud = B300;break;case 600:RS485_Baud = B600;break;case 1200:RS485_Baud = B1200;break;case 1800:RS485_Baud = B1800;break;case 2400:RS485_Baud = B2400;break;case 4800:RS485_Baud = B4800;break;case 9600:RS485_Baud = B9600;break;case 19200:RS485_Baud = B19200;break;case 38400:RS485_Baud = B38400;break;case 57600:RS485_Baud = B57600;break;case 115200:RS485_Baud = B115200;break;case 230400:RS485_Baud = B230400;break;default:valid = false;break;}if (valid) {/* FIXME: store the baud rate */}return valid;}/***************************************************************************** DESCRIPTION: Transmit a frame on the wire* RETURN: none* ALGORITHM: none* NOTES: none*****************************************************************************/void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */uint8_t * buffer, /* frame to send (up to 501 bytes of data) */uint16_t nbytes){ /* number of bytes of data (up to 501) */uint32_t turnaround_time = Tturnaround * 1000;uint32_t baud = RS485_Get_Baud_Rate();ssize_t written = 0;int greska;/* sleeping for turnaround time is necessary to give other devicestime to change from sending to receiving state. */usleep(turnaround_time / baud); //至少要等待Tturnaround时间才启动RS485缓冲器发送/*On success, the number of bytes written are returned (zero indicatesnothing was written). On error, -1 is returned, and errno is setappropriately. If count is zero and the file descriptor refers to aregular file, 0 will be returned without causing any other effect. Fora special file, the results are not portable.*/written = write(RS485_Handle, buffer, nbytes); //RS485_Handle初始时是为-1,当发出open操作时应该是个正整数,而write函数的原型是(fd,buf,n)greska = errno;if (written <= 0) {printf("write error: %s\n", strerror(greska));} else {/* wait until all output has been transmitted. */tcdrain(RS485_Handle); //Linux中的传输等待函数}/* tcdrain(RS485_Handle); *//* per MSTP spec, sort of */if (mstp_port) {mstp_port->SilenceTimerReset();}return;}/***************************************************************************** DESCRIPTION: Get a byte of receive data* RETURN: none* ALGORITHM: none* NOTES: none*****************************************************************************/RS485_Check_UART_Data函数分别检查ReceiveError、DataAvailable。