当前位置:网站首页>Scoring system based on 485 bus
Scoring system based on 485 bus
2022-07-06 15:19:00 【Hu Da jinshengyu】
be based on 485 Bus scoring system
Programming objectives :
Deepen the understanding through this case RS485 communication mode , The main controller of the upper computer communicates with all the lower computers .
Description of program operation effect :
adopt RS232/RS485 The converter will be multiple with 485 The MCU of the lower computer control program of the module is mounted on the bus . Use a single chip microcomputer as the upper computer , Download hex file , Another single-chip microcomputer is used as the lower computer , Download the lower computer program . After the MCU of the lower computer is powered on , The first two digits of the nixie tube display the slave number , The last three digits show the scoring results . First press the center button of the navigation button to enter the setting mode , The selected set decimal point of the nixie tube is lit ; Then by controlling the left and right directions of the navigation keys, the position selection of the nixie tube is realized , The up and down direction realizes the addition and subtraction of the numerical value on the nixie tube , Press the center button again to exit the setting mode . Then press KEY2、KEY3 Press the key to mark the completion of slave number and scoring setting , The first 1 Position and number 8 position LED The light is on ; Finally, by controlling the slave detection and multi machine scoring buttons of the master controller of the upper computer , Get the slave number and score set by the MCU , So as to realize the communication between the upper computer and the lower computer .
Program related circuit and working principle description
This case is simulated Modbus agreement , Adopt master 、 From a technical , The main controller of the upper computer can communicate with all the lower computers , It can also communicate with a designated lower computer alone . simulation Modbus Agreement , The data packets of the upper and lower computers only contain 5 Bytes , Its basic format is : Data packet head (0x5A)+ Address code ( Broadcast address / Slave address )+ Function code + Carrying data ( A byte )+ Check code bytes , The carrying data part can be expanded by multiple bytes , It can be modified according to the situation . The specific definition of data package is as follows :( Check bytes in the Protocol , This scoring system adopts accumulation and coding .)
(1) The host detects whether the slave is normal and related data packets :( The host communicates with a single slave device ):
(1) The host detects whether the slave is normal and related data packets :( The host communicates with a single slave device )
A、 The device detects packets normally :
Direction : Upper computer -----> Lower machine
Packet messages : Data packet head + Slave address + Detect function code (Fun_CheckSlave)+ Custom content (Check_Content)+ Check byte
function : Check whether the lower computer is normal . normal , The lower computer sends a response query packet ; Is not normal , Then the lower computer will not respond ; An error occurred during data transmission , The lower computer sends a response error packet , The upper computer can re detect whether the device is normal by setting multiple polling ;
B. Respond to query packets :
Direction : Lower machine —–> Upper computer
Packet messages : Data packet head + Slave address + Detect function code (Fun_CheckSlave)+ Custom content ( Received from host Check_Content)+ Check byte
C. Respond to error packets :
Direction : Lower machine —–> Upper computer
Packet messages : Data packet head + Slave address + Detect function code (Fun_CheckSlave)+ Error code (ErrorInfo)+ Check byte
(2) The host gets the data package related to the score of the slave :( The host communicates with a single slave device ):
D. Get more 、 Stand alone scoring data package :
Direction : Upper computer —–> Lower machine
Packet messages : Data packet head + Detect the normal slave address (0x00)+ Read the function code of the lower computer (Fun_ReadInfo)+ Slave address + Check byte
function : Check the normal equipment , Make a poll , Get the score of the slave machine for which the score is ready . For single machine direct communication , No polling .
E. The result returns a packet :
Direction : Lower machine —–> Upper computer
Packet messages : Data packet head + Slave address + Read the function code of the lower computer (Fun_ReadInfo)+ The score returned by the slave + Check byte ( The score is >100: Indicates that the above mentioned is not ready , Respond to error packets )
(3) This round of scoring ends with relevant data packets :
F. Reset packet :( The master communicates with all slaves )
Direction : Upper computer —–> Lower machine
Packet messages : Data packet head + Broadcast address + Reset function code (Fun_Reset)+ The score returned by the slave (0x00)+ Check byte
function : Instruct all normally connected slaves to reset , Prepare for the next round of scoring .
Implementation process :
- Through the DuPont line 51 SCM and RS232/RS485 Converter connection , Re pass USB turn RS232/RS485 Serial communication line and PC Machine connection , download hex file , And power on the MCU ;
- If you directly use a single chip microcomputer as the host , The MCU needs to download the contact software in the upper computer program instead of the lower computer software ;
- The initial phenomenon after downloading from the lower computer is : The leftmost two nixie tubes show 00 Indicates the slave number , Far right 3 A digital tube display 000 Indicates the score ;
- Press the center button of the navigation key to enter the setting mode , Press the center key again to exit the setting mode after setting the slave number and scoring , Then press the KEY1,KEY2, Flag setting is complete ;
- Control the upper computer to detect the slave computer and obtain the number of the lower computer , And get its score , The data is displayed on the main controller of the upper computer , Finally, finish scoring , Single chip microcomputer LED The light goes out .
The specific idea is shown in the figure above .
First , We can understand the specific function of this program through the serial port assistant , You can use the above A、D、F Let's get a general idea of what we need to do .A The function of is to query whether the lower computer is normal . normal , The lower computer sends a response query packet ; Is not normal , Then the lower computer will not respond ; An error occurred during data transmission , The lower computer sends a response error packet , The upper computer can re detect whether the device is normal by setting multiple polling . therefore , You only need to see the following output on the serial port assistant, which is correct :
D、F The situation is similar , You can also get the following output :
Define the functional requirements of dual computer communication through the serial port assistant .
Next, let's implement the code :
following , Give priority to the code ( It uses C++)
#include <cstdio>
#include <iostream>
#include <string>
#include <unistd.h>
#include <signal.h>
#include "serial.h"
#include <setjmp.h>
using namespace std;
typedef unsigned char uchar;
/* be based on RS485 Bus scoring system - Host program - Double machine scoring */
string format(const vector<uchar> &data); // Data is processed into strings
int check(serial &pipe, int addr); // Equipment inspection
int get_score(serial &pipe, int addr); // Get points
void reset(serial &pipe); // Slave reset
int main() {
serial pipe("/dev/ttyUSB0", B9600);
int addr, check_ret, score;
while(1){
cout<<" Enter description :\n Enter the legal slave address to query the score \n Input -2 Reset the slave \n Input -1 Exit procedure \n If the program does not work correctly , Cannot receive slave response , Please restart and try again \n Please enter the command :";
cin>>addr;
if(addr == -1) break;
if(addr == -2) {
reset(pipe);
continue;
}
check_ret = check(pipe, addr);
if(check_ret == 1){
cout<<"Equipment test normal"<<endl;
sleep(1);
if(!(score = get_score(pipe, addr)))
cout<<"Failed to get score"<<endl;
else
cout<<"score:"<<score<<endl;
}
else if(check_ret == 0){
cout<<"The address is incorrect. Please enter the address and try again"<<endl;
continue;
}
else{
cout<<"Data transfer error, please restart slave machine"<<endl;
}
//reset(pipe);
cout<<"The slave machine is reset. Enter -1 to exit"<<endl;
}
return 0;
}
/*****************************************************
Process data into strings
******************************************************/
string format(const vector<uchar> &data) {
std::string str(2 * data.size() + 1, '\x00');
for (int i = 0; i < data.size(); i++) {
sprintf(&str[i * 2], "%02X", data[i]);
}
return str;
}
/*****************************************************
Slave address detection :
Parameters :serial A serial port , Slave address
The host sends data for detection :5a + Slave address + Detect function code 08 + 13 + Check code
Return value :1( The address is correct );0( Wrong address );-1( Data error )
******************************************************/
int check(serial &pipe,int addr){
int check_code = 117 + addr, ret; // The check code is cumulative sum
vector<uchar> code = {0x5a, 0x08, 0x13};
vector<uchar> rec;
code.insert(code.begin()+1, (uchar)addr); // Insert slave address
code.push_back((uchar)check_code); // Insert the check code
//cout << format(code) << endl;
/* Write and receive response packets */
pipe.myWrite(code);
sleep(1);
rec = pipe.myRead(5);
if(format(rec) == format(code)) // Check whether the received packet is the same as the sent one , If it is the same, the slave address is correct
ret = 1;
else{
if(rec[3] == 0x6f) ret = 0;
else ret = -1;
}
return ret;
}
/*****************************************************
Get slave scores :
Parameters :serial A serial port , Slave address
The host sends for score acquisition :5a + 00 + Read function code 03 + Slave address + Check code
Return value : fraction ( The data is correct );-1( The slave is not ready );-2( Data error )
******************************************************/
int get_score(serial &pipe, int addr){
int check_code = 93 + addr, ret; // The check code is cumulative sum
vector<uchar> code = {0x5a, 0x00, 0x03};
vector<uchar> rec;
code.insert(code.begin()+3, (uchar)addr); // Insert slave address
code.push_back((uchar)check_code); // Insert the check code
//cout << format(data) << endl;
/* Write and receive response packets */
pipe.myWrite(code);
sleep(1);
rec = pipe.myRead(5);
if(rec[3] == 0x6f) ret = -1; // Check for errors
else {
ret = (int)rec[3]; // Turn to numbers
if(ret < 0 || ret > 100) ret =-2; // Check whether the number is legal
}
return ret;
}
/*****************************************************
Slave reset :
Parameters :serial A serial port , Slave score
Master sends for slave reset :5a + Broadcast address 00 + Reset function code 01 + 00 + Check byte
******************************************************/
void reset(serial &pipe){
vector<uchar> code = {0x5a, 0x00, 0x01,0x00,0x5b};
//cout <<"reset:"<< format(code) << endl;
/* Send packet */
for(int i=0;i<600;i++) {
pipe.myWrite(code);
}
return;
}
Ideas as follows :
- First , Judge whether the input lower computer number exists , Address exists and returns 1, Address error returned 0, Data error return -1.
- After judging that the lower computer number exists , Next, you need to get the score of the lower computer ( Here, only the dual computer program is implemented ). Output the obtained scores .
- Next, we need to implement , Exit and reset , Exit input -1, Reset input -2 that will do .
The contents of the header file are as follows :
#ifndef SERIAL_H
#define SERIAL_H
#include <cstring>
#include <vector>
#include <sys/termios.h>
class serial {
private:
int board = -1, epfd = -1;
public:
serial(const char *board_path, speed_t baud_rate);
~serial();
std::vector<unsigned char> myRead(size_t n) const;
void myWrite(const std::vector<unsigned char> &data) const;
};
#endif //SERIAL_H
The functions defined in the header file are as follows :
#include "serial.h"
#include <cerrno>
#include <cstdio>
#include <iostream>
#include <sys/epoll.h>
#include <sys/fcntl.h>
#include <sys/termios.h>
#include <sys/unistd.h>
#include <stdio.h>
#include <signal.h>
#define err_check(code) if ((code) < 0) {
\ printf("Error: %s\n", strerror(errno)); \ _exit(1); \ }
serial::serial(const char *board_path, speed_t baud_rate) {
/** * O_RDWR Means in read-write mode (myRead & myWrite) Open file * Reference resources :https://man7.org/linux/man-pages/man3/open.3p.html */
err_check(board = open(board_path, O_RDWR | O_NOCTTY ))
termios attrs {
};
tcgetattr(board, &attrs);
// set baud rate
err_check(cfsetispeed(&attrs, baud_rate))
err_check(cfsetospeed(&attrs, baud_rate))
attrs.c_iflag &= ~( BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF );
attrs.c_oflag &= ~( OPOST | ONLCR | OCRNL );
attrs.c_lflag &= ~( ECHO | ICANON | IEXTEN | ISIG );
attrs.c_cflag &= ~( CSIZE | PARENB );
attrs.c_cflag |= CS8;
attrs.c_cc[VMIN] = 1;
attrs.c_cc[VTIME] = 0;
// Set terminal parameters , All changes take effect immediately
err_check(tcsetattr(board, TCSANOW, &attrs))
// Reopen the device file to apply the new terminal parameters
close(board);
err_check(board = open(board_path, O_RDWR | O_NOCTTY))
// Create a new epoll example , And return a file descriptor for control
err_check(epfd = epoll_create(1))
epoll_event event {
.events = EPOLLIN | EPOLLET, // An event is triggered when the opposite end becomes readable
.data = {
.fd = board
}
};
// Add this event to epoll In the listening list
err_check(epoll_ctl(epfd, EPOLL_CTL_ADD, board, &event))
}
serial::~serial() {
(~board) && close(board);
(~epfd) && close(epfd);
}
std::vector<unsigned char> serial::myRead(size_t n) const {
size_t count = 0;
std::vector<unsigned char> buffer(n);
while (count < n)
{
epoll_event event {
};
// Wait for data from the opposite end of the serial port
epoll_wait(epfd, &event, 1, 5000); // Specify the timeout value , Avoid indefinite blocking waiting
// Reading data , Then decide whether to continue reading according to the amount of data read
count += ::read(board, &buffer[count], n);
}
//tcflush(board,TCIOFLUSH);
return buffer;
}
void serial::myWrite(const std::vector<unsigned char> &data) const {
size_t count = 0;
//tcflush(board,TCOFLUSH);
while (count < data.size()) {
// Write data to serial port
count += ::write(board, &data[count], data.size() - count);
}
}
The operation results are as follows :
( Here is just a change in the number of judgments .)
So far, the experiment , Complete .
Experience :
After several experiments , Not only honed my will , Strengthened my faith , I believe we can also gain a lot in future experiments .
ad locum , The procedure for running on multiple machines is as follows :
import binascii
import serial.tools.list_ports
# init
plist = list(serial.tools.list_ports.comports()) # Get port list
ser = serial.Serial(list(plist[0])[0], 9600, timeout=0.05) # Import pyserial modular
def read_times():
while 1:
dic = []
reading = ser.read(5) # Read serial data
if reading != b'':
a = str(hex(int(binascii.hexlify(reading), 16)))
b = a.replace("0x", "")
for index in range(0, len(b), 2):
dic.append(b[index] + b[index + 1])
return dic
devices = list(map(int, input(" Please input the lower computer of the device , In the middle to ' ' separate :").split())) # List of storage devices
print(devices)
# part 1: Verify the lower computer equipment
for device in devices:
data = [0x5A, device, 0x08, 0x13]
data.append(sum(data))
print("{}\n Slave equipment number : {:2d} The verification information is : {}\n Trying to verify ...".format('-'*50, device, data))
flag = True
for _ in range(100):
ser.write(data)
retdata = read_times()
if retdata:
print(retdata)
retdata = [int(i,16) for i in retdata]
if retdata == data:
print(" The returned verification information is : {}, The slave is normal .".format(retdata))
else:
print(" The slave transmission result is abnormal ")
flag = False
break
if flag:
print(" There is no return from the slave ")
print('-'*50)
print(' Read the scores from the machine :')
for device in devices:
data = [0x5A, 0x00, 0x03, device]
data.append(sum(data))
print("{}\n Slave equipment number : {:2d} The message sent is : {}\n Try to score ...".format('-'*50, device, data))
flag = True
for _ in range(100):
ser.write(data)
retdata = read_times()
if retdata:
print(retdata)
retdata = [int(i,16) for i in retdata]
print(retdata)
if retdata[1] == device and retdata[4] == sum(retdata[:4]):
print(" The slave score is : {}, The slave is normal .".format(retdata[3]))
elif retdata[3] == 0x6F:
print(" The slave score is greater than 100, error ")
else:
print(" The slave transmission result is abnormal ")
flag = False
break
if flag:
print(" There is no return from the slave ")
print('-'*50)
print(' Slave reset operation :')
data = [0x5A, 0x00, 0x01, 0x00, 0x5B]
ser.write(data)
print(" The slave has been reset , You can start the next round of scoring .")
After running the program, enter the number you set on your board , If multiple machines are running, the numbers of each machine are separated by spaces , Then return and wait .
边栏推荐
- Emqtt distribution cluster and node bridge construction
- Sleep quality today 81 points
- Install and run tensorflow object detection API video object recognition system of Google open source
- Investment operation steps
- Dlib detects blink times based on video stream
- CSAPP shell lab experiment report
- Global and Chinese markets of PIM analyzers 2022-2028: Research Report on technology, participants, trends, market size and share
- Leetcode simple question: check whether the numbers in the sentence are increasing
- 软件测试行业的未来趋势及规划
- MySQL数据库(三)高级数据查询语句
猜你喜欢
随机推荐
Cc36 different subsequences
Sleep quality today 81 points
Rearrange spaces between words in leetcode simple questions
遇到程序员不修改bug时怎么办?我教你
Mysql database (V) views, stored procedures and triggers
C4D quick start tutorial - Introduction to software interface
[issue 18] share a Netease go experience
STC-B学习板蜂鸣器播放音乐2.0
线程及线程池
Réponses aux devoirs du csapp 7 8 9
[Ogg III] daily operation and maintenance: clean up archive logs, register Ogg process services, and regularly back up databases
Global and Chinese market of portable and handheld TVs 2022-2028: Research Report on technology, participants, trends, market size and share
CSAPP家庭作業答案7 8 9章
Global and Chinese markets of PIM analyzers 2022-2028: Research Report on technology, participants, trends, market size and share
UCORE lab5 user process management experiment report
Lab 8 文件系统
Build your own application based on Google's open source tensorflow object detection API video object recognition system (I)
JDBC介绍
How to do agile testing in automated testing?
Want to change jobs? Do you know the seven skills you need to master in the interview software test