Zdar,
pro nějaký projekt potřebuji na AT Mega 16 zprovoznit HW řízení toku dat. ATM16 HW řízení nemá, ale to jsem po pár experimentech vyřešil prostě tak, že softwarově řídím signál CTS směrem do PC.
RxD a TxD jsou zapojené na nohy 14 a 15, pro řízení CTS jsem využil pin 17 (PD3) a nakonec na RTS zbyla noha 16 (PD2).
Vytvořil jsem si malé pole bytů, které používám jako kruhový buffer se dvěma indexy (in, out) a proměnnou uchovávající počet bytů v poli, protože i když nastavím CTS tak, aby PC přestalo posílat data, tak to zřejmě PC pár bytů trvá než zareaguje (někde jsem se dočetl, že možná 2 - 3 byty, s čipy FTDI na USB prý to je horší než klasickými sériáky). Po pár experimentech se to ustálilo na velikosti 20 bytů buffer a 8 bytů hranice při které nastavuji CTS, 12 bytů je rezerva pro byty poslané CTS navzdory.
Data přijímám v přerušení. Kód vypadá takto:
Kód:
#define CTS_STOP PORTD |= 0x04
#define CTS_RECIEVE PORTD &= ~0x04
#define L3_ON PORTC |= 0x80
#define L3_OFF PORTC &= ~0x80
Kód:
#define USART_MAX_BYTES 8
#define USART_BUFFER_SIZE 20
volatile unsigned char usart_buffer [USART_BUFFER_SIZE];
volatile unsigned char usart_index_in;
volatile unsigned char usart_index_out;
volatile unsigned char usart_bytes;
Kód:
ISR (USART_RXC_vect)
{
usart_buffer [usart_index_in] = UDR;
usart_bytes++;
if (usart_bytes > USART_MAX_BYTES) CTS_STOP;
if (usart_bytes > USART_BUFFER_SIZE) LED3_ON;
usart_index_in++;
if (usart_index_in >= USART_BUFFER_SIZE) usart_index_in = 0;
}
V podstatě bezprostředně potom, co je byte přijmut do registru, tak ho uložím do kruhového bufferu, zvýším počet, posunu index, nastavím signál a jednu LED signalizující příp. přetečení bufferu ke kterému nedochází. Nic víc. Funguje to.
Někde jinde mám funkci, která z bufferu data vybírá, jsou-li tam nějaká a něco s nimi dělá. To je taky ok.
ALE chová se to nespolehlivě. ATM16 se občas resetuje. Někdy po pár stovkách bytů, někdy po desítkách tisíc. Náhodně.
Vypozoroval jsem, že
- záleží na taktu, čím víc, tím hůř, při 1MHz skoro 100% vše ok, při 8MHz jedno jestli RC oscilátor, nebo krystal, to občas nastane, při 16 i 20MHz nastává reset velmi často, třeba po pár stech bytů
- nezáleží na přenosové rychlosti, v podstatě stejně špatně se to chová jak pro 9600bps, tak pro 19200bps, rychleji komunikovat nepotřebuji (19200 pro daný účel stačí), při dalším experimentování mohu zkusit i jiné rychlosti
- do pinu 17, který používám pro řízení CTS proniká frekvence oscilátoru * 2, u 1MHz taktu to je téměř neznatelné, ale u 8MHz taktu byť z RC oscilátoru tam naměřím 16MHz cosi s amplitudou cca 200mV, analogicky pro jiné frekvence, s 20MHz krystalem tam byl skoro 40MHz skoro sinus, hádám, že to je nějaký přeslech uvnitř čipu
- určitě není problém s napájením, je důkladně blokováno dostatkem kondenzátorů (od fotky jich tam je pár navíc přímo u čipů), osciloskopem je na 5V minimální šum jak u ATM16, tak u MAX232 i na jiných částech nepájivého pole
- zkusil jsem např. i odpor mezi ATM16 a MAX232 (pár desítek ohmů), nebo kondenzátor na PD3 proti zemi (150pF, 220pF), nic nemělo pozorovatelný vliv
Na fotce - počítadlo se sedmisegmentovkami v pozadí ukazuje 9700, tj. 100* ASCII kód znaku malé A, kterými jsem v jeden okamžik testoval přenos. Později jsem z PC přenášel větší soubory se známou velikostí a počítaly přenesené byty.
Setkal jste se někdo s něčím podobným?Až zas najdu čas, zkusím přemístit CTS na jinou nohu Atmelu (jiný port), zkusím jiný Atmel (kus i model) atd... pro tuto chvíli mne zajímá jestli to je nějaká známá anomálie ATM16. Možná má vliv i to, že to je konstrukce na nepájivém poli.