fix protocol V2 bug
This commit is contained in:
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
uint16_t address = 0x0000;
|
uint16_t address = 0x0000;
|
||||||
uint16_t calib_offset = 0x0000;
|
uint16_t calib_offset = 0x0000;
|
||||||
|
char *payload;
|
||||||
|
|
||||||
|
|
||||||
void eeprom_write_c(uint16_t address, uint8_t data)
|
void eeprom_write_c(uint16_t address, uint8_t data)
|
||||||
{
|
{
|
||||||
@@ -60,11 +62,10 @@ void initialSetup()
|
|||||||
|
|
||||||
void readCommand()
|
void readCommand()
|
||||||
{
|
{
|
||||||
char *payload = malloc(PROTO_MAXPKGLEN);
|
int payload_len = parse_buffer(address, payload);
|
||||||
uint8_t payload_len = sfbus_recv_frame_v2(address, payload);
|
if (payload_len > 0) // if positive, package is valid
|
||||||
payload += 2; // skip address bytes
|
|
||||||
if (payload_len > 0)
|
|
||||||
{
|
{
|
||||||
|
payload += 2; // skip address bytes
|
||||||
// read command byte
|
// read command byte
|
||||||
uint8_t opcode = *payload;
|
uint8_t opcode = *payload;
|
||||||
// parse commands
|
// parse commands
|
||||||
@@ -166,14 +167,16 @@ void readCommand()
|
|||||||
_delay_ms(2);
|
_delay_ms(2);
|
||||||
sfbus_send_frame_v2(0xFFFF, &msg, 1);
|
sfbus_send_frame_v2(0xFFFF, &msg, 1);
|
||||||
}
|
}
|
||||||
|
//memset(payload, 0x00, PROTO_MAXPKGLEN); // clear buffer
|
||||||
}
|
}
|
||||||
free(payload);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
payload = malloc(PROTO_MAXPKGLEN);
|
||||||
initialSetup();
|
initialSetup();
|
||||||
rs485_init();
|
rs485_init();
|
||||||
|
setup_async_rx();
|
||||||
mctrl_init(calib_offset);
|
mctrl_init(calib_offset);
|
||||||
|
|
||||||
while (1 == 1)
|
while (1 == 1)
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ int rs485_recv_c_rxout(uint8_t timeout, char *data)
|
|||||||
|
|
||||||
// SFBUS Functions
|
// SFBUS Functions
|
||||||
// receive paket with crc checking and timeout
|
// receive paket with crc checking and timeout
|
||||||
uint8_t sfbus_recv_frame_v2(uint16_t address, char *payload)
|
int sfbus_recv_frame_v2(uint16_t address, char *payload)
|
||||||
{
|
{
|
||||||
const uint8_t RX_TIMEOUT = 2;
|
const uint8_t RX_TIMEOUT = 4;
|
||||||
while (rs485_recv_c() != SFBUS_SOF_BYTE)
|
while (rs485_recv_c() != SFBUS_SOF_BYTE)
|
||||||
{
|
{
|
||||||
} // Wait for start byte
|
} // Wait for start byte
|
||||||
@@ -97,7 +97,7 @@ uint8_t sfbus_recv_frame_v2(uint16_t address, char *payload)
|
|||||||
return (checksum == checksum_calc && address == recv_addr) ? frm_length : 0;
|
return (checksum == checksum_calc && address == recv_addr) ? frm_length : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send paket with crc
|
// send paket with crc
|
||||||
void sfbus_send_frame_v2(uint16_t address, char *payload, uint8_t length)
|
void sfbus_send_frame_v2(uint16_t address, char *payload, uint8_t length)
|
||||||
{
|
{
|
||||||
uint8_t framelen = length;
|
uint8_t framelen = length;
|
||||||
@@ -146,4 +146,99 @@ uint16_t calc_CRC16(char *buffer, uint8_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return crc16;
|
return crc16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// async receive function
|
||||||
|
uint8_t rx_buffer_ix_ptr = 0; // receive buffer index pointer
|
||||||
|
uint8_t rx_buffer_ix_rem = 255; // receive buffer remaining
|
||||||
|
uint8_t rx_buffer_rx_done = 0; // receive buffer complete flag (must be reset before next pkg can be received)
|
||||||
|
uint8_t *rx_buffer_temp; // receive buffer
|
||||||
|
|
||||||
|
// setup async receive function
|
||||||
|
void setup_async_rx()
|
||||||
|
{
|
||||||
|
rx_buffer_temp = malloc(PROTO_MAXPKGLEN); // reserve memory for rx buffer
|
||||||
|
UCSRB |= (1 << RXCIE); //enable rx interrupt
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(USART_RXC_vect)
|
||||||
|
{
|
||||||
|
if (rx_buffer_rx_done == 0) // only receive when last buffer was processed
|
||||||
|
{
|
||||||
|
uint8_t rx_byte = UDR; // read rx buffer
|
||||||
|
if (timer_ticks > 6) // too long since last byte
|
||||||
|
{
|
||||||
|
rx_buffer_ix_ptr = 0; // reset pointer and start new transaction
|
||||||
|
rx_buffer_ix_rem = 255; // reset remaining bytes to default
|
||||||
|
}
|
||||||
|
if (rx_buffer_ix_ptr == 0)
|
||||||
|
{
|
||||||
|
// wait for startbyte
|
||||||
|
if (rx_byte == SFBUS_SOF_BYTE)
|
||||||
|
{
|
||||||
|
*(rx_buffer_temp) = rx_byte;
|
||||||
|
rx_buffer_ix_ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rx_buffer_ix_ptr > 0 && rx_buffer_ix_ptr < (PROTO_MAXPKGLEN - 1)) // when package is already started
|
||||||
|
{ // and buffer is smaller than max length
|
||||||
|
*(rx_buffer_temp + rx_buffer_ix_ptr) = rx_byte; // receive single byte
|
||||||
|
rx_buffer_ix_rem--;
|
||||||
|
rx_buffer_ix_ptr++;
|
||||||
|
if (rx_buffer_ix_ptr == 3) // third byte is always frame length
|
||||||
|
{
|
||||||
|
rx_buffer_ix_rem = rx_byte;
|
||||||
|
}
|
||||||
|
if (rx_buffer_ix_rem == 0) // when last byte is received
|
||||||
|
{
|
||||||
|
rx_buffer_ix_ptr--;
|
||||||
|
rx_buffer_rx_done = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timer_ticks = 0; // reset timer ticks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_buffer(uint16_t address, char *payload)
|
||||||
|
{
|
||||||
|
if (rx_buffer_rx_done > 0)
|
||||||
|
{
|
||||||
|
uint8_t frm_length = *(rx_buffer_temp + 2);
|
||||||
|
// check protocol version
|
||||||
|
if (*(rx_buffer_temp + 1) != 0x01)
|
||||||
|
{
|
||||||
|
clear_buffer();
|
||||||
|
return -1; // abort on incompatible version
|
||||||
|
}
|
||||||
|
if (frm_length < PROTO_MAXPKGLEN) // prevent buffer overflow
|
||||||
|
{
|
||||||
|
memcpy(payload, rx_buffer_temp + 3, frm_length); // copy buffer
|
||||||
|
// if version matches, read address and checksum
|
||||||
|
uint16_t recv_addr = (*(rx_buffer_temp + 3) & 0xFF) | ((*(rx_buffer_temp + 4) & 0xFF) << SHIFT_1B);
|
||||||
|
uint16_t checksum = (*(rx_buffer_temp + (rx_buffer_ix_ptr - 1)) & 0xFF) |
|
||||||
|
((*(rx_buffer_temp + (rx_buffer_ix_ptr)) & 0xFF) << SHIFT_1B);
|
||||||
|
// calculate checksum of received payload
|
||||||
|
uint16_t checksum_calc = calc_CRC16((char *)rx_buffer_temp + 5, rx_buffer_ix_ptr - 6);
|
||||||
|
|
||||||
|
//mctrl_set(address == recv_addr ? 20 : recv_addr + 1, 0);
|
||||||
|
clear_buffer();
|
||||||
|
// return length on valid address and crc, return 0 to ignore
|
||||||
|
return (checksum == checksum_calc && address == recv_addr) ? frm_length : 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// invalid package
|
||||||
|
clear_buffer();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_buffer()
|
||||||
|
{
|
||||||
|
rx_buffer_ix_ptr = 0; // reset pointer and start new transaction
|
||||||
|
rx_buffer_ix_rem = PROTO_MAXPKGLEN; // reset remaining bytes to default
|
||||||
|
rx_buffer_rx_done = 0; // reset done flag
|
||||||
|
//memset(rx_buffer_temp, 0x00, PROTO_MAXPKGLEN); // clear buffer
|
||||||
}
|
}
|
||||||
@@ -26,10 +26,13 @@ extern "C"
|
|||||||
char rs485_recv_c(void);
|
char rs485_recv_c(void);
|
||||||
int rs485_recv_c_rxout(uint8_t timeout, char *data);
|
int rs485_recv_c_rxout(uint8_t timeout, char *data);
|
||||||
|
|
||||||
uint8_t sfbus_recv_frame_v2(uint16_t address, char *payload);
|
int sfbus_recv_frame_v2(uint16_t address, char *payload);
|
||||||
void sfbus_send_frame_v2(uint16_t address, char *payload, uint8_t length);
|
void sfbus_send_frame_v2(uint16_t address, char *payload, uint8_t length);
|
||||||
uint16_t calc_CRC16(char *buffer, uint8_t len);
|
uint16_t calc_CRC16(char *buffer, uint8_t len);
|
||||||
|
|
||||||
|
void setup_async_rx();
|
||||||
|
int parse_buffer(uint16_t address, char *payload);
|
||||||
|
void clear_buffer();
|
||||||
// auxilary var for uart timeout
|
// auxilary var for uart timeout
|
||||||
extern uint16_t timer_ticks;
|
extern uint16_t timer_ticks;
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ int sfbus_ping(int fd, u_int16_t address)
|
|||||||
char *buffer = malloc(64); // allocate rx buffer
|
char *buffer = malloc(64); // allocate rx buffer
|
||||||
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
|
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
|
||||||
int len = sfbus_recv_frame_wait(fd, 0xFFFF, buffer);
|
int len = sfbus_recv_frame_wait(fd, 0xFFFF, buffer);
|
||||||
if (len == 4 && *buffer == (char)0xFF) // expect 0xFF on successful ping
|
if (len == 5 && *buffer == (char)0xFF) // expect 0xFF on successful ping
|
||||||
{
|
{
|
||||||
printf("Ping okay!\n");
|
printf("Ping okay!\n");
|
||||||
free(buffer);
|
free(buffer);
|
||||||
@@ -235,7 +235,8 @@ u_int8_t sfbus_read_status(int fd, u_int16_t address, double *voltage, u_int32_t
|
|||||||
char *cmd = "\xF8";
|
char *cmd = "\xF8";
|
||||||
char *_buffer = malloc(256);
|
char *_buffer = malloc(256);
|
||||||
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
|
sfbus_send_frame_v2(fd, address, strlen(cmd), cmd);
|
||||||
int res = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
|
|
||||||
|
int res = sfbus_recv_frame_wait(fd, 0xFFFF, _buffer);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
@@ -248,7 +249,9 @@ u_int8_t sfbus_read_status(int fd, u_int16_t address, double *voltage, u_int32_t
|
|||||||
|
|
||||||
*voltage = __voltage;
|
*voltage = __voltage;
|
||||||
*counter = (u_int32_t)_counter;
|
*counter = (u_int32_t)_counter;
|
||||||
return *_buffer;
|
|
||||||
|
free(_buffer);
|
||||||
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfbus_reset_device(int fd, u_int16_t address)
|
void sfbus_reset_device(int fd, u_int16_t address)
|
||||||
|
|||||||
Reference in New Issue
Block a user