Needed fuctions for main board:
We need to know what stuff is going in the bus and what 0’s and 1’s go to what message. In Modbus that is defined with time -> we need a timer to check when there is a cap long enought implying that message has ended.
// confs timer 0 to work as intended // (fires interrupt when Modbus message gap is reached meaning that by Modbus standard there can/will be a new message after that) void timer0_init(); // same as timer 0 but different clock rate because sensors need to be read in different rate than other stuff needs to work void timer1_init();
Initialising configurations are needed, so the processor knows what stuff is connected to it, how and how to work with them. Initialising parameters can be found from manuals.
// confs needed pins to work with RS485-chip void rs485_init(); // confs processors UART ( ==serial port ) to work with the bus void uart_init();
Start settings needed:
// reads serial number and Modbus address from eepron for the device/Mursu // in beginning always the same numbers but they can be overwritten with Python script and then those numbers will remain in memory void configure();
Chip and processor need send and receive modes as they can’t do them both in same time. So, one either talks or listens, just like people (should) do…
// puts RS-485 chip into send mode void rs485_mode_send(); // puts RS-485 chip and processor into receive mode (both are listening the Modbus-bus...) void rs485_mode_receive();
Sending in practise:
Device just pushes bytes out without caring what happens to them. So, it is just shouting stuff out.
// processor sends one byte out void uart_transmit(uint8_t byte);
Receiving in practise:
Line has bytes going through, if processor is listening, the UART sub system then catches these bytes and informs main program that it has received data. Our system's received buffer is one byte, so they need to be stored safely somewhere else immediately after receiving or the message is just destroyed. So, sub system informs that it has received a byte, tells processors which stops everything and executes code that saves the byte into main memory. This keeps on going untill the whole message is received. Modbus line goes totally silent after the message for some time. This also means that is you have huge lag in your system, it will think single bytes as their own whole messages. When the whole message is received, processor starts to decode the message and then acts accordinly: if there is command, it excutes that and sends response to the command or if there is data which is response to it's inquiry for the data, it deals with the data as wanted by the programmer. In our case
Interrupts are important as when something is received, processor is notified about that, and then processor runs an interrupt service request handler ( ==ISR ). This is because interrupt immediatly then stores the received byte and flags that message is being received. So, something important is happening that needs instant attention. Therefore word interrupt as it interrupts everything that is going on with something more important.
// interrupt: // USART0_RX_vect -name is from datasheet: // USART0_RX_vect usart0-device receives a byte (usart means that it could also work in syncronous mode, // meaning explicit clock signal that tells when bit changes, so not sniffing when there is a change) ISR(USART0_RX_vect) // how many bytes is received, needed because in Modbus standard one can send messages with different lenghts. // So, making sure that we don't read pass the message in buffer (==no old data) uint8_t uart_bytes_received(); // clears UART's received buffer, in reality it just changes the point where we write stuff, coming back to the start point point of the buffer. void uart_clear(); // computes the checksum which is used in Modbus messages (error detection) uint16_t compute_crc( uint8_t byte, uint16_t crc); // in Modbus standard device must send out error response when something goes wrong (there is a fault in master's message or an error happening during handling the message) void modbus_error_response( uint8_t func, uint8_t error ); // read stuff from register (stuff gets there by some other code...) void modbus_read_register( uint16_t start, uint16_t stop ); // handles Modbus write register function, meaning master wants to write something into the register void modbus_write_register( uint16_t address, uint16_t data ); // parses and handless received messages from master void modbus_handle_message();