Yop yop,
Ai fais le test pour la fonction de la lib crc16 et elle pèse 52octet en mémoire programme.
J'ai également testé et adapté le code pour un module version tiny et j’obtiens 1388 octet, pas testé mais fonctionnel sur mini (1684octet) .
#include <util/crc16.h>
#include <util/delay.h>
#include <avr/wdt.h>
#define DATA_LENGTH 6
#define ADDRESS 0x11
#define RECEIVER 0x12
#define RE_DE_ON PORTD|=4
#define RE_DE_OFF PORTD&=~(4)
#define RE_DE_REG DDRD |= 4
#define BAUD 115200
#define _WAIT(_pres) _delay_us(_pres)
#define SERIAL_BUFFER_SIZE 10
volatile uint8_t pos = 0;
volatile uint8_t bufferBusRx[SERIAL_BUFFER_SIZE];
volatile uint8_t listener = 0;
volatile uint32_t delayWD = 0;
uint8_t bufferBusTx[DATA_LENGTH] = {0};
volatile uint8_t ack = 0;
uint8_t err = 0;
const uint32_t pres = 69120000/BAUD; //temps de maintien RE_DE
const uint32_t maxRec = 14000000/BAUD; //temps max en reception
const uint32_t maxTrans = (32640000/(BAUD/100))+((ADDRESS*(pres*2))); //temps max de transaction+ temps different entre module selon l'adresse
volatile uint8_t* registreR[3] = {&PINA, &PINB, &PIND}; //tableau pour la gestion semi dynamique des registres (&DDR = &PIN+1, &P0RT= &PIN+2)
uint8_t stateB = 0;
uint32_t delayB = 0;
ISR(USART_RX_vect)
{
if((UCSRB & (1<<RXB8))) // si bit9 à 1 = adresse
{
listener = UDR;
if(listener == ADDRESS) //s'il sagit de son adresse ou adresse controleur = 0x80 ou si une transaction en cours&& adresse de ack = 0x81 on active l'ecoute
{
UCSRA &= ~(1<<MPCM);
pos = 0;
}
else //sinon toute donnees transitant sur le bus seront ignore
{
UCSRA |= (1<<MPCM);
}
delayWD = micros()+maxTrans; //on active un delay max d'occupation du bus quelque soit l'emeteur ou ecouteur
}
else //si mode écoute entrante, on enregistre les donnees
{
if(pos <= 9)
{
bufferBusRx[pos] = UDR;
++pos;
}
else
{
pos = 0;
}
}
}
////////////////////////////////////////////////////////////////////////////
void setup()
{
RE_DE_REG; //pin RE_DE en sortie
DDRD |= 63;
begin(BAUD); //init
}
void loop()
{
if(pos == 9) //si donnees entrente
{
readData();
pos = 0;
}
else //sinon on verifie s'il y a des donnee a transmettre dans le buffer
{
sendData();
}
PORTD &= ~(31);
}
uint8_t sendData()
{
if(bufferBusTx[2] && !listener) // si données à transmettre et que le bus est libre (=0)
{
_WAIT(pres); //petite pause de sécurité car même en cas de liberation '0', RE_DE peux encore être maintenu de l'autre côté
writeData(bufferBusTx); //on envois les données
ack = 1; //
}
if(listener && micros() >= delayWD) // si delay de transaction max est dépasse donc erreur, collision, etc
{
listener = 0x00;
ack = 0;
}
}
void readData() // reception
{
if(bufferBusRx[0] == 0x02 && bufferBusRx[9] == 0x03) //debut de trame
{
if(checkData()) //crc ok, on envoie la commande
{
action(0);
}
else //sinon on retourne directement un message d'erreur crc à l'envoyeur
{
ackError(0x02);
}
}
else //sinon on retourne directement un message d'erreur general de reception
{
ackError(0x01);
}
}
void action(uint8_t local)
{
if(bufferBusRx[4]==0x00) // test off
{
*(registreR[bufferBusRx[5]]+2) &= ~(bufferBusRx[6]); //PORT &= ~(bit)
}
else if(bufferBusRx[4]==0x01) //test on
{
*(registreR[bufferBusRx[5]]+2) |= bufferBusRx[6];
}
uint8_t val = ((*registreR[bufferBusRx[5]])&(bufferBusRx[6])); // pour ack : PIN&BIT
if(local) //s'il sagit d'une commande local on rempli le buffer de transmition
{
bufferBusTx[0] = 0x05;
bufferBusTx[1] = 0x80;
bufferBusTx[2] = ADDRESS;
bufferBusTx[3] = 0xFD;
bufferBusTx[4] = bufferBusRx[5];
bufferBusTx[5] = val;
}
else //sinon on retourne directement un ack de confirmation
{
uint8_t data[6];
data[0] = 0x05;
data[1] = 0x80;
data[2] = ADDRESS;
data[3] = 0xFF;
data[4] = bufferBusRx[5];
data[5] = val;
_WAIT(pres);
writeData(data);
}
}
void writeData(uint8_t* data)
{
//calcul du crc en premier
uint16_t crc = 0xFFFF;
for(uint8_t i=0; i <= data[0]; i++)
{
crc = _crc16_update(crc, data[i]);
}
//active le mode transmition
RE_DE_ON;
write(data[1], 1); //adressage
write(0x02, 0); //debut de trame
for(uint8_t i=0; i <= data[0]; i++) //donnees (suivant la taille specifiée)
{
write(data[i], 0);
}
write(((crc & 0xFF00) >> 8), 0); //crc MSB
write((crc & 0x00FF), 0); //crc LSB
write(0x03, 0); //fin de trame
_WAIT(pres); //delay de maintien
RE_DE_OFF; // on desacive le mode de transmition
}
uint8_t checkData() //controle crc
{
uint16_t crc = 0xFFFF;
uint16_t _crc = (bufferBusRx[7]<<8);
_crc += bufferBusRx[8];
for(uint8_t i=1; i <= bufferBusRx[1]+1; i++)
{
crc = _crc16_update(crc, bufferBusRx[i]);
}
if(crc == _crc)
{
return 1;
}
return 0;
}
void ackError(uint8_t ErrorNo)
{
uint8_t data[5] = {0};
data[0] = 0x04;
data[1] = 0x81;
data[2] = ADDRESS;
data[3] = 0xFE;
data[4] = ErrorNo;
_WAIT(pres);
writeData(data);
}
void write(uint8_t data, uint8_t txb8)
{
while (!((UCSRA) & (1 << UDRE)))
;
if(txb8)
{
UCSRB |= (1<<TXB8);
}
else
{
UCSRB &= ~(1<<TXB8);
}
UDR = data;
}
void begin(unsigned long baud)
{
uint16_t baud_setting;
UCSRA = 0;
baud_setting = (F_CPU / 8 / baud - 1) / 2;
UBRRH = baud_setting >> 8;
UBRRL = baud_setting;
UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<UCSZ2);
UCSRC = (3<<UCSZ0);
UCSRA |= (1<<MPCM);
}