Komunikace přes usart s PC

Nazdar lidičky,
potřeboval bych poradit kde dělám chybu (chyby). Teprve začínám s Cečkem , v asembleru jsem toho taky moc neudělal a tohle je moje první komunikace s pc. Všechno mi to celkem chodí, ale občas se neprovede pouze zobrazení přijaté hodnoty a na pc se zobrazí chyba (NAK), ale nevím, zda je to špatným crc, nebo jinou chybou. Ale když vyřadím zkoušku crc, tak se nic nezmění. Ostatní přijaté příkazy se provedou v pořádku. Některé pasáže tam jsou dvakrát, jak to zkouším a přepisuji, ale funkční je vždy jen jedna. Už si tu s tím hraju několikátý večer a pořád na to nemůžu přijít.
Ext. displej Petrovice.cpp (8.01 KB)

Nějak mi není jasné, co má program dělat.
Jestli má jenom přijmout údaj času a zobrazit ho na displeji, tak na co má vlastní hodiny (ISR(TIMER1_COMPA_vect))?

Celý program je napsaný trochu chaoticky.
Zkus si napřed napsat kostru v pseudokódu, např.

[code]// pseudokód

ISR(USART_RXC_vect)
{
přijmi zprávu a ulož do pole “recv_data]”;
usart_flag = 1;
}

//--------------------------------

ISR(TIMER1_COMPA_vect) // 20 ms, 7-seg multiplex
{
vypni všechny anody;
na sementy dej příslušné číslo;
zapni další anodu;
}

//--------------------------------

main()
{
// inicializace portů, čítačů, atd

while(1)
{
if(usart_flag == 1) // přišla zpráva
{
usart_flag = 0;

     // kontrola CRC
     recv_crc = recv_data[8];
     crc = (spočítej crc pole recv_data);
     if(crc == recv_crc)  uart_putc(ACK);
     else {uart_putc(NAK); break;}
     
     // provedení příkazu
     prikaz = recv_data[1];

     if(prikaz == 0x11)  start();
     if(prikaz == 0x12)  reset();
     if(prikaz == 0x13)  stop();
     if(prikaz == 0x14)  zobraz();
  }

}
}

//--------------------------------

void start(void)
{
//kód
}

void stop(void)
{

}

void reset(void)
{
//kód
}

void zobraz(void)
{
//kód
}

[/code]
Možná bych na tvém místě pro přenos použil raději ascii znaky pro snadnější testování s terminálem.

Některé chyby:

crc = crc xor usart_data[t]; Bitové xor je takto:

crc = crc ^ usart_data[t];

unsigned char usart_data[9]; má býtvolatile unsigned char usart_data[9]; Proměnné použité v přerušení i v main() musí být deklarované jako “volatile”.

Převod čísla na kód segmentů se dělá pomocí look-up tabulky.
Je to jednodušší než hejno “case” podmínek.

Atd.

abych byl stručný, je to do displeje k časomíře na požární sport. Program má vlastní počítání času, proto časovač. Pracuje to tak, že pc odešle příkaz start, displej začne počítat sám nezávisle na pc. Až dojde k zastavení měření času v pc, tak do displeje se odešle příkaz stop pro zastavení displeje a hned příkaz zobraz a hodnota naměřená v pc.
Na ASCI přejít nemůžu, protože program v pc je už staršího data, nejsem autor a navíc už pracuje s jiným displejem. Já teď dělám program pro svůj “modernější” displej.
Hejno case mi je taky proti srsti, ale nic jiného mě nenapadlo. Přijímané hodnoty jsou již ve tvaru pro segmenty původního displeje, takže, já si to musím převést zpět do normálních hodnot a pak teprve zobrazovat. Look-up tabulka mi zatím nic neříka, ale zkusím něco pohledat. Nebo jestli můžu poprosit o nějaké nakopnutí.

Vlastně tam už jednu lookup tabulku máš ( znak] ).
Je to tabulka ve které hledáme hodnoty.
Buď hledáme hodnotu pro daný index, nebo index pro danou hodnotu

Tabulka pro převod přijatých kódů na čísla bude trochu složitější.
Zkus třeba

[code]/*
0 = 0x03 nebo 0x01
1 = 0x7B nebo 0x79
2 = 0x46 nebo 0x44
3 = 0x4A nebo 0x48
4 = 0xBA nebo 0xB8
5 = 0x8A nebo 0x88
6 = 0x82 nebo 0x80
7 = 0x5B nebo 0x59
8 = 0x02 nebo 0x00
9 = 0x0A nebo 0x08
nic = 0xFF
*/

unsigned char rec_code] = {
0x03,0x01,0x7B,0x79,0x46,0x44,0x4A,0x48,0xBA,0xB8,
0x8A,0x88,0x82,0x80,0x5B,0x59,0x02,0x00,0x0A,0x08,
0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9};

//--------------------------------

//převod přijatých 7seg kódů na čísla
unsigned char lookup(unsigned char byte)
{
for(int i=0;i<20;i++)
{
if(rec_code* == byte)
{
return rec_code*;
}
}
return 255;
}

unsigned char displej_buf[5];
//--------------------------------

int main(void)
{

// zobraz čas z uart

for(int i=0;i<5;i++)
displej_buf* = lookup(rec_data*);

// zobraz displej_buf]
[/code]

Edit:
V konečné aplikaci se tabulky umisťují většinou do paměti programu.****

Tak jsem se po dlouhé době opět vrátil k řešení problému. Po zkoušení a sestrojení si odbočky na sledování komunikace po RS232 jsem přišel na to, že při komunikaci se používá pro ETX a STX kody 0x02 a 0x03. Zároveň se ale stajná hodnota pouříva při zobrazování pro čísla 0 a 8. Takže vždy, když byla v čase obsažená 0 a 8, tak mi to buď předčasně ukončilo řetězec, nebo znova načítalo a nesedělo CRC. Blby je, že jsem si toho nevšiml v kodu dřív :frowning: ulehčil bych si nervy a práci :smiley: Ale děkuji za pomoc a pustím se do dalšího problému s vyrovnáním potenciálu pro RS 232.