A co robię niezgodnie z dokumentacją? Poniższe funkcje znalazłem na stronie internetowej, która wyglądała całkiem poważnie.
Obojętne mi z której flagi będę korzystał byle działało

A skoro w większości przykładów natknąłem się właśnie na wykorzystanie tych flag to tego się na razie trzymam.
----------------------------------------------
W sumie to zapomniałem zaznaczyć, że ja u siebie pominąłem te linie ze znakami zapytania - więc na moje oko robię tak jak instrukcja każe.
W dodatku zmieniłem funkcje putchar na:
void putchar (char c)
{
UDR=c;
loop_until_bit_is_set(USR,UDRE);
}
I ruszyło

D
Już wiem czym różni się UDRE od TXC, ale nie rozumiem dlaczego poprzednia konstrukcja nie działała. Skoro TXC jest ustawiany po nadaniu ramki to znaczy, że zrobiło się miejsce dla następnej - to dlaczego nie chciał jej przyjmować?
--------------------------------
Poniżej zamieszczam część moich wypociny odnośnie realizacji Modbusa na module USART.
Jeżeli komuś się przyda to proszę korzystać. Dodam tylko, że funkcja licząca CRC jest nie moja.
Program zawierał jeszcze obsługę przycisków i LCD, ale je pominąłem, bo strasznie dużo miejsca zajmowało. Poniższe funkcje działają na Atmega16 innych nie sprawdzałem.
/*-------------------------OPOZNIENIA---------------------------------*/
void delay_us(int us)
{
volatile long unsigned int i;
for(i=0;i<(us*(F_CPU)/35000000);i++);
}
void delay_ms(int ms)
{
volatile long unsigned int i;
for(i=0;i<(ms*(F_CPU)/35000);i++);
/* ------------ Organizacja pamieci urzadzenia -------------------*/
unsigned char pamiec[256];
unsigned char ramka[260];
unsigned char rejestr=0;
int dl_ramki=0;
/* -------------- Konfiguracja USART ----------------------------- */
void usart_init(void)
{
UBRRL = 25; // predkosc transmisji na 2400bps, dla F=1MHz, 1 bajt = 3.3ms
UCSRB &= ~_BV(UCSZ2); // zeruj - dlugosc slowa na 8
UCSRC |= _BV(UCSZ1); // ustaw - dlugosc slowa na 8
UCSRC |= _BV(UCSZ0); // ustaw - dlugosc slowa na 8
UCSRB |= _BV(RXEN); // wlacz modul odbiorczy
UCSRB |= _BV(TXEN); // wlacz modul nadawczy
}
/* ------- Funkcje USARTA ---------------------- */
unsigned char putchar(unsigned char dana)
{
UDR=dana;
loop_until_bit_is_set(UCSRA,UDRE);
return(0);
}
unsigned char getchar (void)
{
unsigned char dana;
loop_until_bit_is_set(UCSRA,RXC);
dana=UDR;
return dana;
}
/* -------- Obliczanie CRC -------------------*/
unsigned short ModbusCRC(unsigned char * buf, int size)
{
unsigned short crc = 0xffff;
int i;
while(size--)
{
crc ^= *buf;
buf++;
for(i=0; i<8; i++)
{
if(crc & 1)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
return crc;
}
/* ----------- Konwersja CRC do dwoch liczb 8bitowych --------------------- */
void konwertuj_16(unsigned short crc, unsigned char *msb, unsigned char *lsb)
{
*lsb = crc; // podstaw mniej znaczacy bajt
crc >>= 8; // przesun o 8 bitow w prawo
*msb = crc; // podstaw bardziej znaczacy bit
}
/* ------------- Odbior ramki -------------------- */
int odbierz_ramke(unsigned char *ramka, int *dl_ramki) // jezeli rozpocznie sie transmisja to kolejne
{ // bajty musza przychodzic w odstepach <20ms
*dl_ramki=0;
int brak_bajtu=0;
while (1) // petla nieskonczona
{
if (bit_is_set(UCSRA,RXC)) // jezeli rozpoczeta transmisja
{
while (brak_bajtu <= 200) // brak transmisji na mniej niz 20ms
{
if (bit_is_set(UCSRA,RXC)) // jezeli przyszedl nowy bajt
{
ramka[*dl_ramki]=UDR; // to go zapisz do ramki
++(*dl_ramki);
brak_bajtu=0; // zresetuj czas oczekiwania na bajt
}
delay_us(100); // razem z <200 w while daje 20ms
++brak_bajtu;
}
return 0; // transmisja zakonczona
}
}
}
int sprawdz_ramke(unsigned char *ramka, int dlugosc) // zwraca 0 dla poprawnej ramki
{ // zwraca 1 dla niepoprawnej ramki
unsigned short crc;
unsigned char msb,lsb;
crc = ModbusCRC(ramka, dlugosc-2);
konwertuj_16(crc, &msb, &lsb);
if (ramka[dlugosc-2]==msb) // wyzszy bajt CRC poprawny
{
if (ramka[dlugosc-1]==lsb) // nizszy bajt CRC poprawny
{
return (0);
}
else
{
return (1);
}
}
else
{
return (1);
}
}