rework hdlc protocol, example in main.c
This commit is contained in:
parent
c0bb094a39
commit
a154d92903
66
hdlc/crc.c
Normal file
66
hdlc/crc.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "crc.h"
|
||||||
|
|
||||||
|
const int8_t size = 2;
|
||||||
|
const CRC_t CRC_INIT = 0xFFFFU;
|
||||||
|
const CRC_t CRC_FINALXOR = 0xFFFFU;
|
||||||
|
const CRC_t CRC_GOOD = 0xF0B8U;
|
||||||
|
|
||||||
|
static const uint16_t CRC_TAB[256U] = {
|
||||||
|
0x0000UL, 0x1189UL, 0x2312UL, 0x329BUL, 0x4624UL, 0x57ADUL, 0x6536UL, 0x74BFUL,
|
||||||
|
0x8C48UL, 0x9DC1UL, 0xAF5AUL, 0xBED3UL, 0xCA6CUL, 0xDBE5UL, 0xE97EUL, 0xF8F7UL,
|
||||||
|
0x1081UL, 0x0108UL, 0x3393UL, 0x221AUL, 0x56A5UL, 0x472CUL, 0x75B7UL, 0x643EUL,
|
||||||
|
0x9CC9UL, 0x8D40UL, 0xBFDBUL, 0xAE52UL, 0xDAEDUL, 0xCB64UL, 0xF9FFUL, 0xE876UL,
|
||||||
|
0x2102UL, 0x308BUL, 0x0210UL, 0x1399UL, 0x6726UL, 0x76AFUL, 0x4434UL, 0x55BDUL,
|
||||||
|
0xAD4AUL, 0xBCC3UL, 0x8E58UL, 0x9FD1UL, 0xEB6EUL, 0xFAE7UL, 0xC87CUL, 0xD9F5UL,
|
||||||
|
0x3183UL, 0x200AUL, 0x1291UL, 0x0318UL, 0x77A7UL, 0x662EUL, 0x54B5UL, 0x453CUL,
|
||||||
|
0xBDCBUL, 0xAC42UL, 0x9ED9UL, 0x8F50UL, 0xFBEFUL, 0xEA66UL, 0xD8FDUL, 0xC974UL,
|
||||||
|
0x4204UL, 0x538DUL, 0x6116UL, 0x709FUL, 0x0420UL, 0x15A9UL, 0x2732UL, 0x36BBUL,
|
||||||
|
0xCE4CUL, 0xDFC5UL, 0xED5EUL, 0xFCD7UL, 0x8868UL, 0x99E1UL, 0xAB7AUL, 0xBAF3UL,
|
||||||
|
0x5285UL, 0x430CUL, 0x7197UL, 0x601EUL, 0x14A1UL, 0x0528UL, 0x37B3UL, 0x263AUL,
|
||||||
|
0xDECDUL, 0xCF44UL, 0xFDDFUL, 0xEC56UL, 0x98E9UL, 0x8960UL, 0xBBFBUL, 0xAA72UL,
|
||||||
|
0x6306UL, 0x728FUL, 0x4014UL, 0x519DUL, 0x2522UL, 0x34ABUL, 0x0630UL, 0x17B9UL,
|
||||||
|
0xEF4EUL, 0xFEC7UL, 0xCC5CUL, 0xDDD5UL, 0xA96AUL, 0xB8E3UL, 0x8A78UL, 0x9BF1UL,
|
||||||
|
0x7387UL, 0x620EUL, 0x5095UL, 0x411CUL, 0x35A3UL, 0x242AUL, 0x16B1UL, 0x0738UL,
|
||||||
|
0xFFCFUL, 0xEE46UL, 0xDCDDUL, 0xCD54UL, 0xB9EBUL, 0xA862UL, 0x9AF9UL, 0x8B70UL,
|
||||||
|
0x8408UL, 0x9581UL, 0xA71AUL, 0xB693UL, 0xC22CUL, 0xD3A5UL, 0xE13EUL, 0xF0B7UL,
|
||||||
|
0x0840UL, 0x19C9UL, 0x2B52UL, 0x3ADBUL, 0x4E64UL, 0x5FEDUL, 0x6D76UL, 0x7CFFUL,
|
||||||
|
0x9489UL, 0x8500UL, 0xB79BUL, 0xA612UL, 0xD2ADUL, 0xC324UL, 0xF1BFUL, 0xE036UL,
|
||||||
|
0x18C1UL, 0x0948UL, 0x3BD3UL, 0x2A5AUL, 0x5EE5UL, 0x4F6CUL, 0x7DF7UL, 0x6C7EUL,
|
||||||
|
0xA50AUL, 0xB483UL, 0x8618UL, 0x9791UL, 0xE32EUL, 0xF2A7UL, 0xC03CUL, 0xD1B5UL,
|
||||||
|
0x2942UL, 0x38CBUL, 0x0A50UL, 0x1BD9UL, 0x6F66UL, 0x7EEFUL, 0x4C74UL, 0x5DFDUL,
|
||||||
|
0xB58BUL, 0xA402UL, 0x9699UL, 0x8710UL, 0xF3AFUL, 0xE226UL, 0xD0BDUL, 0xC134UL,
|
||||||
|
0x39C3UL, 0x284AUL, 0x1AD1UL, 0x0B58UL, 0x7FE7UL, 0x6E6EUL, 0x5CF5UL, 0x4D7CUL,
|
||||||
|
0xC60CUL, 0xD785UL, 0xE51EUL, 0xF497UL, 0x8028UL, 0x91A1UL, 0xA33AUL, 0xB2B3UL,
|
||||||
|
0x4A44UL, 0x5BCDUL, 0x6956UL, 0x78DFUL, 0x0C60UL, 0x1DE9UL, 0x2F72UL, 0x3EFBUL,
|
||||||
|
0xD68DUL, 0xC704UL, 0xF59FUL, 0xE416UL, 0x90A9UL, 0x8120UL, 0xB3BBUL, 0xA232UL,
|
||||||
|
0x5AC5UL, 0x4B4CUL, 0x79D7UL, 0x685EUL, 0x1CE1UL, 0x0D68UL, 0x3FF3UL, 0x2E7AUL,
|
||||||
|
0xE70EUL, 0xF687UL, 0xC41CUL, 0xD595UL, 0xA12AUL, 0xB0A3UL, 0x8238UL, 0x93B1UL,
|
||||||
|
0x6B46UL, 0x7ACFUL, 0x4854UL, 0x59DDUL, 0x2D62UL, 0x3CEBUL, 0x0E70UL, 0x1FF9UL,
|
||||||
|
0xF78FUL, 0xE606UL, 0xD49DUL, 0xC514UL, 0xB1ABUL, 0xA022UL, 0x92B9UL, 0x8330UL,
|
||||||
|
0x7BC7UL, 0x6A4EUL, 0x58D5UL, 0x495CUL, 0x3DE3UL, 0x2C6AUL, 0x1EF1UL, 0x0F78UL
|
||||||
|
};
|
||||||
|
|
||||||
|
void crc_init(CRC16_CCITT* crc_obj) {
|
||||||
|
crc_obj->crc = CRC_INIT;
|
||||||
|
crc_obj->size = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc_update(CRC16_CCITT* crc_obj, uint8_t data) {
|
||||||
|
crc_obj->crc = (crc_obj->crc >> 8U) ^ CRC_TAB[(crc_obj->crc ^ data) & CRC_FINALXOR];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool crc_good(const CRC16_CCITT* crc_obj) {
|
||||||
|
return crc_obj->crc == 0xF0B8U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc_final(CRC16_CCITT* crc_obj) {
|
||||||
|
crc_obj->crc ^= CRC_FINALXOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t crc_get(const CRC16_CCITT* crc_obj, int8_t pos) {
|
||||||
|
if (pos == 0){
|
||||||
|
return crc_obj->crc;
|
||||||
|
} else{
|
||||||
|
return crc_obj->crc >> 8U;
|
||||||
|
}
|
||||||
|
}
|
25
hdlc/crc.h
Normal file
25
hdlc/crc.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Created by 79513 on 13.06.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CRC16_CCITT_H_
|
||||||
|
#define CRC16_CCITT_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef uint16_t CRC_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const CRC_t* CRC_TAB;
|
||||||
|
CRC_t crc;
|
||||||
|
int size;
|
||||||
|
} CRC16_CCITT;
|
||||||
|
|
||||||
|
void crc_init(CRC16_CCITT* crc_obj);
|
||||||
|
void crc_update(CRC16_CCITT* crc_obj, uint8_t data);
|
||||||
|
bool crc_good(const CRC16_CCITT* crc_obj);
|
||||||
|
void crc_final(CRC16_CCITT* crc_obj);
|
||||||
|
uint8_t crc_get(const CRC16_CCITT* crc_obj, int8_t pos);
|
||||||
|
|
||||||
|
#endif
|
164
hdlc/hdlc.c
164
hdlc/hdlc.c
@ -1,164 +0,0 @@
|
|||||||
#include "hdlc.h"
|
|
||||||
|
|
||||||
#define FRAME_BOUNDARY_OCTET 0x7E
|
|
||||||
|
|
||||||
/* "Управляющий экранирующий октет", имеет битовую последовательность '01111101', (7D шестнадцатеричный) */
|
|
||||||
#define CONTROL_ESCAPE_OCTET 0x7D
|
|
||||||
|
|
||||||
/* Если любой из этих двух октетов появляется в передаваемых данных, отправляется экранирующий октет, */
|
|
||||||
/* за которым следует исходный октет данных с инвертированным битом 5 */
|
|
||||||
#define INVERT_OCTET 0x20
|
|
||||||
|
|
||||||
/* Последовательность проверки кадров (FCS) представляет собой 16-битный CRC-CCITT */
|
|
||||||
/* Функция AVR Libc CRC - это _crc_ccitt_update() */
|
|
||||||
#define CRC16_CCITT_INIT_VAL 0xFFFF
|
|
||||||
|
|
||||||
/* 16-битный копировальный аппарат с младшими и старшими байтами */
|
|
||||||
#define low(x) ((x) & 0xFF)
|
|
||||||
#define high(x) (((x)>>8) & 0xFF)
|
|
||||||
|
|
||||||
#define lo8(x) ((x)&0xff)
|
|
||||||
#define hi8(x) ((x)>>8)
|
|
||||||
|
|
||||||
struct {
|
|
||||||
sendchar_type sendchar_function;
|
|
||||||
frame_handler_type frame_handler;
|
|
||||||
bool escape_character;
|
|
||||||
uint16_t frame_position;
|
|
||||||
uint16_t frame_checksum;
|
|
||||||
uint8_t receive_frame_buffer[MINIHDLC_MAX_FRAME_LENGTH + 1];
|
|
||||||
} mhst;
|
|
||||||
|
|
||||||
static uint16_t _crc_ccitt_update(uint16_t crc, uint8_t data) {
|
|
||||||
data ^= lo8(crc);
|
|
||||||
data ^= data << 4;
|
|
||||||
|
|
||||||
return ((((uint16_t) data << 8) | hi8(crc)) ^ (uint8_t) (data >> 4)
|
|
||||||
^ ((uint16_t) data << 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
void hdlc_init(sendchar_type sendchar_function,
|
|
||||||
frame_handler_type frame_hander_function) {
|
|
||||||
mhst.sendchar_function = sendchar_function;
|
|
||||||
mhst.frame_handler = frame_hander_function;
|
|
||||||
mhst.frame_position = 0;
|
|
||||||
mhst.frame_checksum = CRC16_CCITT_INIT_VAL;
|
|
||||||
mhst.escape_character = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Функция для отправки байта через UART*/
|
|
||||||
static inline void hdlc_sendchar(uint8_t data) {
|
|
||||||
if (mhst.sendchar_function) {
|
|
||||||
(*mhst.sendchar_function)(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Функция для поиска допустимого кадра HDLC по входящим данным */
|
|
||||||
void hdlc_char_receiver(uint8_t data) {
|
|
||||||
/* FRAME FLAG */
|
|
||||||
if (data == FRAME_BOUNDARY_OCTET) {
|
|
||||||
if (mhst.escape_character == true) {
|
|
||||||
mhst.escape_character = false;
|
|
||||||
}
|
|
||||||
/* Если обнаружен допустимый кадр */
|
|
||||||
else if ((mhst.frame_position >= 2)
|
|
||||||
&& (mhst.frame_checksum
|
|
||||||
== ((mhst.receive_frame_buffer[mhst.frame_position - 1]
|
|
||||||
<< 8)
|
|
||||||
| (mhst.receive_frame_buffer[mhst.frame_position
|
|
||||||
- 2] & 0xff))))
|
|
||||||
{
|
|
||||||
/* Вызовите пользовательскую функцию и передайте ей фрейм */
|
|
||||||
(*mhst.frame_handler)(mhst.receive_frame_buffer,
|
|
||||||
mhst.frame_position - 2);
|
|
||||||
}
|
|
||||||
mhst.frame_position = 0;
|
|
||||||
mhst.frame_checksum = CRC16_CCITT_INIT_VAL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mhst.escape_character) {
|
|
||||||
mhst.escape_character = false;
|
|
||||||
data ^= INVERT_OCTET;
|
|
||||||
} else if (data == CONTROL_ESCAPE_OCTET) {
|
|
||||||
mhst.escape_character = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mhst.receive_frame_buffer[mhst.frame_position] = data;
|
|
||||||
|
|
||||||
if (mhst.frame_position - 2 >= 0) {
|
|
||||||
mhst.frame_checksum = _crc_ccitt_update(mhst.frame_checksum,
|
|
||||||
mhst.receive_frame_buffer[mhst.frame_position - 2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
mhst.frame_position++;
|
|
||||||
|
|
||||||
if (mhst.frame_position == MINIHDLC_MAX_FRAME_LENGTH) {
|
|
||||||
mhst.frame_position = 0;
|
|
||||||
mhst.frame_checksum = CRC16_CCITT_INIT_VAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Оберните заданные данные во фрейм HDLC и отправляйте их по байту за раз */
|
|
||||||
void hdlc_send_frame(const uint8_t *frame_buffer, uint8_t frame_length) {
|
|
||||||
uint8_t data;
|
|
||||||
uint16_t fcs = CRC16_CCITT_INIT_VAL;
|
|
||||||
|
|
||||||
hdlc_sendchar((uint8_t) FRAME_BOUNDARY_OCTET);
|
|
||||||
|
|
||||||
while (frame_length) {
|
|
||||||
data = *frame_buffer++;
|
|
||||||
fcs = _crc_ccitt_update(fcs, data);
|
|
||||||
if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET)) {
|
|
||||||
hdlc_sendchar((uint8_t) CONTROL_ESCAPE_OCTET);
|
|
||||||
data ^= INVERT_OCTET;
|
|
||||||
}
|
|
||||||
hdlc_sendchar((uint8_t) data);
|
|
||||||
frame_length--;
|
|
||||||
}
|
|
||||||
data = low(fcs);
|
|
||||||
if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET)) {
|
|
||||||
hdlc_sendchar((uint8_t) CONTROL_ESCAPE_OCTET);
|
|
||||||
data ^= (uint8_t) INVERT_OCTET;
|
|
||||||
}
|
|
||||||
hdlc_sendchar((uint8_t) data);
|
|
||||||
data = high(fcs);
|
|
||||||
if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET)) {
|
|
||||||
hdlc_sendchar(CONTROL_ESCAPE_OCTET);
|
|
||||||
data ^= INVERT_OCTET;
|
|
||||||
}
|
|
||||||
hdlc_sendchar(data);
|
|
||||||
hdlc_sendchar(FRAME_BOUNDARY_OCTET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Оберните заданные данные во фрейм HDLC и отправьте их в статический буфер */
|
|
||||||
|
|
||||||
static uint8_t frame_buffer[MINIHDLC_MAX_FRAME_LENGTH + 1];
|
|
||||||
static uint32_t frame_buffer_size = 0;
|
|
||||||
|
|
||||||
static void buffer_init() {
|
|
||||||
frame_buffer_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void buffer_push(uint8_t data) {
|
|
||||||
if (frame_buffer_size >= MINIHDLC_MAX_FRAME_LENGTH) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
frame_buffer[frame_buffer_size] = data;
|
|
||||||
frame_buffer_size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hdlc_send_frame_to_buffer(const uint8_t *frame_buffer, uint8_t frame_length) {
|
|
||||||
mhst.sendchar_function = buffer_push;
|
|
||||||
buffer_init();
|
|
||||||
hdlc_send_frame(frame_buffer, frame_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *hdlc_get_buffer() {
|
|
||||||
return frame_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t hdlc_get_buffer_size() {
|
|
||||||
return frame_buffer_size;
|
|
||||||
}
|
|
175
hdlc/hdlc.h
175
hdlc/hdlc.h
@ -1,22 +1,167 @@
|
|||||||
#ifndef hdlc_h
|
#ifndef HDLC_H_
|
||||||
#define hdlc_h
|
#define HDLC_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <string.h>
|
||||||
|
#include "crc.h"
|
||||||
|
|
||||||
typedef void (*sendchar_type)(uint8_t data);
|
#define HDLC_TEMPLATE \
|
||||||
typedef void (*frame_handler_type)(const uint8_t *frame_buffer,
|
int16_t (*readByte)(void), \
|
||||||
uint16_t frame_length);
|
void (*writeByte)(uint8_t data), \
|
||||||
|
uint16_t rxBuffLen, \
|
||||||
|
struct CRC
|
||||||
|
|
||||||
#define MINIHDLC_MAX_FRAME_LENGTH 64
|
#define HDLC_TEMPLATETYPE \
|
||||||
|
readByte, \
|
||||||
|
writeByte, \
|
||||||
|
rxBuffLen, \
|
||||||
|
CRC
|
||||||
|
|
||||||
void hdlc_init(sendchar_type sendchar_function,
|
struct HDLC {
|
||||||
frame_handler_type frame_hander_function);
|
const uint8_t DATAINVBIT;
|
||||||
void hdlc_char_receiver(uint8_t data);
|
const uint8_t DATASTART;
|
||||||
void hdlc_send_frame(const uint8_t *frame_buffer, uint8_t frame_length);
|
const uint8_t DATAESCAPE;
|
||||||
|
const uint8_t* DATAESCAPELIST;
|
||||||
|
|
||||||
void hdlc_send_frame_to_buffer(const uint8_t *frame_buffer, uint8_t frame_length);
|
int16_t (*readByte)(void);
|
||||||
uint8_t *hdlc_get_buffer();
|
void (*writeByte)(uint8_t data);
|
||||||
uint32_t hdlc_get_buffer_size();
|
uint16_t rxBuffLen;
|
||||||
|
CRC16_CCITT rxcrc;
|
||||||
|
|
||||||
#endif
|
const uint16_t RXBFLEN;
|
||||||
|
|
||||||
|
int8_t status;
|
||||||
|
uint16_t len;
|
||||||
|
CRC16_CCITT txcrc;
|
||||||
|
uint8_t data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void escapeAndWriteByte(struct HDLC* hdlc, uint8_t data) {
|
||||||
|
const uint8_t* escapeList = hdlc->DATAESCAPELIST;
|
||||||
|
while (*escapeList != 0) {
|
||||||
|
if (data == *escapeList) {
|
||||||
|
hdlc->writeByte(hdlc->DATAESCAPE);
|
||||||
|
data ^= hdlc->DATAINVBIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escapeList++;
|
||||||
|
}
|
||||||
|
hdlc->writeByte(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ESCAPED (-1)
|
||||||
|
#define RECEIVING 0
|
||||||
|
#define OK 1
|
||||||
|
#define CRCERR 2
|
||||||
|
|
||||||
|
void HDLC_init(struct HDLC* hdlc){
|
||||||
|
hdlc->len = 0U;
|
||||||
|
hdlc->status = RECEIVING;
|
||||||
|
crc_init(&hdlc->rxcrc);
|
||||||
|
};;
|
||||||
|
|
||||||
|
void HDLC_transmitStart(struct HDLC *hdlc);
|
||||||
|
void HDLC_transmitStart(struct HDLC *hdlc) {
|
||||||
|
hdlc->writeByte(hdlc->DATASTART);
|
||||||
|
crc_init(&hdlc->txcrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HDLC_transmitByte(struct HDLC* hdlc, uint8_t data);
|
||||||
|
void HDLC_transmitByte(struct HDLC* hdlc, uint8_t data){
|
||||||
|
escapeAndWriteByte(hdlc, data);
|
||||||
|
crc_update(&hdlc->txcrc, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HDLC_transmitBytes(struct HDLC* hdlc, const void *vdata, uint16_t len);
|
||||||
|
void HDLC_transmitBytes(struct HDLC* hdlc, const void *vdata, uint16_t len){
|
||||||
|
const uint8_t* data = (const uint8_t*)vdata;
|
||||||
|
while(len)
|
||||||
|
{
|
||||||
|
HDLC_transmitByte(hdlc, *data);
|
||||||
|
++data;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HDLC_transmitEnd(struct HDLC *hdlc);
|
||||||
|
void HDLC_transmitEnd(struct HDLC *hdlc){
|
||||||
|
crc_final(&hdlc->txcrc);
|
||||||
|
for(int i = 0; i < hdlc->txcrc.size; ++i)
|
||||||
|
escapeAndWriteByte(hdlc, hdlc->txcrc.crc);
|
||||||
|
|
||||||
|
hdlc->writeByte(hdlc->DATASTART);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HDLC_transmitBlock(struct HDLC* hdlc, const void* vdata, uint16_t len){
|
||||||
|
HDLC_transmitStart(hdlc);
|
||||||
|
HDLC_transmitBytes(hdlc, vdata, len);
|
||||||
|
HDLC_transmitEnd(hdlc);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t HDLC_receive(struct HDLC* hdlc);
|
||||||
|
uint16_t HDLC_receive(struct HDLC* hdlc){
|
||||||
|
int16_t c = hdlc->readByte();
|
||||||
|
if(c == -1)
|
||||||
|
return 0U;
|
||||||
|
|
||||||
|
if(hdlc->status >= OK)
|
||||||
|
HDLC_init(hdlc);
|
||||||
|
|
||||||
|
uint16_t retv = 0U;
|
||||||
|
|
||||||
|
if(c == hdlc->DATASTART)
|
||||||
|
{
|
||||||
|
if(hdlc->status == RECEIVING && hdlc->len != 0U)
|
||||||
|
{
|
||||||
|
if(crc_good(&hdlc->rxcrc))
|
||||||
|
{
|
||||||
|
hdlc->status = OK;
|
||||||
|
hdlc->len -= hdlc->rxcrc.size;
|
||||||
|
retv = hdlc->len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hdlc->status = CRCERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HDLC_init(hdlc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(hdlc->status == ESCAPED)
|
||||||
|
{
|
||||||
|
hdlc->status = RECEIVING;
|
||||||
|
|
||||||
|
c ^= hdlc->DATAINVBIT;
|
||||||
|
crc_update(&hdlc->rxcrc, c);
|
||||||
|
if (hdlc->len < hdlc->RXBFLEN)
|
||||||
|
hdlc->data[hdlc->len] = c;
|
||||||
|
++hdlc->len;
|
||||||
|
}
|
||||||
|
else if(c != hdlc->DATAESCAPE)
|
||||||
|
{
|
||||||
|
crc_update(&hdlc->rxcrc, c);
|
||||||
|
if(hdlc->len < hdlc->RXBFLEN)
|
||||||
|
hdlc->data[hdlc->len] = c;
|
||||||
|
++hdlc->len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hdlc->status = ESCAPED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retv;
|
||||||
|
}
|
||||||
|
uint16_t HDLC_copyReceivedMessage(const struct HDLC* hdlc, uint8_t buff[]);
|
||||||
|
uint16_t HDLC_copyReceivedMessage(const struct HDLC* hdlc, uint8_t buff[]){
|
||||||
|
const uint16_t datalen = (hdlc->len > hdlc->RXBFLEN) ? hdlc->RXBFLEN : hdlc->len;
|
||||||
|
memcpy(buff, hdlc->data, datalen);
|
||||||
|
return datalen;
|
||||||
|
}
|
||||||
|
uint16_t HDLC_copyReceivedMessage2(const struct HDLC* hdlc, uint8_t* buff, uint16_t pos, uint16_t num);
|
||||||
|
|
||||||
|
#endif /* HDLC_H_ */
|
||||||
|
33
hdlc/main.c
Normal file
33
hdlc/main.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "hdlc.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct HDLC hdlc;
|
||||||
|
|
||||||
|
void hdlc_sendMsg() {
|
||||||
|
uint8_t msg[] = "Hello world!";
|
||||||
|
HDLC_transmitBlock(&hdlc, msg, sizeof(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdlc_receiveMsg() {
|
||||||
|
int16_t resp = HDLC_receive(&hdlc);
|
||||||
|
if(resp != 0U)
|
||||||
|
{
|
||||||
|
uint8_t buff[hdlc.RXBFLEN];
|
||||||
|
uint16_t size = HDLC_copyReceivedMessage(&hdlc, buff);
|
||||||
|
|
||||||
|
printf("Msg[%u]=%s\n", size, buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//нужно указать 2 функции на чтение и запись байтов, чтобы работало
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
HDLC_init(&hdlc);
|
||||||
|
|
||||||
|
hdlc_sendMsg();
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
hdlc_receiveMsg();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user