LINUX_RS232/RS485通信

LINUX_RS232/RS485通信

#include <stdio.h>
#include <pthread.h>
#include “RS485.h”

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <linux/serial.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <stdint.h>

/**

  • @brief: set the properties of serial port
  • @Param: fd: file descriptor
  • @Param: nSpeed: Baud Rate
  • @Param: nBits: character size
  • @Param: nEvent: parity of serial port
  • @Param: nStop: stop bits
    */

typedef enum {DISABLE = 0, ENABLE} RS485_ENABLE_t;

int Set_Uart(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio, oldtio;

memset(&oldtio, 0, sizeof(oldtio));
/* save the old serial port configuration */
if(tcgetattr(fd, &oldtio) != 0) {
	perror("set_port/tcgetattr");
	return -1;
}

memset(&newtio, 0, sizeof(newtio));
/* ignore modem control lines and enable receiver */
newtio.c_cflag = newtio.c_cflag |= CLOCAL | CREAD;// 开启读取模式和本地连接模式
newtio.c_cflag &= ~CSIZE;// 数据位掩码
/* set character size */
switch (nBits) {
	case 8:
		newtio.c_cflag |= CS8;// 8个数据位
		break;
	case 7:
		newtio.c_cflag |= CS7;
		break;
	case 6:
		newtio.c_cflag |= CS6;
		break;
	case 5:
		newtio.c_cflag |= CS5;
		break;
	default:
		newtio.c_cflag |= CS8;
		break;
}
/* set the parity */ 
switch (nEvent) {
	case 'o':
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'e':
	case 'E':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'n':
	case 'N':
		newtio.c_cflag &= ~PARENB;// 无奇偶校验
		break;
	default:
		newtio.c_cflag &= ~PARENB;
		break;
}
/* set the stop bits */
switch (nStop) {
	case 1:
		newtio.c_cflag &= ~CSTOPB;// 1个停止位
		break;
	case 2:
		newtio.c_cflag |= CSTOPB;
		break;
	default:
		newtio.c_cflag &= ~CSTOPB;
		break;
}
/* set output and input baud rate */
switch (nSpeed) {
	case 0:
		cfsetospeed(&newtio, B0);
		cfsetispeed(&newtio, B0);
		break;
	case 50:
		cfsetospeed(&newtio, B50);
		cfsetispeed(&newtio, B50);
		break;
	case 75:
		cfsetospeed(&newtio, B75);
		cfsetispeed(&newtio, B75);
		break;
	case 110:
		cfsetospeed(&newtio, B110);
		cfsetispeed(&newtio, B110);
		break;
	case 134:
		cfsetospeed(&newtio, B134);
		cfsetispeed(&newtio, B134);
		break;
	case 150:
		cfsetospeed(&newtio, B150);
		cfsetispeed(&newtio, B150);
		break;
	case 200:
		cfsetospeed(&newtio, B200);
		cfsetispeed(&newtio, B200);
		break;
	case 300:
		cfsetospeed(&newtio, B300);
		cfsetispeed(&newtio, B300);
		break;
	case 600:
		cfsetospeed(&newtio, B600);
		cfsetispeed(&newtio, B600);
		break;
	case 1200:
		cfsetospeed(&newtio, B1200);
		cfsetispeed(&newtio, B1200);
		break;
	case 1800:
		cfsetospeed(&newtio, B1800);
		cfsetispeed(&newtio, B1800);
		break;
	case 2400:
		cfsetospeed(&newtio, B2400);
		cfsetispeed(&newtio, B2400);
		break;
	case 4800:
		cfsetospeed(&newtio, B4800);
		cfsetispeed(&newtio, B4800);
		break;
	case 9600:
		cfsetospeed(&newtio, B9600);
		cfsetispeed(&newtio, B9600);
		break;
	case 19200:
		cfsetospeed(&newtio, B19200);
		cfsetispeed(&newtio, B19200);
		break;
	case 38400:
		cfsetospeed(&newtio, B38400);
		cfsetispeed(&newtio, B38400);
		break;
	case 57600:
		cfsetospeed(&newtio, B57600);
		cfsetispeed(&newtio, B57600);
		break;
	case 115200:
		cfsetospeed(&newtio, B115200);
		cfsetispeed(&newtio, B115200);
		break;
	case 230400:
		cfsetospeed(&newtio, B230400);
		cfsetispeed(&newtio, B230400);
		break;
	default:
		cfsetospeed(&newtio, B115200);
		cfsetispeed(&newtio, B115200);
		break;
}
/* set timeout in deciseconds for non-canonical read */
newtio.c_cc[VTIME] = 0;
/* set minimum number of characters for non-canonical read */
newtio.c_cc[VMIN] = 0;
/* flushes data received but not read */
tcflush(fd, TCIFLUSH);
/* set the parameters associated with the terminal from
	the termios structure and the change occurs immediately */
if((tcsetattr(fd, TCSANOW, &newtio))!=0)
{
	perror("set_port/tcsetattr");
	return -1;
}

return 0;

}

/**

  • @brief: open serial port
  • @Param: dir: serial device path
    */
    int Open_Uart(char *dir)
    {
    int fd ;
    fd = open(dir, O_RDWR);
    if(fd < 0) {
    perror(“open_port”);
    }
    return fd;

}

/*******************************************************************
*名称: UART_Close
*功能: 关闭串口并返回串口设备文件描述
*入口参数: fd 文件描述符
*出口参数:void
*******************************************************************/

void Close_Port(int fd)
{
close(fd);
}

/*******************************************************************

  • 名称: UART0_Recv

  • 功能: 接收串口数据

  • 入口参数: fd 文件描述符

  •               rcv_buf    接收串口中数据存入rcv_buf缓冲区中  
    
  •               data_len   一帧数据的长度  
    
  • 出口参数: 正确返回为1,错误返回为0
    *******************************************************************/
    int Uart_Recv(int fd, char *rcv_buf,int data_len)
    {
    int len,fs_sel;

    len = read(fd,rcv_buf,data_len);
    return len;
    }

/********************************************************************

  • 名称: UART0_Send

  • 功能: 发送数据

  • 入口参数: fd 文件描述符

  •               send_buf     存放串口发送数据  
    
  •               data_len     一帧数据的个数  
    
  • 出口参数: 正确返回为1,错误返回为0
    *******************************************************************/
    int Uart_Send(int fd, char *send_buf,int data_len)
    {
    int len = 0;

    len = write(fd,send_buf,data_len);
    if (len == data_len )
    {
    //printf(“send data is %s\n”,send_buf);
    return len;
    }
    else
    {

      tcflush(fd,TCOFLUSH);    
      return 0;    
    

    }

}

uint16_t GetCRC16(uint8_t *buff,uint8_t len)
{
uint8_t i=0;
uint8_t j=0;

uint16_t wtmp=0xffff;
uint16_t out=0;

for(i=0; i<len; i++) 
{
    wtmp = wtmp ^ buff[i];
    
    for(j=0; j<8; j++) 
    {
        if((wtmp & 0x0001) == 0)
        {
            wtmp=wtmp>>1;  
           out=wtmp;
        } 
        else
        {
            wtmp=wtmp>>1;
            wtmp ^= 0xa001;   
            out=wtmp;
        }
    }
    
    
}  
return out;

}

//封装请求码
int buildRequest(int sid,int func, int addr, int nb, uint8_t *req)
{
//这里控制的就是外部定义的req数组。下面按RTU的数据格式填充
req[0] = sid; //从机地址
req[1] = func; //功能码
req[2] = (uint8_t)(addr >> 8); //理论上,有要分大小端存储的数,都可以拆分开。
req[3] = (uint8_t)(addr & 0xff);

if (func == 3)
{
    req[4] = (uint8_t)(nb >> 8); //当功能码是03时完成的任务
    req[5] = (uint8_t)(nb & 0xff);
}
uint16_t crc = GetCRC16(req, 6); //这里是一个CRC校验,形成两字节的校验位
req[6] = (uint8_t)(crc & 0xff);
req[7] = (uint8_t)(crc >> 8);          //上返回的unsigned short类型,转为uint8_t

return 8;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mason辘轳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值