31 Commits
Author SHA1 Message Date
stud126166 c17371a76d Загрузить файлы в «/» 2024-02-13 18:47:51 +00:00
Qukich 800f48bc11 fix final version(hdlc) 2024-02-11 17:16:36 +03:00
Qukich 80cd73c3d6 final version, gg 2024-02-09 12:36:55 +03:00
Qukich ca36c67ba2 fix index 2024-02-07 19:39:27 +03:00
Qukich 0f99988c3e Merge branch 'dev' of https://git.vyatsu.ru/ICS-Microprocessor-2020/Display_Avr_3 into dev 2024-02-07 19:27:10 +03:00
Qukich 38b0a7f8ad fix i-frame 2024-02-07 19:27:01 +03:00
stud126172 9d42cbee7f Merge pull request 'lcd1602_v2' (#12) from lcd1602_v2 into dev
Reviewed-on: #12
2024-02-06 07:34:23 +00:00
stud126165 158df4a788 Merge pull request 'uart' (#11) from uart into dev
Reviewed-on: #11
2024-02-06 07:32:12 +00:00
Qukich 659ce6c581 delete trash 2024-02-06 10:30:03 +03:00
Qukich a26f4d3366 create dev 2024-02-06 10:29:00 +03:00
Qukich 3f78f6b38f fix, add protocol and example in dir hdlc 2024-02-02 14:19:11 +03:00
Qukich 82408c4d50 new version. Example in main 2024-02-02 14:16:59 +03:00
Qukich 941a9feef6 rework send frames and init client 2024-01-12 14:17:34 +03:00
Qukich 26c316f47a com 2023-12-26 12:18:19 +03:00
Qukich 0cd965969e w2 2023-12-25 20:11:57 +03:00
Qukich 671c3ba048 w 2023-12-25 20:11:27 +03:00
stud126172 8dade4f9a0 Загрузил(а) файлы в '' 2023-09-28 14:26:24 +00:00
stud126166 97f38c92d5 Загрузил(а) файлы в '' 2023-07-29 13:50:30 +00:00
Qukich ecdac7b3d3 delete serial ports 2023-06-25 16:36:30 +03:00
stud126186 c16d9662dd Merge pull request 'uart' (#5) from uart into hdlc-interface
Reviewed-on: #5
2023-06-25 13:10:45 +00:00
Qukich 321722d9b1 rework validate 2023-06-25 16:04:52 +03:00
Qukich 8e4329c9d3 It remains to complete the validation of frames 2023-06-22 13:11:57 +03:00
Qukich eceecf15d4 add client 2023-06-19 19:38:35 +03:00
Qukich 4b4a162f72 delete malloc 2023-06-15 19:48:27 +03:00
stud126172 be7bedb8c7 1602 2023-06-15 16:29:15 +00:00
Qukich a19da2cbd3 add hdlc frame 2023-06-15 16:22:51 +03:00
Qukich a154d92903 rework hdlc protocol, example in main.c 2023-06-14 15:36:47 +03:00
Qukich c0bb094a39 rework hdlc protocol 2023-06-06 19:59:18 +03:00
Qukich c82c3b11cb add hdlc protocol, need test 2023-05-24 18:09:43 +03:00
stud126172 037f7ce38a lcd 2023-05-11 08:24:30 +00:00
Qukich d71e47036c add header hdlc file 2023-05-08 14:47:51 +03:00
37 changed files with 2564 additions and 35 deletions
+13
View File
@@ -0,0 +1,13 @@
hdlc1.c
hdlc1.h
hdlc_frame.c
hdlc_frame.h
main1.c
uart.c
uart.h
!./hdlc
/.idea/Display_Avr_3.iml
/.idea/.gitignore
/.idea/vcs.xml
/.idea/modules.xml
+113
View File
@@ -0,0 +1,113 @@
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <compat/twi.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "lcdpcf8574.h"
#include "pcf8574.h"
#include "i2cmaster.h"
#include "lcd.h"
#include <Arduino.h>
struct DisplayData {
char topLine[64];
int value1;
int value2;
int value3;
};
struct TextCounter {
unsigned long startTime;
int incrementValue;
};
TextCounter textCounter;
void Lcd_inciliation() {
lcd_init(LCD_DISP_ON_BLINK); // инициализация дисплея
lcd_home(); // домой курсор
lcd_led(0); // вкл подсветки
textCounter.startTime = millis(); // Запоминаем время запуска программы
}
void fillBuffer1(const char * source, char * buffer, size_t bufferSize, int incrementValue) {
int startIndex = incrementValue % strlen(source); // Определяем начальный индекс на основе incrementValue
int endIndex = startIndex + 16;
if (endIndex > strlen(source)) {
// Если endIndex превышает длину строки source, переносим его на начало строки
endIndex = endIndex - strlen(source);
// Копируем символы с конца строки source
strncpy(buffer, source + startIndex, strlen(source) - startIndex);
// Копируем оставшиеся символы с начала строки source
strncat(buffer, source, endIndex);
} else {
strncpy(buffer, source + startIndex, endIndex - startIndex);
}
buffer[endIndex - startIndex] = '\0'; // Установка нулевого символа в конце буфера
}
void fillBuffer2(int value1, int value2, int value3, char * buffer, size_t bufferSize) {
snprintf(buffer, bufferSize, "%d.%d.%d", value1, value2, value3);
}
int convertR(char h, char t, char o)
{
return ((h - '0') * 100 + (t - '0') * 10 + (o - '0') * 1);
}
void first_nine(struct DisplayData arr) {
size_t len = strlen(arr.topLine);
memmove(arr, arr.topLine + 9, len - 8 );
}
void printLcd(const char * inputText)
{
unsigned long currentTime = millis(); // Текущее время
// Проверяем, прошло ли 500 мс с момента последнего увеличения incrementValue
if (currentTime - textCounter.startTime >= 500) {
textCounter.incrementValue++; // Увеличиваем incrementValue на 1
textCounter.startTime = currentTime; // Обновляем время
}
struct DisplayData displayData;
strncpy(displayData.topLine, inputText, sizeof(displayData.topLine) - 1);
displayData.topLine[sizeof(displayData.topLine) - 1] = '\0';
displayData.value1 = convertR(displayData.topLine[0], displayData.topLine[1], displayData.topLine[2]);
displayData.value2 = convertR(displayData.topLine[3], displayData.topLine[4], displayData.topLine[5]);
displayData.value3 = convertR(displayData.topLine[6], displayData.topLine[7], displayData.topLine[8]);
first_nine(displayData);
// Буферы для заполнения данных
char buffer1[17];
char buffer2[17];
// Заполнение буфера 1
fillBuffer1(displayData.topLine, buffer1, sizeof(buffer1), textCounter.incrementValue);
// Заполнение буфера 2
fillBuffer2(displayData.value1, displayData.value2, displayData.value3, buffer2, sizeof(buffer2));
// Создание массива для вывода на дисплей
char displayArray[32];
strncpy(displayArray, buffer1, 16); // Копирование первых 16 символов из buffer1 в displayArray
strncpy(displayArray + 16, buffer2, 16); // Копирование первых 16 символов из buffer2 в displayArray, начиная с позиции 16
// Вывод данных на экран
lcd_gotoxy(0, 0);
lcd_puts(displayArray);
lcd_gotoxy(0, 1);
lcd_puts(displayArray + 16); // Вывод второй половины displayArray
}
+315
View File
@@ -0,0 +1,315 @@
// Based on the work by DFRobot
#include "LiquidCrystal_I2C.h"
#include <inttypes.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#define printIIC(args) Wire.write(args)
inline size_t LiquidCrystal_I2C::write(uint8_t value) {
send(value, Rs);
return 1;
}
#else
#include "WProgram.h"
#define printIIC(args) Wire.send(args)
inline void LiquidCrystal_I2C::write(uint8_t value) {
send(value, Rs);
}
#endif
#include "Wire.h"
// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set:
// DL = 1; 8-bit interface data
// N = 0; 1-line display
// F = 0; 5x8 dot character font
// 3. Display on/off control:
// D = 0; Display off
// C = 0; Cursor off
// B = 0; Blinking off
// 4. Entry mode set:
// I/D = 1; Increment by 1
// S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).
LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows)
{
_Addr = lcd_Addr;
_cols = lcd_cols;
_rows = lcd_rows;
_backlightval = LCD_NOBACKLIGHT;
}
void LiquidCrystal_I2C::init(){
init_priv();
}
void LiquidCrystal_I2C::init_priv()
{
Wire.begin();
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
begin(_cols, _rows);
}
void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
if (lines > 1) {
_displayfunction |= LCD_2LINE;
}
_numlines = lines;
// for some 1 line displays you can select a 10 pixel high font
if ((dotsize != 0) && (lines == 1)) {
_displayfunction |= LCD_5x10DOTS;
}
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// according to datasheet, we need at least 40ms after power rises above 2.7V
// before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
delay(50);
// Now we pull both RS and R/W low to begin commands
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
delay(1000);
//put the LCD into 4 bit mode
// this is according to the hitachi HD44780 datasheet
// figure 24, pg 46
// we start in 8bit mode, try to set 4 bit mode
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
// second try
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
// third go!
write4bits(0x03 << 4);
delayMicroseconds(150);
// finally, set to 4-bit interface
write4bits(0x02 << 4);
// set # lines, font size, etc.
command(LCD_FUNCTIONSET | _displayfunction);
// turn the display on with no cursor or blinking default
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
display();
// clear it off
clear();
// Initialize to default text direction (for roman languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
// set the entry mode
command(LCD_ENTRYMODESET | _displaymode);
home();
}
/********** high level commands, for the user! */
void LiquidCrystal_I2C::clear(){
command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::home(){
command(LCD_RETURNHOME); // set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row){
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if ( row > _numlines ) {
row = _numlines-1; // we count rows starting w/0
}
command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
// Turn the display on/off (quickly)
void LiquidCrystal_I2C::noDisplay() {
_displaycontrol &= ~LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::display() {
_displaycontrol |= LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void LiquidCrystal_I2C::noCursor() {
_displaycontrol &= ~LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::cursor() {
_displaycontrol |= LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void LiquidCrystal_I2C::noBlink() {
_displaycontrol &= ~LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::blink() {
_displaycontrol |= LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void LiquidCrystal_I2C::scrollDisplayLeft(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void LiquidCrystal_I2C::scrollDisplayRight(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
// This is for text that flows Left to Right
void LiquidCrystal_I2C::leftToRight(void) {
_displaymode |= LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void LiquidCrystal_I2C::rightToLeft(void) {
_displaymode &= ~LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void LiquidCrystal_I2C::autoscroll(void) {
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void LiquidCrystal_I2C::noAutoscroll(void) {
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) {
write(charmap[i]);
}
}
// Turn the (optional) backlight off/on
void LiquidCrystal_I2C::noBacklight(void) {
_backlightval=LCD_NOBACKLIGHT;
expanderWrite(0);
}
void LiquidCrystal_I2C::backlight(void) {
_backlightval=LCD_BACKLIGHT;
expanderWrite(0);
}
/*********** mid level commands, for sending data/cmds */
inline void LiquidCrystal_I2C::command(uint8_t value) {
send(value, 0);
}
/************ low level data pushing commands **********/
// write either command or data
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
uint8_t highnib=value&0xf0;
uint8_t lownib=(value<<4)&0xf0;
write4bits((highnib)|mode);
write4bits((lownib)|mode);
}
void LiquidCrystal_I2C::write4bits(uint8_t value) {
expanderWrite(value);
pulseEnable(value);
}
void LiquidCrystal_I2C::expanderWrite(uint8_t _data){
Wire.beginTransmission(_Addr);
printIIC((int)(_data) | _backlightval);
Wire.endTransmission();
}
void LiquidCrystal_I2C::pulseEnable(uint8_t _data){
expanderWrite(_data | En); // En high
delayMicroseconds(1); // enable pulse must be >450ns
expanderWrite(_data & ~En); // En low
delayMicroseconds(50); // commands need > 37us to settle
}
// Alias functions
void LiquidCrystal_I2C::cursor_on(){
cursor();
}
void LiquidCrystal_I2C::cursor_off(){
noCursor();
}
void LiquidCrystal_I2C::blink_on(){
blink();
}
void LiquidCrystal_I2C::blink_off(){
noBlink();
}
void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows){
createChar(char_num, rows);
}
void LiquidCrystal_I2C::setBacklight(uint8_t new_val){
if(new_val){
backlight(); // turn backlight on
}else{
noBacklight(); // turn backlight off
}
}
void LiquidCrystal_I2C::printstr(const char c[]){
//This function is not identical to the function used for "real" I2C displays
//it's here so the user sketch doesn't have to be changed
print(c);
}
// unsupported API functions
void LiquidCrystal_I2C::off(){}
void LiquidCrystal_I2C::on(){}
void LiquidCrystal_I2C::setDelay (int cmdDelay,int charDelay) {}
uint8_t LiquidCrystal_I2C::status(){return 0;}
uint8_t LiquidCrystal_I2C::keypad (){return 0;}
uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype){return 0;}
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end){}
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end){}
void LiquidCrystal_I2C::setContrast(uint8_t new_val){}
+126
View File
@@ -0,0 +1,126 @@
//YWROBOT
#ifndef LiquidCrystal_I2C_h
#define LiquidCrystal_I2C_h
#include <inttypes.h>
#include "Print.h"
#include <Wire.h>
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define En B00000100 // Enable bit
#define Rw B00000010 // Read/Write bit
#define Rs B00000001 // Register select bit
class LiquidCrystal_I2C : public Print {
public:
LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS );
void clear();
void home();
void noDisplay();
void display();
void noBlink();
void blink();
void noCursor();
void cursor();
void scrollDisplayLeft();
void scrollDisplayRight();
void printLeft();
void printRight();
void leftToRight();
void rightToLeft();
void shiftIncrement();
void shiftDecrement();
void noBacklight();
void backlight();
void autoscroll();
void noAutoscroll();
void createChar(uint8_t, uint8_t[]);
void setCursor(uint8_t, uint8_t);
#if defined(ARDUINO) && ARDUINO >= 100
virtual size_t write(uint8_t);
#else
virtual void write(uint8_t);
#endif
void command(uint8_t);
void init();
////compatibility API function aliases
void blink_on(); // alias for blink()
void blink_off(); // alias for noBlink()
void cursor_on(); // alias for cursor()
void cursor_off(); // alias for noCursor()
void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight()
void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar()
void printstr(const char[]);
////Unsupported API functions (not implemented in this library)
uint8_t status();
void setContrast(uint8_t new_val);
uint8_t keypad();
void setDelay(int,int);
void on();
void off();
uint8_t init_bargraph(uint8_t graphtype);
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
private:
void init_priv();
void send(uint8_t, uint8_t);
void write4bits(uint8_t);
void expanderWrite(uint8_t);
void pulseEnable(uint8_t);
uint8_t _Addr;
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _numlines;
uint8_t _cols;
uint8_t _rows;
uint8_t _backlightval;
};
#endif
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
# LiquidCrystal_I2C
LiquidCrystal Arduino library for the DFRobot I2C LCD displays
@@ -0,0 +1,70 @@
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args) write(args);
#else
#define printByte(args) print(args,BYTE);
#endif
uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4};
uint8_t note[8] = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0};
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};
uint8_t duck[8] = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0};
uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0};
uint8_t retarrow[8] = { 0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.createChar(0, bell);
lcd.createChar(1, note);
lcd.createChar(2, clock);
lcd.createChar(3, heart);
lcd.createChar(4, duck);
lcd.createChar(5, check);
lcd.createChar(6, cross);
lcd.createChar(7, retarrow);
lcd.home();
lcd.print("Hello world...");
lcd.setCursor(0, 1);
lcd.print(" i ");
lcd.printByte(3);
lcd.print(" arduinos!");
delay(5000);
displayKeyCodes();
}
// display all keycodes
void displayKeyCodes(void) {
uint8_t i = 0;
while (1) {
lcd.clear();
lcd.print("Codes 0x"); lcd.print(i, HEX);
lcd.print("-0x"); lcd.print(i+16, HEX);
lcd.setCursor(0, 1);
for (int j=0; j<16; j++) {
lcd.printByte(i+j);
}
i+=16;
delay(4000);
}
}
void loop()
{
}
@@ -0,0 +1,28 @@
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
lcd.init(); // initialize the lcd
lcd.init();
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(3,0);
lcd.print("Hello, world!");
lcd.setCursor(2,1);
lcd.print("Ywrobot Arduino!");
lcd.setCursor(0,2);
lcd.print("Arduino LCM IIC 2004");
lcd.setCursor(2,3);
lcd.print("Power By Ec-yuan!");
}
void loop()
{
}
@@ -0,0 +1,34 @@
/*
* Displays text sent over the serial port (e.g. from the Serial Monitor) on
* an attached LCD.
* YWROBOT
*Compatible with the Arduino IDE 1.0
*Library version:1.1
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
lcd.init(); // initialize the lcd
lcd.backlight();
Serial.begin(9600);
}
void loop()
{
// when characters arrive over the serial port...
if (Serial.available()) {
// wait a bit for the entire message to arrive
delay(100);
// clear the screen
lcd.clear();
// read all the available characters
while (Serial.available() > 0) {
// display each character to the LCD
lcd.write(Serial.read());
}
}
}
+46
View File
@@ -0,0 +1,46 @@
###########################################
# Syntax Coloring Map For LiquidCrystal_I2C
###########################################
###########################################
# Datatypes (KEYWORD1)
###########################################
LiquidCrystal_I2C KEYWORD1
###########################################
# Methods and Functions (KEYWORD2)
###########################################
init KEYWORD2
begin KEYWORD2
clear KEYWORD2
home KEYWORD2
noDisplay KEYWORD2
display KEYWORD2
noBlink KEYWORD2
blink KEYWORD2
noCursor KEYWORD2
cursor KEYWORD2
scrollDisplayLeft KEYWORD2
scrollDisplayRight KEYWORD2
leftToRight KEYWORD2
rightToLeft KEYWORD2
shiftIncrement KEYWORD2
shiftDecrement KEYWORD2
noBacklight KEYWORD2
backlight KEYWORD2
autoscroll KEYWORD2
noAutoscroll KEYWORD2
createChar KEYWORD2
setCursor KEYWORD2
print KEYWORD2
blink_on KEYWORD2
blink_off KEYWORD2
cursor_on KEYWORD2
cursor_off KEYWORD2
setBacklight KEYWORD2
load_custom_character KEYWORD2
printstr KEYWORD2
###########################################
# Constants (LITERAL1)
###########################################
+15
View File
@@ -0,0 +1,15 @@
{
"name": "LiquidCrystal_I2C",
"keywords": "LCD, liquidcrystal, I2C",
"description": "A library for DFRobot I2C LCD displays",
"repository":
{
"type": "git",
"url": "https://github.com/marcoschwartz/LiquidCrystal_I2C.git"
},
"frameworks": "arduino",
"platforms":
[
"atmelavr"
]
}
+9
View File
@@ -0,0 +1,9 @@
name=LiquidCrystal I2C
version=1.1.2
author=Frank de Brabander
maintainer=Marco Schwartz <marcolivier.schwartz@gmail.com>
sentence=A library for I2C LCD displays.
paragraph= The library allows to control I2C displays with functions extremely similar to LiquidCrystal library. THIS LIBRARY MIGHT NOT BE COMPATIBLE WITH EXISTING SKETCHES.
category=Display
url=https://github.com/marcoschwartz/LiquidCrystal_I2C
architectures=avr
+100
View File
@@ -0,0 +1,100 @@
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <compat/twi.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "lcdpcf8574.h"
#include "pcf8574.h"
#include "i2cmaster.h"
#include "lsd.h"
#include <Arduino.h>
struct DisplayData {
char topLine[64];
int value1;
int value2;
int value3;
};
struct TextCounter {
unsigned long startTime;
int incrementValue;
};
TextCounter textCounter;
void Lsd_inciliation() {
lcd_init(LCD_DISP_ON_BLINK); // инициализация дисплея
lcd_home(); // домой курсор
lcd_led(0); // вкл подсветки
textCounter.startTime = millis(); // Запоминаем время запуска программы
}
void fillBuffer1(const char * source, char * buffer, size_t bufferSize, int incrementValue) {
int startIndex = incrementValue % strlen(source); // Определяем начальный индекс на основе incrementValue
int endIndex = startIndex + 16;
if (endIndex > strlen(source)) {
// Если endIndex превышает длину строки source, переносим его на начало строки
endIndex = endIndex - strlen(source);
// Копируем символы с конца строки source
strncpy(buffer, source + startIndex, strlen(source) - startIndex);
// Копируем оставшиеся символы с начала строки source
strncat(buffer, source, endIndex);
} else {
strncpy(buffer, source + startIndex, endIndex - startIndex);
}
buffer[endIndex - startIndex] = '\0'; // Установка нулевого символа в конце буфера
}
void fillBuffer2(int value1, int value2, int value3, char * buffer, size_t bufferSize) {
snprintf(buffer, bufferSize, "%d.%d.%d", value1, value2, value3);
}
void printLsd(const char * inputText)
{
unsigned long currentTime = millis(); // Текущее время
// Проверяем, прошло ли 500 мс с момента последнего увеличения incrementValue
if (currentTime - textCounter.startTime >= 500) {
textCounter.incrementValue++; // Увеличиваем incrementValue на 1
textCounter.startTime = currentTime; // Обновляем время
}
DisplayData displayData;
strncpy(displayData.topLine, inputText, sizeof(displayData.topLine) - 1);
displayData.topLine[sizeof(displayData.topLine) - 1] = '\0';
displayData.value1 = 500;
displayData.value2 = 800;
displayData.value3 = 855;
// Буферы для заполнения данных
char buffer1[17];
char buffer2[17];
// Заполнение буфера 1
fillBuffer1(displayData.topLine, buffer1, sizeof(buffer1), textCounter.incrementValue);
// Заполнение буфера 2
fillBuffer2(displayData.value1, displayData.value2, displayData.value3, buffer2, sizeof(buffer2));
// Создание массива для вывода на дисплей
char displayArray[32];
strncpy(displayArray, buffer1, 16); // Копирование первых 16 символов из buffer1 в displayArray
strncpy(displayArray + 16, buffer2, 16); // Копирование первых 16 символов из buffer2 в displayArray, начиная с позиции 16
// Вывод данных на экран
lcd_gotoxy(0, 0);
lcd_puts(displayArray);
lcd_gotoxy(0, 1);
lcd_puts(displayArray + 16); // Вывод второй половины displayArray
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef Lsd_print_h
#define Lsd_print_h
#include <Arduino.h>
void Lsd_inciliation();
void printLsd(const char* inputText);
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef MYLCD_H_
#define MYLCD_H_
// ïîäêëþ÷àåì âñå ëèáû
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <compat/twi.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "lcdpcf8574.h"
#include "pcf8574.h"
#include "i2cmaster.h"
#endif
+42
View File
@@ -0,0 +1,42 @@
#ifndef _I2CMASTER_H
#define _I2CMASTER_H
// флаг, отвечающий за чтение данных по i2c
#define I2C_READ 1
// флаг, отвечающий за отправку данных по i2c
#define I2C_WRITE 0
// частота тактирования линии в Герцах
#define SCL_CLOCK 100000L
// инициализация интерфейса
void i2c_init(void);
// передача условия СТОП на шину
void i2c_stop(void);
// передача условия СТАРТ на шину
unsigned char i2c_start(unsigned char addr);
// повторный старт(перезапуск)
unsigned char i2c_rep_start(unsigned char addr);
// ждем, если устрой-во занято, а потом передаем условие СТАРТ на шину
void i2c_start_wait(unsigned char addr);
// отправка данных
unsigned char i2c_write(unsigned char data);
// читаем данные и продолжаем вещание
unsigned char i2c_readAck(void);
// читаем данные и после их получения передаем услови СТОП
unsigned char i2c_readNak(void);
// читаем данные с шины
unsigned char i2c_read(unsigned char ack);
// выбираем какой варинт чтения данных будет
#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
#endif
+10
View File
@@ -0,0 +1,10 @@
lcd_init KEYWORD2
lcd_clrscr KEYWORD2
lcd_home KEYWORD2
lcd_gotoxy KEYWORD2
lcd_led KEYWORD2
lcd_putc KEYWORD2
lcd_puts KEYWORD2
lcd_puts_p KEYWORD2
lcd_command KEYWORD2
lcd_data KEYWORD2
+316
View File
@@ -0,0 +1,316 @@
#include "MyLCD.h"
// задержеки через асемблер
#define lcd_e_delay() __asm__ __volatile__( "rjmp 1f\n 1:" );
#define lcd_e_toggle() toggle_e()
volatile uint8_t dataport = 0;
static void toggle_e(void);
// сама реализация задержек
static inline void _delayFourCycles(unsigned int __count)
{
if ( __count == 0 )
__asm__ __volatile__( "rjmp 1f\n 1:" );
else
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}
// тупа оборачиваем функцию в макрос
#define delay(us) _delayFourCycles( ( ( 1*(F_CPU/4000) )*us)/1000 )
// переключение пина для начала записи команды
static void toggle_e(void)
{
pcf8574_setoutputpinhigh(LCD_PCF8574_DEVICEID, LCD_E_PIN);
lcd_e_delay();
pcf8574_setoutputpinlow(LCD_PCF8574_DEVICEID, LCD_E_PIN);
}
// отправка байта для контроллера LCD
static void lcd_write(uint8_t data,uint8_t rs)
{
if (rs) //отправка данных (RS=1, RW=0)
dataport |= _BV(LCD_RS_PIN);
else // отпрака инструкций(RS=0, RW=0)
dataport &= ~_BV(LCD_RS_PIN);
dataport &= ~_BV(LCD_RW_PIN);
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
// отправка старшего полубайта
dataport &= ~_BV(LCD_DATA3_PIN);
dataport &= ~_BV(LCD_DATA2_PIN);
dataport &= ~_BV(LCD_DATA1_PIN);
dataport &= ~_BV(LCD_DATA0_PIN);
if(data & 0x80) dataport |= _BV(LCD_DATA3_PIN);
if(data & 0x40) dataport |= _BV(LCD_DATA2_PIN);
if(data & 0x20) dataport |= _BV(LCD_DATA1_PIN);
if(data & 0x10) dataport |= _BV(LCD_DATA0_PIN);
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
lcd_e_toggle();
// отправка младшего полубайта
dataport &= ~_BV(LCD_DATA3_PIN);
dataport &= ~_BV(LCD_DATA2_PIN);
dataport &= ~_BV(LCD_DATA1_PIN);
dataport &= ~_BV(LCD_DATA0_PIN);
if(data & 0x08) dataport |= _BV(LCD_DATA3_PIN);
if(data & 0x04) dataport |= _BV(LCD_DATA2_PIN);
if(data & 0x02) dataport |= _BV(LCD_DATA1_PIN);
if(data & 0x01) dataport |= _BV(LCD_DATA0_PIN);
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
lcd_e_toggle();
// завершаем передачу
dataport |= _BV(LCD_DATA0_PIN);
dataport |= _BV(LCD_DATA1_PIN);
dataport |= _BV(LCD_DATA2_PIN);
dataport |= _BV(LCD_DATA3_PIN);
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
}
// чтение байта
static uint8_t lcd_read(uint8_t rs)
{
uint8_t data;
if (rs) // запись данных (RS=1, RW=0)
dataport |= _BV(LCD_RS_PIN);
else // запись инструкций (RS=0, RW=0)
dataport &= ~_BV(LCD_RS_PIN);
dataport |= _BV(LCD_RW_PIN);
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
pcf8574_setoutputpinhigh(LCD_PCF8574_DEVICEID, LCD_E_PIN);
lcd_e_delay();
// чтение страшего полубайта
data = pcf8574_getoutputpin(LCD_PCF8574_DEVICEID, LCD_DATA0_PIN) << 4;
pcf8574_setoutputpinlow(LCD_PCF8574_DEVICEID, LCD_E_PIN);
lcd_e_delay();
pcf8574_setoutputpinhigh(LCD_PCF8574_DEVICEID, LCD_E_PIN);
lcd_e_delay();
// чтение младшего полубайта
data |= pcf8574_getoutputpin(LCD_PCF8574_DEVICEID, LCD_DATA0_PIN) &0x0F;
pcf8574_setoutputpinlow(LCD_PCF8574_DEVICEID, LCD_E_PIN);
return data;
}
// ждем пока ЖК освободится
static uint8_t lcd_waitbusy(void)
{
register uint8_t c;
// ждем
while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}
// задержка
delay(2);
// получаем адрес
return (lcd_read(0));
}
// перемещение курсора по строкам
static inline void lcd_newline(uint8_t pos)
{
register uint8_t addressCounter;
#if LCD_LINES==1
addressCounter = 0;
#endif
#if LCD_LINES==2
if ( pos < (LCD_START_LINE2) )
addressCounter = LCD_START_LINE2;
else
addressCounter = LCD_START_LINE1;
#endif
#if LCD_LINES==4
if ( pos < LCD_START_LINE3 )
addressCounter = LCD_START_LINE2;
else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) )
addressCounter = LCD_START_LINE3;
else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) )
addressCounter = LCD_START_LINE4;
else
addressCounter = LCD_START_LINE1;
#endif
lcd_command((1<<LCD_DDRAM)+addressCounter);
}
// служебная функция для отправки команд дисплею
void lcd_command(uint8_t cmd)
{
lcd_waitbusy();
lcd_write(cmd,0);
}
// отправка байта на дисплей
void lcd_data(uint8_t data)
{
lcd_waitbusy();
lcd_write(data,1);
}
// перемещение курсора по координатам
void lcd_gotoxy(uint8_t x, uint8_t y)
{
#if LCD_LINES==1
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
#endif
#if LCD_LINES==2
if ( y==0 )
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
else
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
#endif
#if LCD_LINES==4
if ( y==0 )
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
else if ( y==1)
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
else if ( y==2)
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE3+x);
else
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE4+x);
#endif
}
// тырим координаты
int lcd_getxy(void)
{
return lcd_waitbusy();
}
// очистка дисплея
void lcd_clrscr(void)
{
lcd_command(1<<LCD_CLR);
}
// вкл и откл подсветки
void lcd_led(uint8_t onoff)
{
if(onoff)
dataport &= ~_BV(LCD_LED_PIN);
else
dataport |= _BV(LCD_LED_PIN);
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
}
// курсов в начало координат
void lcd_home(void)
{
lcd_command(1<<LCD_HOME);
}
// отображение символа в текущей позиции курсора
void lcd_putc(char c)
{
uint8_t pos;
pos = lcd_waitbusy();
if (c=='\n')
{
lcd_newline(pos);
}
else
{
#if LCD_WRAP_LINES==1
#if LCD_LINES==1
if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
}
#elif LCD_LINES==2
if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);
}else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ){
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
}
#elif LCD_LINES==4
if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);
}else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE3,0);
}else if ( pos == LCD_START_LINE3+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE4,0);
}else if ( pos == LCD_START_LINE4+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
}
#endif
lcd_waitbusy();
#endif
lcd_write(c, 1);
}
}
// вывод строки на дисплей
void lcd_puts(const char *s)
{
register char c;
while ( (c = *s++) ) {
lcd_putc(c);
}
}
// вывод строки из памяти
void lcd_puts_p(const char *progmem_s)
{
register char c;
while ( (c = pgm_read_byte(progmem_s++)) ) {
lcd_putc(c);
}
}
// инициализация дисплея
void lcd_init(uint8_t dispAttr)
{
#if LCD_PCF8574_INIT == 1
//инициализация pcf
pcf8574_init();
#endif
dataport = 0;
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
delay(16000);
// первоначальная запись на ЖК-дисплей — 8 бит
dataport |= _BV(LCD_DATA1_PIN); // _BV(LCD_FUNCTION)>>4;
dataport |= _BV(LCD_DATA0_PIN); // _BV(LCD_FUNCTION_8BIT)>>4;
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
// дрючим дисплей чтобы он начал работать
lcd_e_toggle();
delay(4992);
lcd_e_toggle();
delay(64);
lcd_e_toggle();
delay(64);
// переходим в 4 битный режим
dataport &= ~_BV(LCD_DATA0_PIN);
pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport);
lcd_e_toggle();
delay(64);
lcd_command(LCD_FUNCTION_DEFAULT); // настраиваем кол-во строк
lcd_command(LCD_DISP_OFF); // вырубаем дисплей
lcd_clrscr(); // чистим экран
lcd_command(LCD_MODE_DEFAULT); // запускаемся в стандартном режиме
lcd_command(dispAttr); // отправляем настройки
}
+110
View File
@@ -0,0 +1,110 @@
#ifndef LCD_H
#define LCD_H
#define LCD_PCF8574_INIT 1 //èíèöèàëèçàöèÿ pcf
#define LCD_PCF8574_DEVICEID 0 //id óñò-âà
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES
// óñòàíîâêà ðåæèìà ââîäà: âêëþ÷åíèå/âûêëþ÷åíèå ñìåùåíèÿ äèñïëåÿ, íàïðàâëåíèå ïåðåìåùåíèÿ êóðñîðà óìåíüøàòü/óâåëè÷èâàòü
#define LCD_ENTRY_DEC 0x04 // ñìåùåíèå äèñïëåÿ âûêëþ÷åíî, êóðñîð ïåðåìåùàåòñÿ ïî íàêëîíó
#define LCD_ENTRY_DEC_SHIFT 0x05 // âêëþ÷åíèå ñäâèãà äèñïëåÿ, ïåðåìåùåíèå êóðñîðà ïî íàêëîíó
#define LCD_ENTRY_INC_ 0x06 // ñìåùåíèå äèñïëåÿ âûêëþ÷åíî, âêë. ïåðåìåùåíèå êóðñîðà â íàïðàâëåíèè
#define LCD_ENTRY_INC_SHIFT 0x07 // âêëþ÷åíèå ñìåùåíèÿ äèñïëåÿ, óâåëè÷åíèå íàïðàâëåíèÿ ïåðåìåùåíèÿ êóðñîðà
// âêëþ÷åíèå/âûêëþ÷åíèå äèñïëåÿ, âêëþ÷åíèå/âûêëþ÷åíèå êóðñîðà, ìèãàþùèé ñèìâîë â ïîçèöèè êóðñîðà
#define LCD_DISP_OFF 0x08 // äèñïëåé âûêëþ÷åí
#define LCD_DISP_ON 0x0C // äèñïëåé âêë, êóðñîð âûêë
#define LCD_DISP_ON_BLINK 0x0D // äèñïëåé âêë, êóðñîð âûêë, åñòü ìèãàþùèé ñèìâë
#define LCD_DISP_ON_CURSOR 0x0E // äèñïëåé âêë, êóðñîð âêë
#define LCD_DISP_ON_CURSOR_BLINK 0x0F // äèñïëåé âêë, êóðñîð âêë, åñòü ìèãàþùèé ñèìâë
// ïåðåìåùåíèå êóðñîðà/ñìåùåíèå äèñïëåÿ
#define LCD_MOVE_CURSOR_LEFT 0x10 // êóðñîð íàëåâî
#define LCD_MOVE_CURSOR_RIGHT 0x14 // êóðñîð íàïðàâî
#define LCD_MOVE_DISP_LEFT 0x18 // ñäâèã âëåâî
#define LCD_MOVE_DISP_RIGHT 0x1C // ñäâèã âïðàâî
// íàáîð ôóíêöèé: óñòàíîâêà äëèíû äàííûõ èíòåðôåéñà è êîëè÷åñòâà ñòðîê îòîáðàæåíèÿ
#define LCD_FUNCTION_4BIT_1LINE 0x20 // 4-áèòíûé èíòåðôåéñ, îäíà ñòðîêà, 5x7 òî÷åê
#define LCD_FUNCTION_4BIT_2LINES 0x28 // 4-áèòíûé èíòåðôåéñ, äâóõñòðî÷íûé, 5x7 òî÷åê
#define LCD_FUNCTION_8BIT_1LINE 0x30 // 8-áèòíûé èíòåðôåéñ, îäíà ñòðîêà, 5x7 òî÷åê
#define LCD_FUNCTION_8BIT_2LINES 0x38 // 8-áèòíûé èíòåðôåéñ, äâóõñòðî÷íûé, 5x7 òî÷åê
#define LCD_LINES 2 // êîë-âî ñòðîê
#define LCD_DISP_LENGTH 16 // êîë-âî ñèìâîëîâ â ñòðîêå
#define LCD_LINE_LENGTH 0x40 // âíóòðåííÿÿ äëèíà ñòðîêè äèñïëåÿ
#define LCD_START_LINE1 0x00 // DDRM àäðåñ äëÿ 1 ñòðîêè
#define LCD_START_LINE2 0x40 // DDRM àäðåñ äëÿ 2 ñòðîêè
#define LCD_WRAP_LINES 1 // ïåðåíîñ ñòðîêè
#define LCD_DATA0_PIN 4 // ïèí äëÿ äàííûõ
#define LCD_DATA1_PIN 5 // ïèí äëÿ äàííûõ
#define LCD_DATA2_PIN 6 // ïèí äëÿ äàííûõ
#define LCD_DATA3_PIN 7 // ïèí äëÿ äàííûõ
#define LCD_RS_PIN 0 // ïèí ëèíèè RS
#define LCD_RW_PIN 1 // ïèí ëèíèè RW
#define LCD_E_PIN 2 // ïèí ëèíèè òàêòèðîâàíèÿ
#define LCD_LED_PIN 3 // ïèí ïîäñâåòêè
// Ïîçèöèè áèòîâ ðåãèñòðà êîìàíä HD44780U.
#define LCD_CLR 0 // îò÷èñòèòü äèñïëåé
#define LCD_HOME 1 // âåðíóòü êóðñîð äîìîé
#define LCD_ENTRY_MODE 2 // óñòàíîâêà ðåæèìà ââîäà
#define LCD_ENTRY_INC 1 // èíêðåìåíò
#define LCD_ENTRY_SHIFT 0 // âêë ñìåùåíèå
#define LCD_ON 3 // âêë êóðñîðà
#define LCD_ON_DISPLAY 2 // âûêë äèñïëåé
#define LCD_ON_CURSOR 1 // âûêë êóðñîð
#define LCD_ON_BLINK 0 // ìèãàíèå êóðñîðà
#define LCD_MOVE 4 // ïåðåäâèæåíèå êóðñîðà
#define LCD_MOVE_DISP 3 // ïåðåäâèæåíèå êóðñîðà
#define LCD_MOVE_RIGHT 2 // ïåðåäâèæåíèå êóðñîðà íàïðàâî
#define LCD_FUNCTION 5 // íàñòðîéêà ôóíêöèé
#define LCD_FUNCTION_8BIT 4 // 8 áèòíûé ðåæèì
#define LCD_FUNCTION_2LINES 3 // àêòèâàöèÿ ñòðîê
#define LCD_FUNCTION_10DOTS 2 // øðèôòû
#define LCD_CGRAM 6 // óñòàíîâêà àäðåñà CG RAM
#define LCD_DDRAM 7 // óñòàíîâêà àäðåñà DD RAM
#define LCD_BUSY 7 // äèñïëåé çàíÿò
// ñòàíäàðòíûé ðåæèì
#define LCD_MODE_DEFAULT ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
// èíèöèàëèçàöèÿ äèñïëåÿ
void lcd_init(uint8_t dispAttr);
// î÷èñòêà äèñïëåÿ
void lcd_clrscr(void);
// êóðñîâ â íà÷àëî êîîðäèíàò
void lcd_home(void);
// ïåðåìåùåíèå êóðñîðà ïî êîîðäèíàòàì
void lcd_gotoxy(uint8_t x, uint8_t y);
// âêë è îòêë ïîäñâåòêè
void lcd_led(uint8_t onoff);
// îòîáðàæåíèå ñèìâîëà â òåêóùåé ïîçèöèè êóðñîðà
void lcd_putc(char c);
// âûâîä ñòðîêè íà äèñïëåé
void lcd_puts(const char *s);
// âûâîä ñòðîêè èç ïàìÿòè
void lcd_puts_p(const char *progmem_s);
// ñëóæåáíàÿ ôóíêöèÿ äëÿ îòïðàâêè êîìàíä äèñïëåþ
void lcd_command(uint8_t cmd);
// îòïðàâêà áàéòà íà äèñïëåé
void lcd_data(uint8_t data);
// ìàêðîñû äëÿ àâòîìàòè÷åñêîãî ñîõðàíåíèÿ ñòðîêîâîé êîíñòàíòû â ïàìÿòè ïðîãðàììû
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
#endif
+115
View File
@@ -0,0 +1,115 @@
#include "MyLCD.h"
uint8_t pcf8574_pinstatus[PCF8574_MAXDEVICES];
// инициализация pcf
void pcf8574_init() {
#if PCF8574_I2CINIT == 1
// инитим i2c
i2c_init();
_delay_us(10);
#endif
uint8_t i = 0;
for(i=0; i<PCF8574_MAXDEVICES; i++)
pcf8574_pinstatus[i] = 0;
}
// получаем статус вывода
int8_t pcf8574_getoutput(uint8_t deviceid) {
int8_t data = -1;
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES)) {
data = pcf8574_pinstatus[deviceid];
}
return data;
}
// получаем статус пинов вывода
int8_t pcf8574_getoutputpin(uint8_t deviceid, uint8_t pin) {
int8_t data = -1;
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES) && (pin >= 0 && pin < PCF8574_MAXPINS)) {
data = pcf8574_pinstatus[deviceid];
data = (data >> pin) & 0b00000001;
}
return data;
}
// настройка вывода
int8_t pcf8574_setoutput(uint8_t deviceid, uint8_t data) {
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES)) {
pcf8574_pinstatus[deviceid] = data;
i2c_start(((PCF8574_ADDRBASE+deviceid)<<1) | I2C_WRITE);
i2c_write(data);
i2c_stop();
return 0;
}
return -1;
}
// установить выходные контакты, заменить фактический статус устройства из pinstart для i2c
int8_t pcf8574_setoutputpins(uint8_t deviceid, uint8_t pinstart, uint8_t pinlength, int8_t data) {
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES) && (pinstart - pinlength + 1 >= 0 && pinstart - pinlength + 1 >= 0 && pinstart < PCF8574_MAXPINS && pinstart > 0 && pinlength > 0)) {
uint8_t b = 0;
b = pcf8574_pinstatus[deviceid];
uint8_t mask = ((1 << pinlength) - 1) << (pinstart - pinlength + 1);
data <<= (pinstart - pinlength + 1);
data &= mask;
b &= ~(mask);
b |= data;
pcf8574_pinstatus[deviceid] = b;
//рестартим
i2c_start(((PCF8574_ADDRBASE+deviceid)<<1) | I2C_WRITE);
i2c_write(b);
i2c_stop();
return 0;
}
return -1;
}
// настройка пинов вывода
int8_t pcf8574_setoutputpin(uint8_t deviceid, uint8_t pin, uint8_t data) {
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES) && (pin >= 0 && pin < PCF8574_MAXPINS)) {
uint8_t b = 0;
b = pcf8574_pinstatus[deviceid];
b = (data != 0) ? (b | (1 << pin)) : (b & ~(1 << pin));
pcf8574_pinstatus[deviceid] = b;
//рестартим
i2c_start(((PCF8574_ADDRBASE+deviceid)<<1) | I2C_WRITE);
i2c_write(b);
i2c_stop();
return 0;
}
return -1;
}
// установка высокого уровня на выходных пинах
int8_t pcf8574_setoutputpinhigh(uint8_t deviceid, uint8_t pin) {
return pcf8574_setoutputpin(deviceid, pin, 1);
}
// установка низкого уровня на выходных пинах
int8_t pcf8574_setoutputpinlow(uint8_t deviceid, uint8_t pin) {
return pcf8574_setoutputpin(deviceid, pin, 0);
}
// получение входных данных
int8_t pcf8574_getinput(uint8_t deviceid) {
int8_t data = -1;
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES)) {
i2c_start(((PCF8574_ADDRBASE+deviceid)<<1) | I2C_READ);
data = ~i2c_readNak();
i2c_stop();
}
return data;
}
// получение входного контакта (высокий или низкий)
int8_t pcf8574_getinputpin(uint8_t deviceid, uint8_t pin) {
int8_t data = -1;
if((deviceid >= 0 && deviceid < PCF8574_MAXDEVICES) && (pin >= 0 && pin < PCF8574_MAXPINS)) {
data = pcf8574_getinput(deviceid);
if(data != -1) {
data = (data >> pin) & 0b00000001;
}
}
return data;
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef PCF8574_H_
#define PCF8574_H_
#define PCF8574_ADDRBASE (0x27) // àäðåñ óñò-âà
#define PCF8574_I2CINIT 1 // èíèöèàëèçàöèÿ i2c
#define PCF8574_MAXDEVICES 1 // ìàêñ êîë-âî óòðîéñòâ
#define PCF8574_MAXPINS 8 // ìàêñ êîë-âî ïèíîâ
void pcf8574_init();
int8_t pcf8574_getoutput(uint8_t deviceid);
int8_t pcf8574_getoutputpin(uint8_t deviceid, uint8_t pin);
int8_t pcf8574_setoutput(uint8_t deviceid, uint8_t data);
int8_t pcf8574_setoutputpins(uint8_t deviceid, uint8_t pinstart, uint8_t pinlength, int8_t data);
int8_t pcf8574_setoutputpin(uint8_t deviceid, uint8_t pin, uint8_t data);
int8_t pcf8574_setoutputpinhigh(uint8_t deviceid, uint8_t pin);
int8_t pcf8574_setoutputpinlow(uint8_t deviceid, uint8_t pin);
int8_t pcf8574_getinput(uint8_t deviceid);
int8_t pcf8574_getinputpin(uint8_t deviceid, uint8_t pin);
#endif
+117
View File
@@ -0,0 +1,117 @@
#include "MyLCD.h"
// инициализация интерфейса i2c
void i2c_init(void)
{
// предделитель тактовой частоты равен 1
TWSR = 0;
// рассчет скорости передачи данных
TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
}
// передача условия СТАРТ на шину
unsigned char i2c_start(unsigned char address)
{
uint8_t twst;
// отправка условия СТАРТ
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// ожидание завершения передачи условия СТАРТ
while(!(TWCR & (1<<TWINT)));
// проверка значений регистра
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
// отправка адреса устрой-ва
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// ожидание ответа от ведомого уст-ва
while(!(TWCR & (1<<TWINT)));
// проверка полученных значений
twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
return 0;
}
// ждем, если устрой-во занято, а потом передаем условие СТАРТ на шину
void i2c_start_wait(unsigned char address)
{
uint8_t twst;
for(;;)
{
// отправка условия СТАРТ
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// ожидание завершения передачи условия СТАРТ
while(!(TWCR & (1<<TWINT)));
// проверка значений регистра
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
// отправка адреса устрой-ва
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// ожидание ответа от ведомого уст-ва
while(!(TWCR & (1<<TWINT)));
// проверка занято ли ведомое уст-во
twst = TW_STATUS & 0xF8;
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
{
// устройство занято, отправьте условие остановки для прекращения операции записи
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// ждем освобождения шины
while(TWCR & (1<<TWSTO));
continue;
}
break;
}
}
// тупа повторяем условие СТАРТ
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start(address);
}
// передача условия СТОП на шину
void i2c_stop(void)
{
// отправка условия СТОП
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// ждем выполнения условия остановки
while(TWCR & (1<<TWSTO));
}
// отправка данных, если функция вернет 0, то все успешно, иначе нет
unsigned char i2c_write( unsigned char data )
{
uint8_t twst;
// отправляем данные на уст-во
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
// ждем завершения передачи
while(!(TWCR & (1<<TWINT)));
// записываем ответ от ведомого уст-ва
twst = TW_STATUS & 0xF8;
if( twst != TW_MT_DATA_ACK) return 1;
return 0;
}
// читаем данные и продолжаем вещание
unsigned char i2c_readAck(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
// читаем данные и после их получения передаем услови СТОП
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
+1 -1
View File
@@ -3,7 +3,7 @@
#include "circular_buf.h" #include "circular_buf.h"
void clear_buffer(struct circular_buffer* cb) { void initialize_buffer(struct circular_buffer* cb) {
cb->buf_head = 0; cb->buf_head = 0;
cb->buf_tail = 0; cb->buf_tail = 0;
} }
+1 -1
View File
@@ -9,7 +9,7 @@ struct circular_buffer{
unsigned char buf_tail; unsigned char buf_tail;
}; };
void clear_buffer(struct circular_buffer* cb); void initialize_buffer(struct circular_buffer* cb);
int buffer_empty(const struct circular_buffer* cb); int buffer_empty(const struct circular_buffer* cb);
int buffer_full(const struct circular_buffer* cb); int buffer_full(const struct circular_buffer* cb);
void write_buffer(struct circular_buffer* cb, int value); void write_buffer(struct circular_buffer* cb, int value);
+21
View File
@@ -0,0 +1,21 @@
#include <avr/io.h>
#include <avr/interrupt.h>
static volatile unsigned long timerMillis = 0;
void timerInit() {
TCCR1B |= (1 << WGM12) | (1 << CS11) | (1 << CS10);
OCR1A = 250;
TIMSK1 |= (1 << OCIE1A);
sei();
}
unsigned long millis() {
unsigned long ms;
ms = timerMillis;
return ms;
}
ISR(TIMER1_COMPA_vect) {
timerMillis++;
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef TIMER_H
#define TIMER_H
void timerInit();
unsigned long millis();
#endif // TIMER_H
+34 -33
View File
@@ -2,14 +2,12 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "timer.h"
#include "circular_buf.h" #include "circular_buf.h"
#include "uart.h" #include "uart.h"
struct circular_buffer uartRxBuffer;
struct circular_buffer uartTxBuffer;
void UART_init(void) { void UART_init(void) {
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1<<TXCIE0) | (1 << UDRIE0); // прерывание по приему и передаче UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << UDRIE0); // прерывание по приему и опустошению буфера передачи
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
UBRR0H = 0; UBRR0H = 0;
UBRR0L = 103; UBRR0L = 103;
@@ -17,47 +15,50 @@ void UART_init(void) {
void UART_send(uint8_t* data, size_t length) { void UART_send(uint8_t* data, size_t length) {
for (size_t i = 0; i < length; i++) { for (size_t i = 0; i < length; i++) {
if (!buffer_full(&uartTxBuffer)) { if (!buffer_full(&usartTxBuffer)) {
write_buffer(&uartTxBuffer, data[i]); write_buffer(&usartTxBuffer, data[i]);
} else { } else {
break; // если буфер передачи заполнен, то отправка прерывается break; // если буфер передачи заполнен, то отправка прерывается
} }
} }
UCSR0B |= (1 << TXCIE0); // включаем прерывание по завершении передачи UCSR0B |= (1 << UDRIE0); // Включаем прерывание по опустошению буфера
clear_buffer(&uartTxBuffer);
} }
// Получение данных из буфера // Получение данных из буфера
int UART_receive(uint8_t* data, size_t length) { int UART_receive(uint8_t* data, size_t length) {
char overflow = 0; // Флаг переполнения, который устанавливается, если превышен размер массива char overflow=0; // Флаг переполнения, который устанавливается, если превышен размер массива
uint32_t byteCount = 0; // Счетчик байтов, принятых из буфера приема uint32_t byteCount=0; // Счетчик байтов, принятых из буфера приема
// Пока буфер приема не пуст и не превышен лимит длины массива, uint32_t timeout_ms = 4; // Таймаут в миллисекундах для общего времени приема данных
// функция продолжает читать байты из буфера и сохранять их в массив data. uint32_t start_time = millis();
while (!buffer_empty(&uartRxBuffer) && byteCount < length) { //Цикл приема данных с таймаутом
int reader = read_buffer(&uartRxBuffer); // Прием и запись символа в переменную while(1)
data[byteCount] = reader; // Запись в массив с индексом byteCount {
byteCount++; // Пока буфер приема не пуст и не истек таймаут общего времени,
} // функция продолжает читать байты из буфера и сохранять их в массив data.
// Проверка переполнения while (!buffer_empty(&usartRxBuffer)) {
if (byteCount > length) { int reader = read_buffer(&usartRxBuffer);//прием и запись символа в переменную
overflow = 1; if(byteCount<=length){
} data[byteCount] = reader; // запись в массив с индексом byteCount
clear_buffer(&uartRxBuffer); }
return overflow ? -1 : byteCount; // Возвращает количество успешно принятых байт или -1 в случае переполнения else{
overflow=1;
}
byteCount++;
start_time = millis();
}
if ((millis() - start_time) > timeout_ms) { // если превышение времени в 4 ms
break;
}
}
return overflow?-1:byteCount; // возвращает количество успешно принятых байт или -1
} }
// прерывание по завершению приема // прерывание по завершению приема
ISR(USART_RX_vect) { ISR(USART_RX_vect) {
uint8_t data = UDR0; // читаем из регистра UDR0 uint8_t data = UDR0; // читаем из регистра UDR0
if (!buffer_full(&uartRxBuffer)) { if (!buffer_full(&usartRxBuffer)) {
write_buffer(&uartRxBuffer, data);// записываем символ в буфер приема write_buffer(&usartRxBuffer, data);// записываем символ в буфер приема
} }
} }
ISR(USART_TX_vect) {
if (!buffer_empty(&uartTxBuffer)) {
UDR0 = read_buffer(&uartTxBuffer);
} else {
UCSR0B &= ~(1 << TXCIE0); // отключаем прерывание, когда все данные отправлены
}
}
+5
View File
@@ -2,9 +2,14 @@
#define UART_H #define UART_H
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include "timer.h"
#include "circular_buf.h"
#define F_CPU 16000000 #define F_CPU 16000000
struct circular_buffer usartRxBuffer;
struct circular_buffer usartTxBuffer;
void UART_init(void); void UART_init(void);
void UART_send(uint8_t* data, size_t length); void UART_send(uint8_t* data, size_t length);
int UART_receive(uint8_t* data, size_t length); int UART_receive(uint8_t* data, size_t length);
+132
View File
@@ -0,0 +1,132 @@
#include "client.h"
#include "hdlc.h"
#include "stdio.h"
#define ERR_INVALID_DATA_SIZE -1
#define ERR_ALL_BUFFERS_FILL -2
#define ERR_INVALID_PARAMS -3
#define ERR_INVALID_STATE -4
#define ERR_FRAME_TIME_OUT -5
#define ERR_INVALID_SEQ_NUMBER_FRAME -6
#define ERR_TIMEOUT_ANSWER -7
#define SIZE_DATA_BUFFERS 64
int connecting_frame_timeout_bf;
void init_hdlc_client(struct Client* client, int connecting_frame_timeout){
client->state = IDLE_STATE;
client->connecting_frame_timeout = connecting_frame_timeout;
connecting_frame_timeout_bf = connecting_frame_timeout;
client->current_index_frame = 20;
// client->current_state_hdlc.control_escape = 0;
// client->current_state_hdlc.fcs = FCS_INIT_VALUE;
// client->current_state_hdlc.start_index = -1;
// client->current_state_hdlc.end_index = -1;
// client->current_state_hdlc.src_index = 0;
// client->current_state_hdlc.dest_index = 0;
}
void hdlc_connect(struct Client* client){
client->state = CONNECTING;
client->frameS.seq_no = 0;
client->frameS.frame = S_FRAME;
client->current_index_frame = client->frameS.seq_no;
}
int hdlc_send_data(struct Client* client, uint8_t* data, size_t data_len){
if (client->state != READY_STATE){
return ERR_INVALID_STATE;
}
client->state = RECIVING;
if (SIZE_DATA_BUFFERS < data_len){
return ERR_INVALID_DATA_SIZE;
}
client->frameI.seq_no = 0;
client->frameI.frame = I_FRAME;
client->data_i_frame = *data;
client->len_data_i_frame = data_len;
client->current_index_frame = client->frameI.seq_no;
client->state = RECIVING;
return 0;
}
int hdlc_get_raw_frame(struct Client *client, uint8_t* buffer, size_t lenBuffer) {
if(client->state == RECIVING){
int ret = hdlc_frame_data(client->frameI, &client->data_i_frame,
client->len_data_i_frame, buffer, &lenBuffer);
if (ret < 0){
printf("err in get_frame: %d\n", ret);
}
}
if (client->state == CONNECTING){
int ret = hdlc_frame_data(client->frameS, NULL, 0, buffer, &lenBuffer);
if (ret < 0){
printf("err in get_frame: %d\n", ret);
}
}
if (client->state == DISCONNECTING){
int ret = hdlc_frame_data(client->frame_rej, NULL, 0, buffer, &lenBuffer);
if (ret < 0){
printf("err in get_frame: %d\n", ret);
}
}
return 0;
}
int hdlc_decode_recived_raw_data(struct Client* client, uint8_t* buffer, size_t len_buffer, uint8_t* recived_data, size_t* len_recived_data){
hdlc_control_t recv_control;
uint8_t recive[len_buffer];
int ret = hdlc_get_data(&recv_control, buffer, len_buffer, &recive,
&len_buffer);
if (ret < 0) {
return ret;
}
if (recv_control.seq_no != client->current_index_frame){
client->state = DISCONNECTING;
client->frame_rej.seq_no = 0;
client->frame_rej.frame = S_FRAME_NACK;
return ERR_INVALID_SEQ_NUMBER_FRAME;
}
switch (recv_control.frame) {
case S_FRAME:
client->state = READY_STATE;
break;
case I_FRAME:
*recived_data = buffer[3];
*len_recived_data = sizeof(buffer[3]);
break;
case S_FRAME_NACK:
client->state = DISCONNECTING;
client->frame_rej.seq_no = 0;
client->frame_rej.frame = S_FRAME_NACK;
return ERR_INVALID_SEQ_NUMBER_FRAME;
}
client->connecting_frame_timeout = connecting_frame_timeout_bf;
return 0;
}
int hdlc_timeout_handler(struct Client* client, int delta_time){
client->connecting_frame_timeout -= delta_time;
if (client->connecting_frame_timeout <= 0){
return ERR_FRAME_TIME_OUT;
}
return 0;
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef CLIENT_H
#define CLIENT_H
#include <stdint.h>
#include <stdbool.h>
#include "hdlc.h"
enum HDLCState {
UNINITIALIZED_STATE = 0, // состояние до инцилизации
IDLE_STATE, // Состояние ожидания начала
READY_STATE, // Состояние принятия
CONNECTING, // состояние соединения
DISCONNECTING, // состояния отключения
RECIVING // состояние приема и отправки
};
struct Client{
enum HDLCState state;
int connecting_frame_timeout; //-1
uint8_t current_index_frame;
//hdlc_state_t current_state_hdlc;
hdlc_control_t frameS;
hdlc_control_t frameI;
uint8_t data_i_frame;
size_t len_data_i_frame;
// hdlc_control_t frame3;
// hdlc_control_t frame4;
hdlc_control_t frame_rej;
};
//название функций
void init_hdlc_client(struct Client* client, int connecting_frame_timeout);
void hdlc_connect(struct Client* client);
int hdlc_send_data(struct Client* client, uint8_t* data, size_t data_len);
int hdlc_get_raw_frame(struct Client *client, uint8_t* buffer, size_t lenBuffer);
//принимает буффер с уарта
int hdlc_decode_recived_raw_data(struct Client* client, uint8_t* buffer, size_t len_buffer, uint8_t* recived_data, size_t* len_recived_data);
int hdlc_timeout_handler(struct Client* client, int delta_time);
#endif //CLIENT_H
+41
View File
@@ -0,0 +1,41 @@
#include "fcs.h"
/*
* CRC-Type: CRC16 CCIT
* Polynomial: 0x1021 (x^16+x^12+x^5+1)
* Lookup Table: Reflected
*/
static const unsigned short fcstab[256] = {
0x0000, 0x1189, 0x2312, 0x329b,
0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c,
0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c,
0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff,
0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183,
0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42,
0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116,
0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7,
0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1,
0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960,
0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630,
0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf,
0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581,
0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52,
0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612,
0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5,
0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7,
0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74,
0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c,
0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd,
0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f,
0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e,
0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a,
0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb,
0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9,
0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 };
FCS_SIZE calc_fcs(FCS_SIZE fcs, unsigned char value) {
return (fcs >> 8) ^ fcstab[(fcs ^ value) & 0xff];
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef FCS_H
#define FCS_H
#define FCS_INIT_VALUE 0xFFFF /* FCS initialization value. */
#define FCS_GOOD_VALUE 0xF0B8 /* FCS value for valid frames. */
#define FCS_INVERT_MASK 0xFFFF /* Invert the FCS value accordingly to the specification */
#define FCS_SIZE unsigned short
/**
* Calculates a new FCS based on the current value and value of data.
*
* @param fcs Current FCS value
* @param value The value to be added
* @returns Calculated FCS value
*/
FCS_SIZE calc_fcs(FCS_SIZE fcs, unsigned char value);
#endif
+261
View File
@@ -0,0 +1,261 @@
#include "hdlc.h"
// HDLC Control field bit positions
#define HDLC_CONTROL_S_OR_U_FRAME_BIT 0
#define HDLC_CONTROL_SEND_SEQ_NO_BIT 1
#define HDLC_CONTROL_S_FRAME_TYPE_BIT 2
#define HDLC_CONTROL_POLL_BIT 4
#define HDLC_CONTROL_RECV_SEQ_NO_BIT 5
// HDLC Control type definitions
#define HDLC_CONTROL_TYPE_RECEIVE_READY 0
#define HDLC_CONTROL_TYPE_RECEIVE_NOT_READY 1
#define HDLC_CONTROL_TYPE_REJECT 2
#define HDLC_CONTROL_TYPE_SELECTIVE_REJECT 3
static hdlc_state_t hdlc_state = {
.control_escape = 0,
.fcs = FCS_INIT_VALUE,
.start_index = -1,
.end_index = -1,
.src_index = 0,
.dest_index = 0,
};
int hdlc_set_state(hdlc_state_t *state) {
if (!state) {
return -EINVAL;
}
hdlc_state = *state;
return 0;
}
int hdlc_get_state(hdlc_state_t *state) {
if (!state) {
return -EINVAL;
}
*state = hdlc_state;
return 0;
}
void hdlc_escape_value(char value, char *dest, int *dest_index) {
// Check and escape the value if needed
if ((value == HDLC_FLAG_SEQUENCE) || (value == HDLC_CONTROL_ESCAPE)) {
dest[(*dest_index)++] = HDLC_CONTROL_ESCAPE;
value ^= 0x20;
}
// Add the value to the destination buffer and increment destination index
dest[(*dest_index)++] = value;
}
hdlc_control_t hdlc_get_control_type(unsigned char control) {
hdlc_control_t value;
// Check if the frame is a S-frame (or U-frame)
if (control & (1 << HDLC_CONTROL_S_OR_U_FRAME_BIT)) {
// Check if S-frame type is a Receive Ready (ACK)
if (((control >> HDLC_CONTROL_S_FRAME_TYPE_BIT) & 0x3)
== HDLC_CONTROL_TYPE_RECEIVE_READY) {
value.frame = S_FRAME;
} else {
// Assume it is an NACK since Receive Not Ready, Selective Reject and U-frames are not supported
value.frame = S_FRAME_NACK;
}
// Add the receive sequence number from the S-frame (or U-frame)
value.seq_no = (control >> HDLC_CONTROL_RECV_SEQ_NO_BIT);
} else {
// It must be an I-frame so add the send sequence number (receive sequence number is not used)
value.frame = I_FRAME;
value.seq_no = (control >> HDLC_CONTROL_SEND_SEQ_NO_BIT);
}
return value;
}
unsigned char hdlc_frame_control_type(hdlc_control_t *control) {
unsigned char value = 0;
switch (control->frame) {
case I_FRAME:
// Create the HDLC I-frame control byte with Poll bit set
value |= (control->seq_no << HDLC_CONTROL_SEND_SEQ_NO_BIT);
value |= (1 << HDLC_CONTROL_POLL_BIT);
break;
case S_FRAME:
// Create the HDLC Receive Ready S-frame control byte with Poll bit cleared
value |= (control->seq_no << HDLC_CONTROL_RECV_SEQ_NO_BIT);
value |= (1 << HDLC_CONTROL_S_OR_U_FRAME_BIT);
break;
case S_FRAME_NACK:
// Create the HDLC Receive Ready S-frame control byte with Poll bit cleared
value |= (control->seq_no << HDLC_CONTROL_RECV_SEQ_NO_BIT);
value |= (HDLC_CONTROL_TYPE_REJECT << HDLC_CONTROL_S_FRAME_TYPE_BIT);
value |= (1 << HDLC_CONTROL_S_OR_U_FRAME_BIT);
break;
}
return value;
}
void hdlc_get_data_reset() {
hdlc_get_data_reset_with_state(&hdlc_state);
}
void hdlc_get_data_reset_with_state(hdlc_state_t *state) {
state->fcs = FCS_INIT_VALUE;
state->start_index = state->end_index = -1;
state->src_index = state->dest_index = 0;
state->control_escape = 0;
}
//int hdlc_get_data(hdlc_control_t *control, const char *src,
// unsigned int src_len, char *dest, unsigned int *dest_len)
int hdlc_get_data(hdlc_control_t *control, uint8_t *src,
size_t src_len, uint8_t *dest, size_t *dest_len){
return hdlc_get_data_with_state(&hdlc_state, control, src, src_len, dest, dest_len);
}
//int hdlc_get_data_with_state(hdlc_state_t *state, hdlc_control_t *control, const char *src,
// unsigned int src_len, char *dest, unsigned int *dest_len)
int hdlc_get_data_with_state(hdlc_state_t *state, hdlc_control_t *control, uint8_t *src,
size_t src_len, uint8_t *dest, size_t *dest_len){
int ret;
char value;
unsigned int i;
// Make sure that all parameters are valid
if (!state || !control || !src || !dest || !dest_len) {
return -EINVAL;
}
// Run through the data bytes
for (i = 0; i < src_len; i++) {
// First find the start flag sequence
if (state->start_index < 0) {
if (src[i] == HDLC_FLAG_SEQUENCE) {
// Check if an additional flag sequence byte is present
if ((i < (src_len - 1)) && (src[i + 1] == HDLC_FLAG_SEQUENCE)) {
// Just loop again to silently discard it (accordingly to HDLC)
continue;
}
state->start_index = state->src_index;
}
} else {
// Check for end flag sequence
if (src[i] == HDLC_FLAG_SEQUENCE) {
// Check if an additional flag sequence byte is present or earlier received
if (((i < (src_len - 1)) && (src[i + 1] == HDLC_FLAG_SEQUENCE))
|| ((state->start_index + 1) == state->src_index)) {
// Just loop again to silently discard it (accordingly to HDLC)
continue;
}
state->end_index = state->src_index;
break;
} else if (src[i] == HDLC_CONTROL_ESCAPE) {
state->control_escape = 1;
} else {
// Update the value based on any control escape received
if (state->control_escape) {
state->control_escape = 0;
value = src[i] ^ 0x20;
} else {
value = src[i];
}
// Now update the FCS value
state->fcs = calc_fcs(state->fcs, value);
if (state->src_index == state->start_index + 2) {
// Control field is the second byte after the start flag sequence
*control = hdlc_get_control_type(value);
} else if (state->src_index > (state->start_index + 2)) {
// Start adding the data values after the Control field to the buffer
dest[state->dest_index++] = value;
}
}
}
state->src_index++;
}
// Check for invalid frame (no start or end flag sequence)
if ((state->start_index < 0) || (state->end_index < 0)) {
// Return no message and make sure destination length is 0
*dest_len = 0;
ret = -ENOMSG;
} else {
// A frame is at least 4 bytes in size and has a valid FCS value
if ((state->end_index < (state->start_index + 4))
|| (state->fcs != FCS_GOOD_VALUE)) {
// Return FCS error and indicate that data up to end flag sequence in buffer should be discarded
*dest_len = i;
ret = -EIO;
} else {
// Return success and indicate that data up to end flag sequence in buffer should be discarded
*dest_len = state->dest_index - sizeof(state->fcs);
ret = i;
}
// Reset values for next frame
hdlc_get_data_reset_with_state(state);
}
return ret;
}
//int hdlc_frame_data(hdlc_control_t *control, const char *src,
// unsigned int src_len, char *dest, unsigned int *dest_len)
int hdlc_frame_data(hdlc_control_t *control, uint8_t *src,
size_t src_len, uint8_t *dest, size_t *dest_len){
unsigned int i;
int dest_index = 0;
unsigned char value = 0;
FCS_SIZE fcs = FCS_INIT_VALUE;
// Make sure that all parameters are valid
if (!control || (!src && (src_len > 0)) || !dest || !dest_len) {
return -EINVAL;
}
// Start by adding the start flag sequence
dest[dest_index++] = HDLC_FLAG_SEQUENCE;
// Add the all-station address from HDLC (broadcast)
fcs = calc_fcs(fcs, HDLC_ALL_STATION_ADDR);
hdlc_escape_value(HDLC_ALL_STATION_ADDR, dest, &dest_index);
// Add the framed control field value
value = hdlc_frame_control_type(control);
fcs = calc_fcs(fcs, value);
hdlc_escape_value(value, dest, &dest_index);
// Only DATA frames should contain data
if (control->frame == I_FRAME) {
// Calculate FCS and escape data
for (i = 0; i < src_len; i++) {
fcs = calc_fcs(fcs, src[i]);
hdlc_escape_value(src[i], dest, &dest_index);
}
}
// Invert the FCS value accordingly to the specification
fcs ^= FCS_INVERT_MASK;
// Run through the FCS bytes and escape the values
for (i = 0; i < sizeof(fcs); i++) {
value = ((fcs >> (8 * i)) & 0xFF);
hdlc_escape_value(value, dest, &dest_index);
}
// Add end flag sequence and update length of frame
dest[dest_index++] = HDLC_FLAG_SEQUENCE;
*dest_len = dest_index;
return 0;
}
+108
View File
@@ -0,0 +1,108 @@
//
// Created by 79513 on 15.12.2023.
//
#ifndef HDLC_H
#define HDLC_H
#include "fcs.h"
#include <errno.h>
#include "stdint.h"
/** HDLC start/end flag sequence */
#define HDLC_FLAG_SEQUENCE 0x7E
/** HDLC control escape value */
#define HDLC_CONTROL_ESCAPE 0x7D
/** HDLC all station address */
#define HDLC_ALL_STATION_ADDR 0xFF
/** Supported HDLC frame types */
typedef enum {
I_FRAME,
S_FRAME,
S_FRAME_NACK,
} hdlc_frame_t;
/** Control field information */
typedef struct {
hdlc_frame_t frame;
unsigned char seq_no :3;
} hdlc_control_t;
/** Variables used in hdlc_get_data and hdlc_get_data_with_state
* to keep track of received buffers
*/
typedef struct {
char control_escape;
FCS_SIZE fcs;
int start_index;
int end_index;
int src_index;
int dest_index;
} hdlc_state_t;
/**
* Retrieves data from specified buffer containing the HDLC frame. Frames can be
* parsed from multiple buffers e.g. when received via UART.
*
* @param[out] control Control field structure with frame type and sequence number
* @param[in] src Source buffer with frame
* @param[in] src_len Source buffer length
* @param[out] dest Destination buffer (should be able to contain max frame size)
* @param[out] dest_len Destination buffer length
* @retval >=0 Success (size of returned value should be discarded from source buffer)
* @retval -EINVAL Invalid parameter
* @retval -ENOMSG Invalid message
* @retval -EIO Invalid FCS (size of dest_len should be discarded from source buffer)
*
* @see hdlc_get_data_with_state
*/
int hdlc_get_data(hdlc_control_t *control, uint8_t *src,
size_t src_len, uint8_t *dest, size_t *dest_len);
/**
* Retrieves data from specified buffer containing the HDLC frame. Frames can be
* parsed from multiple buffers e.g. when received via UART.
*
* This function is a variation of @ref hdlc_get_data
* The difference is only in first argument: hdlc_state_t *state
* Data under that pointer is used to keep track of internal buffers.
*
* @see hdlc_get_data
*/
int hdlc_get_data_with_state(hdlc_state_t *state, hdlc_control_t *control, uint8_t *src,
size_t src_len, uint8_t *dest, size_t *dest_len);
/**
* Resets values used in yahdlc_get_data function to keep track of received buffers
*/
void hdlc_get_data_reset();
/**
* This is a variation of @ref hdlc_get_data_reset
* Resets state values that are under the pointer provided as argument
*
* This function need to be called before the first call to hdlc_get_data_with_state
* when custom state storage is used.
*
* @see hdlc_get_data_reset
*/
void hdlc_get_data_reset_with_state(hdlc_state_t *state);
/**
* Creates HDLC frame with specified data buffer.
*
* @param[in] control Control field structure with frame type and sequence number
* @param[in] src Source buffer with data
* @param[in] src_len Source buffer length
* @param[out] dest Destination buffer (should be bigger than source buffer)
* @param[out] dest_len Destination buffer length
* @retval 0 Success
* @retval -EINVAL Invalid parameter
*/
int hdlc_frame_data(hdlc_control_t *control, uint8_t *src,
size_t src_len, uint8_t *dest, size_t *dest_len);
#endif //HDLC_H
+183
View File
@@ -0,0 +1,183 @@
//#include "hdlc.h"
#include "client.h"
int main(){
struct Client hdlc;
init_hdlc_client(&hdlc, 200);
hdlc_control_t frame;
hdlc_connect(&hdlc, &frame);
uint8_t buffer_for_ex[20];
uint8_t fake_buffer;
hdlc_get_raw_frame(&hdlc, &frame, &buffer_for_ex, sizeof(buffer_for_ex));
for (int i = 0; i < 200; i++){
int z = hdlc_timeout_handler(&hdlc, 1);
hdlc_decode_recived_raw_data(&hdlc, &fake_buffer, sizeof(fake_buffer), 0, 0);
}
hdlc_get_raw_frame(&hdlc, &frame, &buffer_for_ex, sizeof(buffer_for_ex));
int i = hdlc_decode_recived_raw_data(&hdlc, &buffer_for_ex, sizeof(buffer_for_ex), 0, 0);
if (i < 0){
printf("err connect: %d\n", i);
}
hdlc_control_t frame_data;
uint8_t data = 33;
hdlc_send_data(&hdlc, &frame_data, &data, sizeof(data));
uint8_t buffer_for_ex_data[7];
hdlc_get_raw_frame(&hdlc, &frame_data, &buffer_for_ex_data, sizeof(buffer_for_ex_data));
//printf("first_ex:%d\n", buffer_for_ex_data[0]);
uint8_t recived_data;
size_t len_recived_data;
int x = hdlc_decode_recived_raw_data(&hdlc, &buffer_for_ex_data, sizeof(buffer_for_ex_data), &recived_data, &len_recived_data);
if (x < 0){
printf("err send: %d\n", x);
}
printf("recived data: %d\n", recived_data);
// uint8_t send[64];
// uint8_t buffer[134];
// for (int i = 0; i < sizeof(send); i++) {
// send[i] = (uint8_t) (rand() % 0x70);
// }
// send_data(&hdlc, send, sizeof(send_data));
// //get_frame(&hdlc, buffer, sizeof(buffer), send_data, sizeof(send_data));
//
// hdlc_get_raw_data(&hdlc, buffer, sizeof(buffer));
// test 1
// int ret;
// uint8_t frame_data[8], recv_data[8];
// size_t i, frame_length = 0, recv_length = 0;
// hdlc_control_t control_send, control_recv;
// // Run through the supported sequence numbers (3-bit)
// for (i = 0; i <= 7; i++) {
// // Initialize the control field structure with frame type and sequence number
// control_send.frame = HDLC_FRAME_ACK;
// control_send.seq_no = i;
//
// // Create an empty frame with the control field information
// ret = hdlc_frame_data(&control_send, NULL, 0, frame_data, &frame_length);
//
// // Get the data from the frame
// ret = hdlc_get_data(&control_recv, frame_data, frame_length, recv_data,
// &recv_length);
//
// // Result should be frame_length minus start flag to be discarded and no bytes received
// if(ret != (int )frame_length - 1){
// printf("err");
// }
// }
// if (recv_length != 0){
// printf("err2");
// }
//
// if (control_send.frame != control_recv.frame){
// printf("err3");
// }
//
// if (control_send.seq_no != control_recv.seq_no){
// printf("err4");
// }
// test 2
// Run through the supported sequence numbers (3-bit)
// for (i = 0; i <= 7; i++) {
// // Initialize the control field structure with frame type and sequence number
// control_send.frame = HDLC_FRAME_DATA;
// control_send.seq_no = i;
//
// char* input = "311";
// uint8_t data = (uint8_t)atoi(input);
//
// // Create an empty frame with the control field information
// ret = hdlc_frame_data(&control_send, &data, 3, frame_data, &frame_length);
// if (ret != 0){
// printf("err123\n");
// }
//
// // Get the data from the frame
// ret = hdlc_get_data(&control_recv, frame_data, frame_length, recv_data,
// &recv_length);
//
// // Result should be frame_length minus start flag to be discarded and no bytes received
// if(ret != (int )frame_length - 1){
// printf("err333\n");
// }
// if (recv_length != 0){
// printf("err2\n");
// }
//
// // Verify the control field information
// if (control_send.frame != control_recv.frame){
// printf("err3\n");
// }
//
// if (control_send.seq_no != control_recv.seq_no){
// printf("err4\n");
// }
// }
// int ret;
// hdlc_control_t control;
// uint8_t send_data[512], frame_data[530], recv_data[530];
// size_t i, frame_length = 0, recv_length = 0, buf_length = 16;
//
// // Initialize data to be send with random values (up to 0x70 to keep below the values to be escaped)
// for (i = 0; i < sizeof(send_data); i++) {
// send_data[i] = (uint8_t) (rand() % 0x70);
// }
//
// // Initialize control field structure and create frame
// control.frame = HDLC_FRAME_DATA;
// ret = hdlc_frame_data(&control, send_data, sizeof(send_data), frame_data,
// &frame_length);
//
// // Check that frame length is maximum 2 bytes larger than data due to escape of FCS value
// if(frame_length >= ((sizeof(send_data) + 6) + 2)){
// printf("1");
// }
// if(ret != 0){
// printf("2");
// }
//
// // Run though the different buffers (simulating decode of buffers from UART)
// for (i = 0; i <= sizeof(send_data); i += buf_length) {
// // Decode the data
// ret = hdlc_get_data(&control, &frame_data[i], buf_length, recv_data,
// &recv_length);
//
// printf("%zu: %s\n", i, recv_data);
//
// if (i < sizeof(send_data)) {
// // All chunks until the last should return no message and zero length
// if (ret != -ENOMSG){
// printf("3");
// }
// if (recv_length != 0){
// printf("1231");
// }
// } else {
// if (ret > 7){
// printf("332");
// }
// if (recv_length != sizeof(send_data)){
// printf("88888");
// }
// // The last chunk should return max 6 frame bytes - 1 start flag sequence byte + 2 byte for the possible
// // escaped FCS = 7 bytes
//// BOOST_CHECK(ret <= 7);
//// BOOST_CHECK_EQUAL(recv_length, sizeof(send_data));
// //printf("5");
// }
// }
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef Lcd_print_h
#define Lcd_print_h
#include <Arduino.h>
void Lcd_inciliation();
void printLcd(const char* inputText);
#endif
+72
View File
@@ -0,0 +1,72 @@
#include "lcd.h"
#include "client.h"
#include "uart.h"
#include "stdbool.h"
#include "stdio.h"
struct Client hdlc;
bool flag_connection = false;
void setup() {
Lsd_inciliation();
UART_init();
init_hdlc_client(&hdlc, 200);
}
void loop() {
if (!flag_connection){
hdlc_connect(&hdlc);
uint8_t buffer;
hdlc_get_raw_frame(&hdlc, &buffer, sizeof(buffer));
UART_send(&buffer, sizeof(buffer));
bool flag_recive = true;
while(flag_recive){
uint8_t buffer;
UART_receive(&buffer, sizeof(buffer));
int err = hdlc_timeout_handler(&hdlc, 1);
if (err != 0){
return err;
}
int ret = hdlc_decode_recived_raw_data(&hdlc, &fake_buffer, sizeof(fake_buffer), 0, 0);
if (ret == -6){
uint8_t buffer;
hdlc_get_raw_frame(&hdlc, &hdlc->frame_rej, &buffer, sizeof(buffer));
UART_send(&buffer, sizeof(buffer));
}
if (ret == 0 && client->state == READY_STATE){
flag_connection = true;
}
}
} else {
bool flag_recive = true;
while(flag_recive){
uint8_t buffer;
UART_receive(&buffer, sizeof(buffer));
int err = hdlc_timeout_handler(&hdlc, 1);
if (err != 0){
return err;
}
uint8_t recived_data;
size_t len_recived_data;
int ret = hdlc_decode_recived_raw_data(&hdlc, &fake_buffer, sizeof(fake_buffer), &recived_data, &len_recived_data);
if (ret == -6){
uint8_t buffer;
hdlc_get_raw_frame(&hdlc, &hdlc->frame_rej, &buffer, sizeof(buffer));
UART_send(&buffer, sizeof(buffer));
}
printLsd(recived_data);
}
}
}