initial commit

This commit is contained in:
Jonathan Roth 2026-03-09 15:08:40 +01:00
commit 41cf57e7d3
17 changed files with 775 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build/
MPLABXLog.xml

57
Makefile Normal file
View File

@ -0,0 +1,57 @@
# ─────────────────────────────────────────────
# Makefile — fdr1-modbus-slave
# Cible : PIC18F4431
# Compilateur : XC8
# ─────────────────────────────────────────────
# Projet
PROJECT = fdr1-modbus-slave
MCU = 18F4431
# Outils
CC = xc8-cc
IPECMD = java -jar /opt/microchip/mplabx/v6.20/mplab_platform/mplab_ipe/ipecmd.jar
# -OK
# Répertoires
SRC_DIR = src
INC_DIR = includes
BUILD_DIR = build
# Flags
DFP = /opt/microchip/mplabx/v6.20/packs/Microchip/PIC18Fxxxx_DFP/1.6.159/xc8
CFLAGS = -mcpu=$(MCU)
CFLAGS += -mdfp=$(DFP)
CFLAGS += -I$(INC_DIR)
CFLAGS += -O2
CFLAGS += -maddrqual=ignore
CFLAGS += -Wl,-Map=$(BUILD_DIR)/$(PROJECT).map
# Sources
SRCS = $(wildcard $(SRC_DIR)/*.c)
# Cible principale
HEX = $(BUILD_DIR)/$(PROJECT).hex
# ─────────────────────────────────────────────
.PHONY: all clean flash
all: $(BUILD_DIR) $(HEX)
# Création du répertoire build si absent
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
# Compilation + link en une seule passe XC8
$(HEX): $(SRCS)
$(CC) $(CFLAGS) $(SRCS) -o $(HEX)
# Flash via PICkit3
flash: $(HEX)
$(IPECMD) -TPPK3 -P$(MCU) -F$(HEX) -M -OL
# Nettoyage
clean:
rm -rf $(BUILD_DIR)

76
README.md Normal file
View File

@ -0,0 +1,76 @@
# fdr1-modbus-slave
Firmware Modbus RTU esclave pour encodeur incrémental, conçu pour tourner sur la carte **FDR1 v1.00**.
Le PIC lit la position du codeur QEI et la met à disposition d'un maître Modbus RTU (OpenPLC ou autre) via liaison série RS232/RS485.
---
## Matériel requis
- Carte **FDR1 v1.00**
- Microcontrôleur **PIC18F4431**
- Quartz **8 MHz** (HSPLL x4 → Fosc = 32 MHz)
- Encodeur incrémental raccordé au périphérique QEI
- Liaison série RS232 (RS485 à venir)
---
## Configuration Modbus RTU
| Paramètre | Valeur |
|------------------|------------|
| Adresse esclave | 183 |
| Vitesse | 115200 bps |
| Format | 8N1 |
| Function code | FC03 |
### Registres
| Adresse | Nom | Type | Accès | Description |
|----------|-----------|--------|-------|-----------------|
| `0x1700` | HR0 | UINT16 | R | Position QEI |
---
## Build & Flash
### Prérequis
- XC8 (dans le PATH)
- MPLABX v6.20 avec DFP PIC18Fxxxx installé
- PICkit3
### Compilation
```bash
make
```
### Flashage
```bash
make flash
```
### Nettoyage
```bash
make clean
```
---
## Licence
Copyright (c) 2026, FDR1 Project
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software must display the following acknowledgement: *This product includes software developed by the FDR1 Project.*
4. Neither the name of the FDR1 Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.

70
includes/config.h Normal file
View File

@ -0,0 +1,70 @@
/*
* File: config.h
* Author: JR
*
* Created on May 6, 2024, 2:50 PM
*
* All configurable parameters are defined here
*
*/
#ifndef CONFIG_H
#define CONFIG_H
// MCU frequency
#define FOSC 32000000 // 8MHz crystal *4 (PLL) = 32MHz
#define _XTAL_FREQ FOSC
#endif
#include "sysconfig.h"
/* Pin Mapping:
*
* Port #4 #2 Func Wire to
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* RA0 2 2 RLD Red LED (limits out of range)
* RA1 3 3 BLD Blue LED (activity)
* RA2 3 4 GLD Green LED (speed)
* RA3 5 5 QEA QEA
* RA4 6 6 QEB QEB
* RA5 7 XX Qenable (reserved/unused)
* RA6 14 10 O Rotation out
* RA7 13 XX
* RB0 33 21 Carriage Step
* RB1 34 22 O Motor Step
* RB2 35 23 Carriage Dir
* RB3 36 24 O Motor Dir
* RB4 37 25 O Motor Enable
* RB5 38 26 P PGM
* RB6 39 27 P PGC
* RB7 40 28 P PGD
* RC0 15 11 Carriage Enable
* RC1 16 12 O DialReq
* RC2 17 13 I DialData
* RC3 18 14 INT0 DialClk
* RC4 23 15 INT1 Btn_Reset_Dist
* RC5 24 16 INT2 Btn_Reset_Limits
* RC6 25 17 TX RS232 TX
* RC7 26 18 RX RS232 RX
* RD0 19 XX
* RD1 20 XX
* RD2 21 XX
* RD3 22 XX
* RD4 27 XX
* RD5 28 XX
* RD6 29 XX
* RD7 30 XX
* RE0 8 XX
* RE1 9 XX
* RE2 10 XX
* RE3 1 1 P VPP
*
*
* Peripherals:
* QEI: 16 bit Motion Feedback (IC+QEI)
* Timer0: 16 bit
* Timer1: 16 bit
* Timer2: 8 bit RTC ?
* Timer5: 16 bit Motor rotation control / Next: Reserved: Velocity measure
*/

13
includes/macros.h Normal file
View File

@ -0,0 +1,13 @@
#include <xc.h>
#ifndef __MACROS_H__
#define __MACROS_H__
#define RED(STATE) {LATDbits.LD0 = STATE;}
#define GREEN(STATE) {LATDbits.LD2 = STATE;}
#define BLUE(STATE) {LATDbits.LD1 = STATE;}
#define RED_TGL() {LATDbits.LD0 = !LATDbits.LD0;}
#define GREEN_TGL() {LATDbits.LD2 = !LATDbits.LD2;}
#define BLUE_TGL() {LATDbits.LD1 = !LATDbits.LD1;}
#endif //__MACROS_H__

9
includes/qei.h Normal file
View File

@ -0,0 +1,9 @@
#include <xc.h>
#ifndef __FDR1_QEI__
#define __FDR1_QEI__
void QEI_Init(void);
uint16_t QEI_ReadPosition(void);
#endif //__FDR1_QEI__

40
includes/rtu.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef RTU_H
#define RTU_H
#include <xc.h>
#include <stdint.h>
// ─────────────────────────────────────────────
// Configuration Modbus RTU
// ─────────────────────────────────────────────
#define RTU_SLAVE_ADDR 0xB7
#define RTU_FC03 0x03
#define RTU_HR0_ADDR 0x1700 // Position QEI
// ─────────────────────────────────────────────
// Timer2 — timeout inter-caractère 3.5×
// ≈ 304 µs @ 115200 bps
// prescaler 1:16, PR2 = 151
// ─────────────────────────────────────────────
#define RTU_TIMER_PRESCALER 16
#define RTU_TIMER_PR2 151
// ─────────────────────────────────────────────
// Buffer
// ─────────────────────────────────────────────
#define RTU_BUF_SIZE 32
// ─────────────────────────────────────────────
// API publique
// ─────────────────────────────────────────────
void RTU_Init(void);
void RTU_RxISR(void); // ISR UART RX haute priorité
void RTU_TimerISR(void); // ISR Timer2 basse priorité
void RTU_Task(void); // boucle principale
#endif // RTU_H

9
includes/setup.h Normal file
View File

@ -0,0 +1,9 @@
#include <xc.h>
#ifndef __FDR1_SETUP__
#define __FDR1_SETUP__
void setup(void);
void setup_gpio(void);
#endif //__FDR1_SETUP__

68
includes/sysconfig.h Normal file
View File

@ -0,0 +1,68 @@
/*
* File: sysconfig.h
* Author: JR
*
* Created on May 6, 2024, 2:50 PM
*/
// CONFIG1H
#pragma config OSC = HSPLL
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = ON // Internal External Oscillator Switchover bit (Internal External Switchover mode enabled)
// CONFIG2L
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset enabled)
#pragma config BORV = 42 // Brown Out Reset Voltage bits (VBOR set to 4.2V)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
#pragma config WINEN = OFF // Watchdog Timer Window Enable bit (WDT window disabled)
// CONFIG3L
#pragma config PWMPIN = OFF // PWM output pins Reset state control (PWM outputs disabled upon Reset (default))
#pragma config LPOL = HIGH // Low-Side Transistors Polarity (PWM0, 2, 4 and 6 are active-high)
#pragma config HPOL = HIGH // High-Side Transistors Polarity (PWM1, 3, 5 and 7 are active-high)
#pragma config T1OSCMX = ON // Timer1 Oscillator MUX (Low-power Timer1 operation when microcontroller is in Sleep mode)
// CONFIG3H
#pragma config FLTAMX = RC1 // FLTA MUX bit (FLTA input is multiplexed with RC1)
#pragma config SSPMX = RC7 // SSP I/O MUX bit (SCK/SCL clocks and SDA/SDI data are multiplexed with RC5 and RC4, respectively. SDO output is multiplexed with RC7.)
#pragma config PWM4MX = RB5 // PWM4 MUX bit (PWM4 output is multiplexed with RB5)
#pragma config EXCLKMX = RC3 // TMR0/T5CKI External clock MUX bit (TMR0/T5CKI external clock input is multiplexed with RC3)
#pragma config MCLRE = ON // MCLR Pin Enable bit (Enabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON // Low-Voltage ICSP Enable bit (Low-voltage ICSP enabled)
// CONFIG5L
#pragma config CP0 = OFF // Code Protection bit (Block 0 (000200-000FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection bit (Block 1 (001000-001FFF) not code-protected)
#pragma config CP2 = OFF // Code Protection bit (Block 2 (002000-002FFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection bit (Block 3 (003000-003FFFh) not code-protected)
// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
// CONFIG6L
#pragma config WRT0 = OFF // Write Protection bit (Block 0 (000200-000FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection bit (Block 1 (001000-001FFF) not write-protected)
#pragma config WRT2 = OFF // Write Protection bit (Block 2 (002000-002FFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection bit (Block 3 (003000-003FFFh) not write-protected)
// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000200-000FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (001000-001FFF) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (002000-002FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (003000-003FFFh) not protected from table reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from table reads executed in other blocks)

8
includes/uart.h Normal file
View File

@ -0,0 +1,8 @@
#include <xc.h>
#ifndef __FDR1_UART__
#define __FDR1_UART__
void UART_Init(void);
#endif //__FDR1_UART__

30
src/main.c Normal file
View File

@ -0,0 +1,30 @@
#include <config.h>
#include <xc.h>
#include <setup.h>
#include <qei.h>
#include <uart.h>
#include <rtu.h>
void main(void) {
setup();
while(1) {
RTU_Task();
}
}
void __interrupt(low_priority) LOWprio_interrupt(void) {
if( PIR1bits.TMR2IF )
RTU_TimerISR();
return;
}
void __interrupt(high_priority) HIGHprio_interrupt(void) {
if( PIR1bits.RCIF )
RTU_RxISR();
return;
}

35
src/qei.c Normal file
View File

@ -0,0 +1,35 @@
#include <xc.h>
void QEI_Init(void) {
QEICONbits.QEIM = 0; // Disable QEI Module
QEICONbits.QERR = 0; // Clear any count errors
QEICONbits.PDEC = 0; // Continue operation during sleep
QEICONbits.nVELM = 1; // Disable velocity mode
DFLTCONbits.FLTCK = 1; // filter 1:2, on QEA, QEB, and IDX
DFLTCONbits.FLT1EN = 1;
DFLTCONbits.FLT2EN = 1;
DFLTCONbits.FLT3EN = 1;
DFLTCONbits.FLT4EN = 0;
MAXCNTH = 0xFF; // MAXCNT = 65535, to maximize range
MAXCNTL = 0xFF;
POSCNTH = 0; // Reset position counter
POSCNTL = 0;
QEICONbits.QEIM = 5; // X4 mode with position counter reset by MAXCNT
// QEICONbits.QEIM = 2; // X2 mode with position counter reset by MAXCNT
}
uint16_t QEI_ReadPosition(void) {
uint8_t hi1, hi2, lo;
do {
hi1 = POSCNTH;
lo = POSCNTL;
hi2 = POSCNTH;
} while (hi1 != hi2);
return ((uint16_t)hi1 << 8) | lo;
}

180
src/rtu.c Normal file
View File

@ -0,0 +1,180 @@
#include "rtu.h"
#include "qei.h"
#include <macros.h>
// ─────────────────────────────────────────────
// Buffers & état interne
// ─────────────────────────────────────────────
static uint8_t rx_buf[RTU_BUF_SIZE];
static uint8_t rx_len;
static uint8_t frame_ready;
// ─────────────────────────────────────────────
// CRC16 Modbus
// ─────────────────────────────────────────────
static uint16_t RTU_CRC16(uint8_t *buf, uint8_t len)
{
uint16_t crc = 0xFFFF;
uint8_t i, bit;
for (i = 0; i < len; i++) {
crc ^= buf[i];
for (bit = 0; bit < 8; bit++) {
if (crc & 0x0001)
crc = (crc >> 1) ^ 0xA001;
else
crc >>= 1;
}
}
return crc;
}
// ─────────────────────────────────────────────
// Envoi d'un octet (attente TXIF)
// ─────────────────────────────────────────────
static void RTU_SendByte(uint8_t byte)
{
while (!PIR1bits.TXIF);
TXREG = byte;
}
// ─────────────────────────────────────────────
// Réponse FC03 — 1 registre
// ─────────────────────────────────────────────
static void RTU_SendFC03(uint16_t value)
{
uint8_t resp[5];
uint16_t crc;
resp[0] = RTU_SLAVE_ADDR;
resp[1] = RTU_FC03;
resp[2] = 0x02; // byte count = 2
resp[3] = (value >> 8); // high byte
resp[4] = (value & 0xFF); // low byte
crc = RTU_CRC16(resp, 5);
RTU_SendByte(resp[0]);
RTU_SendByte(resp[1]);
RTU_SendByte(resp[2]);
RTU_SendByte(resp[3]);
RTU_SendByte(resp[4]);
RTU_SendByte(crc & 0xFF); // CRC low
RTU_SendByte(crc >> 8); // CRC high
}
// ─────────────────────────────────────────────
// Init
// ─────────────────────────────────────────────
void RTU_Init(void)
{
rx_len = 0;
frame_ready = 0;
// Timer2 — timeout inter-caractère 3.5×
PR2 = RTU_TIMER_PR2;
T2CON = 0b00000110; // prescaler 1:16, Timer2 OFF
PIR1bits.TMR2IF = 0;
IPR1bits.TMR2IP = 0; // basse priorité
PIE1bits.TMR2IE = 1;
// UART RX interrupt
IPR1bits.RCIP = 1; // haute priorité
PIE1bits.RCIE = 1;
}
// ─────────────────────────────────────────────
// ISR UART RX — haute priorité
// ─────────────────────────────────────────────
void RTU_RxISR(void)
{
uint8_t byte;
BLUE(1);
// Gestion erreur overrun
if (RCSTAbits.OERR) {
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
}
byte = RCREG;
if (rx_len < RTU_BUF_SIZE)
rx_buf[rx_len++] = byte;
// Redémarre le timer à chaque octet reçu
TMR2 = 0;
PIR1bits.TMR2IF = 0;
T2CONbits.TMR2ON = 1;
}
// ─────────────────────────────────────────────
// ISR Timer2 — basse priorité
// Silence de 3.5× détecté → trame complète
// ─────────────────────────────────────────────
void RTU_TimerISR(void)
{
T2CONbits.TMR2ON = 0;
PIR1bits.TMR2IF = 0;
BLUE(0);
if (rx_len > 0)
frame_ready = 1;
}
// ─────────────────────────────────────────────
// Tâche principale — traitement de la trame
// ─────────────────────────────────────────────
void RTU_Task(void)
{
uint16_t crc_rx, crc_calc;
uint16_t reg_addr, reg_count;
if (!frame_ready)
return;
frame_ready = 0;
// Trame FC03 minimum : 8 octets
if (rx_len < 8)
goto done;
// Adresse esclave
if (rx_buf[0] != RTU_SLAVE_ADDR)
goto done;
// Function code
if (rx_buf[1] != RTU_FC03)
goto done;
// Vérification CRC
crc_rx = (uint16_t)rx_buf[rx_len - 1] << 8 | rx_buf[rx_len - 2];
crc_calc = RTU_CRC16(rx_buf, rx_len - 2);
if (crc_rx != crc_calc)
goto done;
// Adresse et nombre de registres
reg_addr = (uint16_t)rx_buf[2] << 8 | rx_buf[3];
reg_count = (uint16_t)rx_buf[4] << 8 | rx_buf[5];
// On ne supporte que HR0, 1 registre
if (reg_addr != RTU_HR0_ADDR || reg_count != 1)
goto done;
GREEN(1);
RTU_SendFC03(QEI_ReadPosition());
GREEN(0);
done:
rx_len = 0;
}

53
src/setup.c Normal file
View File

@ -0,0 +1,53 @@
#include <config.h>
#include <xc.h>
#include <setup.h>
#include <qei.h>
#include <uart.h>
#include <rtu.h>
#include <macros.h>
void setup(void) {
setup_gpio();
RED(1);
QEI_Init();
UART_Init();
RTU_Init();
INTCON = 0b01010000; // GIE disabled for now, PEIE enable, INT0 enable (always highprio), not int on portB, TMR0
INTCON2 = 0b00000101; // port B pull-up enabled, INT0/1/2 on falling edge
INTCON3 = 0b11011000; // INT1 interrupt high prio, enabled , wired on DialCLK // INT2 interrupt high prio, enabled , wired on DialCLK
RCONbits.IPEN = 1;
INTCONbits.GIEH = 1; // haute priorité
INTCONbits.GIEL = 1; // basse priorité
__delay_ms(3000);
RED(0);
}
void setup_gpio() {
ANSEL0 = 0; // All analog select disable (=digital I/O)
ANSEL0bits.ANS2 = 1; // set RA2/QEI_IDX as analog to disable acting as QEI input
ANSEL1 = 0;
LATA = 0;
TRISA = 0b10111011; // XO / QEx / RA0+RA1+RA2
LATB = 0;
TRISB = 0b00000000; // PGx / Motor driver outputs / SDA+SCL
LATC = 0;
TRISC = 0b10111111; // all inputs: TX/RX/ buttons / RC0+RC1
LATD = 0;
TRISD = 0b11111000; // Red, Blue, Green LEDs as output
LATE = 0;
TRISE = 0b11111000; // (xxxxIOOO) MCLR / Arm
}

17
src/uart.c Normal file
View File

@ -0,0 +1,17 @@
#include <xc.h>
void UART_Init() {
TRISC |= 0b11000000;
RCSTA = 0xB0; // SPEN | SREN | CREN
TXSTA = 0x24; // TXEN | BRGH
// SPBRG = 1; // 250000bps at 8MHz
// SPBRG = 7; // 250000bps at 32MHz
// SPBRG = 3; // 500000bps at 32MHz
// SPBRG = 1; // 1000000bps at 32MHz
// SPBRG = 17; // 115200 bps à 32MHz, erreur -1.36%
SPBRG = 16; // 115200 bps à 32MHz, erreur +2.12%
// EUSART interrupts as low prio, enable
IPR1bits.RCIP = 0;
PIE1bits.RCIE = 1;
}

80
unused/echo.c Normal file
View File

@ -0,0 +1,80 @@
#include <xc.h>
#include <stdio.h>
#include <echo.h>
void echo(char* str) {
for(int i=0; str[i]!=0;i++)
echo_c(str[i]);
}
void echo_c(char c) {
while(!TXIF);
TXREG = c;
}
// void echo_float(float v) {
// char buf[CHAR_BUFF_SIZE];
// sprintf(buf, "%0.3f", v);
// echo(buf);
// }
// void echo_float1(float v) {
// char buf[CHAR_BUFF_SIZE];
// sprintf(buf, "%0.1f", v);
// echo(buf);
// }
// void echo_float2(float v) {
// char buf[CHAR_BUFF_SIZE];
// sprintf(buf, "%0.2f", v);
// echo(buf);
// }
// void echo_float4(float v) {
// char buf[CHAR_BUFF_SIZE];
// sprintf(buf, "%0.4f", v);
// echo(buf);
// }
// void echo_float6(float v) {
// char buf[CHAR_BUFF_SIZE];
// sprintf(buf, "%0.6f", v);
// echo(buf);
// }
// void echo_float8(float v) {
// char buf[CHAR_BUFF_SIZE];
// sprintf(buf, "%0.8f", v);
// echo(buf);
// }
const char h[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
void echo_hex(uint8_t v) {
echo_c(h[(v&0xf0)>>4]);
echo_c(h[(v&0x0f)]);
}
void echo_hex16(uint16_t v) {
echo_hex((v&0xff00)>>8);
echo_hex((v&0x00ff));
}
void echo_uint16(uint16_t v) {
char buf[CHAR_BUFF_SIZE];
sprintf(buf, "%hu", v);
echo(buf);
}
void echo_int32(int32_t v) {
char buf[CHAR_BUFF_SIZE];
sprintf(buf, "%ld", v);
echo(buf);
}
// void echo_bool_label(char* label, uint8_t b) {
// echo(label);
// if(b)
// echo("ON");
// else
// echo("off");
// }

28
unused/echo.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef __ECHO_H__
#define __ECHO_H__
#define NL "\r\n"
#define CHAR_BUFF_SIZE 16
void echo(char*);
void echo_c(char);
// void echo_int(int);
void echo_hex(uint8_t);
void echo_hex16(uint16_t);
void echo_float(float); // def 3 digits
void echo_float1(float); // 6 digits
void echo_float2(float); // 6 digits
void echo_float4(float); // 6 digits
void echo_float6(float); // 6 digits
void echo_float8(float); // 8 digits
void echo_uint16(uint16_t);
void echo_int32(int32_t);
void echo_bool_label(char*, uint8_t);
#endif //__ECHO_H__