Files
split-flap-controller/software/firmware_module/module_rev0/src/rs458.c
2025-01-10 15:00:00 +01:00

95 lines
2.6 KiB
C

/* Copyright (C) 2025 Dennis Gunia - All Rights Reserved
* You may use, distribute and modify this code under the
* terms of the AGPL-3.0 license.
*
* https://www.dennisgunia.de
* https://github.com/dennis9819/splitflap_v1
*/
#include "rs485.h"
void rs485_init() {
// init I/O
DDRD &= ~(1 << PD0); // BUS_DIR & TX is OUTPUT
DDRD |= (1 << PD2) | (1 << PD1); // BUS_DIR & TX is OUTPUT
PORTD &= 0x07; // clear PD0-PD4
// init UART
UBRRH = (BAUDRATE >> 8);
UBRRL = BAUDRATE; // set baud rate
UCSRB |= (1 << TXEN) | (1 << RXEN); // enable receiver and transmitter
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // 8bit data format
}
void dbg(char data) {
while (!(UCSRA & (1 << UDRE)))
;
UDR = data;
}
void rs485_send_c(char data) {
PORTD |= (1 << PD2); // set transciever to transmitt
while (!(UCSRA & (1 << UDRE)))
; // wait until buffer is empty
UCSRA = (1 << TXC); // clear transmit Complete bit
UDR = data;
while (!(UCSRA & (1 << TXC)))
; // wait until transmitt complete
PORTD &= ~(1 << PD2); // set transciever to transmitt
}
void rs485_send_str(char* data) {
for (unsigned int i = 0; i < sizeof(data); i++) {
rs485_send_c(data[i]);
}
}
char rs485_recv_c() {
while (!(UCSRA & (1 << RXC)))
;
; // wait while data is being received
return UDR;
}
// SFBUS Functions
uint8_t sfbus_recv_frame(uint16_t address, char* payload) {
while (rs485_recv_c() != '+') {} // Wwait for start byte
uint8_t frm_version = rs485_recv_c();
if (frm_version != 0) return 0;
uint8_t frm_length = rs485_recv_c();
uint8_t frm_addrL = rs485_recv_c();
uint8_t frm_addrH = rs485_recv_c();
uint16_t frm_addr = frm_addrL | (frm_addrH << 8);
if (frm_addr != address) return 0;
char* _payload = payload;
for (uint8_t i = 0; i < (frm_length - 3); i++) {
*_payload = rs485_recv_c();
_payload++;
}
if (rs485_recv_c() != '$') return -1;
return frm_length;
}
void sfbus_send_frame(uint16_t address, char* payload, uint8_t length) {
char framelen = length;
rs485_send_c(SFBUS_SOF_BYTE); // send startbyte 3 times
rs485_send_c(0); // send protocol version
rs485_send_c(framelen + 3); // send lentgh of remaining frame
rs485_send_c(address & 0xFF); // target address
rs485_send_c((address >> 8) & 0xFF);
while (framelen > 0) { // send payload
rs485_send_c(*payload);
payload++;
framelen--;
}
rs485_send_c(SFBUS_EOF_BYTE); // send end of frame byte
}