Bonjour a tous,
j'essaie de mettre en place un soft-uart sur un atmega8 (la finalité étant de porter sur un at90s2313, déjà en place sur son PCB, ce qui ne le laisse pas la possibilité d'utiliser l'uart matériel)
seul l'émission m’intéresse, a un baud rate de 2400 bps.
J'ai trouvé un code non commenté, qui après adaptation et suppression de ce qui ne me semble pas utile (réception notamment) s’avère fonctionner a 2400 bps sur un atmega a 1mhz (fuse non modifiée)
C'est un pur hasard (et je l'ai trouvé grace a mon analyseur logique...), et je cherche comment et calculé le baud rate sur ce code, qui utilise des timers, avec lesquels j’évite malheureusement de me familiariser depuis que j'utilise des µC (mais il va falloir que j'y passe)
Je pense qu'ici, pour jouer avec le baud rate, la seule chose importante est T0_PRELOAD (en rouge dans le code) et les préscaler définis dans le MAIN . Je n'arrive pas a faire la bonne démarche psychologique pour en trouver la relation, pouvez-vous m'aider a comprendre le calcul a faire? Pourquoi en l'état cela fonctionne à 2400bps?
Merci.
Voici le code, j’espère qu'il ne sera pas trop long...
Code:#define F_CPU 1000000UL #define T0_PRELOAD 207 // 1 Bit #define Tx_M_BIT (1<<PD3) // hw-uart TxD pin volatile unsigned char bTxFlag; // #define TX_M_SEND 1 // volatile unsigned char bTxState; // current state #define TX_C_START 0 // send startbit #define TX_C_BITS 1 // send 8 bits #define TX_C_STOP 2 // send stopp-bit #define TX_C_FINISH 3 // wait 1 bit length (appnote) #define TX_C_END 4 // done volatile unsigned char bTxCount; // Bit-Counter 0-7 volatile unsigned char bTxByte; // Byte to send // --------------------------------------------------- // TIME Interrupt // --------------------------------------------------- ISR(TIMER0_OVF_vect) { TCNT0 = T0_PRELOAD; if (bTxFlag & TX_M_SEND) { switch (bTxState) { case TX_C_START: PORTD &= ~Tx_M_BIT; // Start bTxState = TX_C_BITS; break; case TX_C_BITS: if (bTxByte & 0x01) PORTD |= Tx_M_BIT; // clr Data Bit else PORTD &= ~Tx_M_BIT; // Set Data Bit bTxByte >>= 1; // shift right data bTxCount++; // count if (bTxCount & 0x08) bTxState = TX_C_STOP; break; case TX_C_STOP: PORTD |= Tx_M_BIT; // STOP bTxState = TX_C_FINISH; break; case TX_C_FINISH: bTxState = TX_C_END; break; case TX_C_END: default: bTxFlag &= ~TX_M_SEND; // all done break; } } } // -------------------------------------------------------------------------------- // // -------------------------------------------------------------------------------- void _send_one_byte(char bByte) { bTxState = TX_C_START; // state: start bTxByte = bByte; // data byte bTxCount = 0; // count = 0 TCNT0 = T0_PRELOAD; TIFR &= ~(1<<TOV0); // clear Timer Ovfl TIMSK |= (1<<TOIE0); // enable T/C0 overflow interrupt bTxFlag |= TX_M_SEND; // activate transmission while (bTxFlag & TX_M_SEND); // activate transmission } // -------------------------------------------------------------------------------- // // -------------------------------------------------------------------------------- // --------------------------------------------------- // M A I N // --------------------------------------------------- int main (void) { char bTxt[24] = "\r\nHello, World\r\n"; unsigned char bIx; unsigned char bLn; DDRD = (1<<DDD3); // Port as Output TX PORTD = 0; // Clear all PORTD |= Tx_M_BIT; // Clear (Line inactive) TCCR0 &= ~(1<<CS00); // Timer clock = system clock / 8 TCCR0 |= (1<<CS01); // Timer clock = system clock / 8 TCCR0 &= ~(1<<CS02); // Timer clock = system clock / 8 UCSRA = 0; UCSRB = 0; TIFR &= ~(1<<TOV0); // clear T/C0 overflow flag TIMSK |= (1<<TOIE0); // enable T/C0 overflow interrupt TCNT0 = T0_PRELOAD; // ------------------------------------------------------------ sei(); // ------------------------------------------------------------ bLn = strlen(bTxt); for (bIx = 0;bIx < bLn; bIx++) _send_one_byte(bTxt[bIx]); while (1) { _delay_ms(10); _send_one_byte(0xaa); // echo _delay_ms(10); _send_one_byte('a'); // echo } }
-----