Projekte
BirgerT
nibo2_fork#01
bt_lib_uart.c
Projekte
Forum
Doku
Öffentliche Projekte
Startseite
Beispielprogramme
Projekte von anderen
Welcome
Username
Passwort
Eingeloggt bleiben
Zugangsdaten vergessen?
Registrieren
Projektverwaltung
⇨ Please choose! ⇦
——————————————————
✎ Create new project...
★ Browse existing projects...
——————————————————
⚬ MotorTest#1
⚬ C Tutorial 8#1
⚬ NIBO2 C Project#1
⚙ C Tutorial 15#1
⚬ 2010_11_18_el_test001#1
nibo2_fork#01
BSD_license.h
bt_lib_debugutil.c
bt_lib_debugutil.h
bt_lib_glcd.c
bt_lib_glcd.h
bt_lib_grafix.c
bt_lib_grafix.h
bt_lib_terminal.c
bt_lib_terminal.h
bt_lib_uart.c
bt_lib_uart.h
bt_lib_utils.h
lumpylumpy.h
main.c
nibo2_audio.c
nibo2_audio.h
nibo2_copro.c
nibo2_copro.h
nibo2_copro_cmd.h
nibo2_font.h
nibo2_global.h
nibo2_main_menu.h
nibo2_pwm_leds.c
nibo2_pwm_leds.h
nibo2_register.c
nibo2_register.h
nibo2_sensors.c
nibo2_sensors.h
test_debugutil.h
test_gfx_draw.h
xmas1.h
Project details
Compiler settings
Nachrichten
Sie sind nicht eingeloggt.
Neuigkeiten
★
NiboRoboLib 3.6
2017-01-17: Neue Version 3.6
★
NiboRoboLib 3.4.1
2016-04-16: Neue Version 3.4.1
★
Coding Tutorial
2015-11-22: Jetzt auch für den NIBO burger!
Site-Statistic
7426 private projects
385 public projects
16180353 lines compiled
58212 builds
NIBO
@
nibo2_fork_01/bt_lib_uart.c [read only]
////////////////////////////////////////////////////////////////////////// // // NIBO2 UART // // (c) Birger Töpelmann toepelmann(A)web.de Version 141005a // // Funktionen für die serielle Kommunikation über UART0 und UART1 // // Dokumentation in nibo2_uart.h // // // TODO // wenn alle UART0 Funktionen stehen, diese auch für UART1 realisieren // ////////////////////////////////////////////////////////////////////////// // // BSD License see "license.h" // #include "BSD_license.h" // //#include "bt_lib_utils.h" // Sammlung von Makros und Typedefs //#include "bt_lib_uart.h" // UART Kommunikation mit FIFOs #include "nibo2_global.h" // Nibo2 Global Header // // ================================================= UART Variablen // typedef struct { uint8_t* rx_buff; // Adresse Empfangsbuffer uint8_t* tx_buff; // Adresse Sendebuffer char* str_save; // akt. RAM Ausgabestring Position PGM_P strP_save; // akt. FLASH Ausgabestring Position uint16_t param; // die initialisierten Parameter uint8_t error; // Fehlerflags uint8_t mode; // Verhaltensmodus // uint8_t rx_last; // '\n' wenn RET o. '\n' empfangen wurde // ist di == si, dann ist Buffer leer; ist di+1 == si, dann ist Buffer voll uint8_t rx_di; // Destination Index - Zeiger auf nächsten freien Eintrag uint8_t rx_si; // Source Index - Zeiger auf nächsten zu lesenden Eintrag uint8_t rx_cnt; // Anzahl Bytes im Empfangsbuffer uint8_t tx_di; // Destination Index = hier wird Byte abgelegt uint8_t tx_si; // Source Index = hier steht das zu lesende Byte uint8_t tx_cnt; // Anzahl Bytes im Sendebuffer } uart_t; typedef struct { uint8_t* adresse; // Adresse der Daten uint16_t rest; // Rest Anzahl der Daten uint8_t type; // Datenquelle (PGM, RAM, FIFO) } txd_job_t; #define UART0_JOBLEN 8 volatile uart_t uart0; volatile uint8_t uart0_rxdata[UART0_RXDLEN]; volatile uint8_t uart0_txdata[UART0_TXDLEN]; volatile txd_job_t uart0_txjobs[UART0_JOBLEN]; volatile uart_t uart1; volatile uint8_t uart1_rxdata[UART1_RXDLEN]; volatile uint8_t uart1_txdata[UART1_TXDLEN]; ////////////////////////////////////////////////////////////////////////// // // BAUDRATEN TABELLE // // UBBR Werte von WormFood's AVR Baud Rate Calculator für F_CPU 16Mhz // und mit U2X enabled, für bessere Taktgenauigkeit // ////////////////////////////////////////////////////////////////////////// // const uint16_t uart_baudtable[] PROGMEM = { \ // UBBR Wert, Index = Baud error 0x0D04, // 0 = 600 0.0% 0x0682, // 1 = 1200 0,0% 0x0340, // 2 = 2400 0,0% 0x01A0, // 3 = 4800 0,0% 0x00CF, // 4 = 9600 0,2% 0x008A, // 5 = 14400 0,0% 0x0067, // 6 = 19200 0,2% 0x0044, // 7 = 28800 0,6% 0x0033, // 8 = 38400 0,2% 0x0022, // 9 = 57600 0,8% !! Nibo2 Senden geht, Empfangen nicht 0x0019, // 10 = 76800 0,2% 0x0007, // 11 =250000 0,0% }; // // Texte für UART Info String // const char uart_baud_str[][6] PROGMEM = { //const char uart_baud_str[][strlen_P(PSTR(" Baud"))] PROGMEM = { {" 600"}, {" 1200"}, {" 2400"}, {" 4800"}, {" 9600"}, {"14400"}, {"19200"}, {"28800"}, {"38400"}, {"57600"}, {"76800"}, {" 250k"} }; //const char uart_para_str[][3] PROGMEM = { // {",5"}, {",6"}, {",7"}, {",8"}, {",9"}, // {",n"}, {",o"}, {",e"}, {",1"}, {",2"} //}; // 123456789012345678901 const char uart_info_str[] PROGMEM = {"\n" " NIBO2 by BirgerT \n" " UART"}; //const char uart_info_str[] PROGMEM = {"\n NIBO2\n UART"}; ////////////////////////////////////////////////////////////////////////// // // IMPLEMENTATION // ////////////////////////////////////////////////////////////////////////// // // uartx_init(uart, setup) // Parsen des Setup Werts und Initialisieren des UART // void uart_init(uint8_t uart, uint16_t setup){ uint8_t stop = LOBYTE(setup) & 0x0f; uint8_t prty = LOBYTE(setup) >> 4; uint8_t bits = HIBYTE(setup) & 0x0f; uint8_t bidx = HIBYTE(setup) >> 4; if (bidx > 11) bidx = 4; // ungültiger Index setzt 9600Baud uint16_t ubrr = pgm_read_word(&uart_baudtable[bidx]); uint8_t ucsra = (1<<U2X ); // Doppelte Taktrate -> kleinere Fehler // Enable --RX ISR- --TX ISR-- -UDR Empty-- --RX Ein-- -- TX Ein-- // uint8_t ucsrb = (1<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN); uint8_t ucsrb = (1<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN); // Default Datenformat: ---- no parity ------ - 1 stop - ---- 5 bit ----------- uint8_t ucsrc = (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (0<<UCSZ1) | (0<<UCSZ0); if (prty == 2) { // even parity ucsrc |= (1<<UPM1) | (0<<UPM0); } else if (prty == 1) { // odd parity ucsrc |= (1<<UPM1) | (1<<UPM0); } // else no Parity // andere Datenbit Paketgrößen if (bits == 8) { // Standardgröße 8 bit ucsrc |= (1<<UCSZ1) | (1<<UCSZ0); } else if (bits == 6) { ucsrc |= (0<<UCSZ1) | (1<<UCSZ0); } else if (bits == 7) { ucsrc |= (1<<UCSZ1) | (0<<UCSZ0); } // 9 Bit Mode nicht unterstützt // else if (bits == 9) { // ucsrb |= (1<<UCSZ2); // ucsrc |= (1<<UCSZ1) | (1<<UCSZ0); // } if (stop == '2') { ucsrc |= (1<<USBS); } if ((uart & 1) != 0) { uart0.error = UDR0; // UDR leeren uart0.rx_di = uart0.rx_si = uart0.rx_cnt = 0; uart0.tx_di = uart0.tx_si = uart0.tx_cnt = 0; uart0.tx_buff = uart0_txdata; uart0.rx_buff = uart0_rxdata; uart0.str_save = 0; uart0.strP_save = 0; UBRR0H = HIBYTE(ubrr); UBRR0L = LOBYTE(ubrr); UCSR0A = ucsra; UCSR0B = ucsrb; UCSR0C = ucsrc; uart0.error = 0; uart0.mode = 0; uart0.param = setup; } if ((uart & 2) != 0) { uart1.error = UDR1; // UDR leeren uart1.rx_di = uart1.rx_si = uart1.rx_cnt = 0; uart1.tx_di = uart1.tx_si = uart1.tx_cnt = 0; uart1.tx_buff = uart1_txdata; uart1.rx_buff = uart1_rxdata; uart1.str_save = 0; uart1.strP_save = 0; UBRR1H = HIBYTE(ubrr); UBRR1L = LOBYTE(ubrr); UCSR1A = ucsra; UCSR1B = ucsrb; UCSR1C = ucsrc; uart1.error = 0; uart1.mode = 0; uart1.param = setup; } } // uart_init() // void uart0_init(uint16_t setup){ uart_init(UART0,setup); } void uart1_init(uint16_t setup){ uart_init(UART1,setup); } ////////////////////////////////////////////////////////////////////////// // // UART STRING AUSGABEN // ////////////////////////////////////////////////////////////////////////// // // String bis Endemarke aus dem RAM senden // char* uart0_txd_str(char* str){ // Ist eine Ausgabe fortzusetzen (Zyklischer Aufruf)? if(str == 0){ // Merker letzte Ausgabestringposition str = uart0.str_save; if(str == 0) return 0; // Stringausgabe fortsetzen do { char c = *str++; // Stringende erreicht if (c == 0){ uart0.str_save = 0; return 0; } // Platz im Ausgabe FIFO if (uart0_txd_avail() > 2) { uart0_txd_char(c); } // Ausgabe unterbrechen else { --str; uart0.str_save = str; return str; } // Laufzeit von Buffergröße abhängig } while (1); } // Neuer Ausgabe String else { // Ist vorherige Ausgabe abgeschlossen? if (uart0.str_save == 0) { uart0.str_save = str; } } return uart0.str_save; } // uart0_txd_str() // ////////////////////////////////////////////////////////////////////////// // /* PGM_P uart_txd_strP(uint8_t uart, PGM_P str){ if (str == 0) { // Ausgabe fortsetzen if ((uart & UART0) != 0) uart0_txd_strP(0); if ((uart & UART1) != 0) uart1_txd_strP(0); } else { // Kann ein neuer String ausgegeben werden if((uart & UART0) != 0){ // ist UART0 beschäftigt --> Abbruch if ((uart0.strP_save != 0) || (uart0.str_save != 0)) { return 0; } } if((uart & UART1) != 0){ // ist UART1 beschäftigt --> Abbruch if ((uart1.strP_save != 0) || (uart1.str_save != 0)) { return 0; } } // UART(uart) bereit - Wo soll's denn ausgegeben werden if((uart & UART0) != 0){ uart0.strP_save = str; } if((uart & UART1) != 0){ uart1.strP_save = str; } } // Rückgabe Stringadresse == alles i.O. return str; } */ // ////////////////////////////////////////////////////////////////////////// // PGM_P uart0_txd_strP(PGM_P str){ // Ist eine Ausgabe fortzusetzen (Zyklischer Aufruf)? if(str == 0){ // Merker letzte Ausgabestringposition str = uart0.strP_save; if(str == 0) return 0; // Stringausgabe fortsetzen do { char c = pgm_read_byte(str++); // Stringende erreicht if (c == 0){ uart0.strP_save = 0; return 0; } // Platz im Ausgabe FIFO if (uart0_txd_avail() > 2) { uart0_txd_char(c); } // Ausgabe unterbrechen else { --str; uart0.strP_save = str; return str; } } while (1); } // Neuer Ausgabe String else { // Ist vorherige Ausgabe abgeschlossen? if (uart0.strP_save == 0) { uart0.strP_save = str; } } return uart0.strP_save; } // ////////////////////////////////////////////////////////////////////////// TODO // PGM_P uart1_txd_strP(PGM_P str){ return uart1.strP_save; } // ////////////////////////////////////////////////////////////////////////// // int16_t uart0_txd_strF(const char* str, ...){ va_list parg; va_start(parg,str); while (uart0.tx_cnt > 0){ ; // Warten bis Buffer leer ist } int16_t cp = vsprintf((char*)uart0_txdata,str,parg); va_end(parg); uart0.tx_si = 0; uart0.tx_di = cp & UART0_TXMASK; uart0.tx_cnt = uart0.tx_di; UCSR0B |= (1<<UDRIE); return cp; } // ////////////////////////////////////////////////////////////////////////// // /* const char uart_baud_str[][6] PROGMEM = { {" 600"}, {" 1200"}, {" 2400"}, {" 4800"}, {" 9600"}, {"14400"}, {"19200"}, {"28800"}, {"38400"}, {"57600"}, {" Baud"} }; const char uart_para_str[][3] PROGMEM = { {",5"}, {",6"}, {",7"}, {",8"}, {",9"}, {",n"}, {",o"}, {",e"}, {",1"}, {",2"} }; */ // ////////////////////////////////////////////////////////////////////////// TODO // // Einen Teststring mit den Schnittstellenparametern an Buffer ausgeben // char* uart_info(uint8_t uart, uint16_t setup, char* str){ uint8_t stop,prty,bits,bidx; bits = 0; if (setup != 0) { stop = LOBYTE(setup) & 0x0f; prty = LOBYTE(setup) >> 4; bits = HIBYTE(setup) & 0x0f; bidx = HIBYTE(setup) >> 4; } if (bits > 0) { const char* cp = uart_baud_str[bidx]; do { *str = pgm_read_byte(cp++); } while (*str++ != 0); --str; *str++ = ','; *str++ = '0' + bits; *str++ = ','; if (prty < 2) *str++ = 'n' + prty; else *str++ = 'e'; *str++ = ','; *str++ = '0' + stop; } *str = 0; return str; } char* uart0_info(char* str){ return uart_info(1,uart0.param, str); } char* uart1_info(char* str){ return uart_info(2,uart1.param, str); } ////////////////////////////////////////////////////////////////////////// // // UART0 EMPFANGEN // ////////////////////////////////////////////////////////////////////////// uint8_t uart0_rxd_avail(){ return uart0.rx_cnt; } // ////////////////////////////////////////////////////////////////////////// // uint8_t uart0_error(){ uint8_t temp_err = uart0.error; uart0.error = 0; return temp_err; } // ////////////////////////////////////////////////////////////////////////// // char uart0_rxd_char(){ if (uart0.rx_si == uart0.rx_di ) { uart0.error |= UART_RX_NOCHAR; uart0.rx_cnt = 0; return 0; // nix abzuholen } cli(); char ch = uart0_rxdata[uart0.rx_si]; uart0.rx_si = (uart0.rx_si + 1) & UART0_RXMASK; --uart0.rx_cnt; // if (uart0.rx_cnt == 0) uart0.rx_last = 0; sei(); return ch; } // ////////////////////////////////////////////////////////////////////////// // ISR (USART0_RX_vect){ // Statusbits FE0, DOR0, UPE0 lesen char temp_err = UCSR0A & 0x1C; // Zeichen auslesen = Interrupt quittieren char temp_ch = UDR0; // Passt Zeichen in den Buffer? if (uart0.rx_cnt < UART0_RXDLEN) { uart0_rxdata[uart0.rx_di] = temp_ch; // if (temp_ch == '\n') uart0.rx_last = temp_ch; uart0.rx_di = (uart0.rx_di + 1) & UART0_RXMASK; ++uart0.rx_cnt; } else { // Fehler Buffer Overrun temp_err |= UART_RXBUFF_OR; } uart0.error |= temp_err; } // ////////////////////////////////////////////////////////////////////////// // // UART0 SENDEN // ////////////////////////////////////////////////////////////////////////// // uint8_t uart0_txd_avail(){ if (uart0.mode == 1) { return UART0_JOBLEN - uart0.tx_cnt; } else { return UART0_TXDLEN - uart0.tx_cnt; } } // ////////////////////////////////////////////////////////////////////////// // uint8_t uart0_txd_char(char ch){ uint8_t temp_idx = (uart0.tx_di +1) & UART0_TXMASK; // while (temp_idx == uart0_tx_si){ // ; // Warten auf Platz im Buffer // } // ist der Buffer voll.. if(temp_idx == uart0.tx_si){ // ..Fehlerflag setzen und Abbruch uart0.error |= UART_TXBUFF_OR; return uart0.error; } // Zeichen in Sendebuffer schreiben cli(); uart0_txdata[uart0.tx_di] = ch; uart0.tx_di = temp_idx; ++uart0.tx_cnt; sei(); // Enable UART Transmitter & UDRE Interrupt //UCSR0B |= (1<<TXEN); UCSR0B |= (1<<UDRIE); return 0; } // ////////////////////////////////////////////////////////////////////////// // // Grafikbuffer als Semigrafik an Terminal senden. (c) BirgerT // // Der Grafikbuffer enthält das Pixelabbild für ein GLCD (128 X 64) Pixel. // Die Höhe 64 Pixel ist in 8 Zeilen (Bytes) á 8 Pixel unterteilt. // Eine Zeile hat 128 Pixel (Byte) Spalten. // // Im Terminal Zeichensatz (Codepage) CP437 oder CP850 gibt es ASCII- // Zeichen mit "Klötzchen" Grafik in halber Zeichenhöhe oben, in halber // Zeichenhöhe unten sowie in ganzer Zeichenhöhe (und Leerzeichen). // Ein "halbes" Zeichen entspricht einem Pixel. // // Die ASCII Zeichen für die Grafik im Terminalprogramm const uint8_t gfx_char[] PROGMEM = {0x20,0xdf,0xdc,0xdb}; // // In der ISR werden Zeile für Zeile (1..8) immer 2 Bits ausmaskiert und // im "Zeilensprungverfahren" das zugehörige Grafikzeichen gesendet: // 00 = Leerzeichen, 01 = Klötzchen(pixel) oben, 10 = unten, 11 = Block // // Der Terminalcursor wird vor der Ausgabe einer Zeile über eine // VT100 Escape Sequenze in die 1. Spalte der entsprechenden Zeile // synchronisiert. // void uart0_txd_isr_gfxb(){ // Verwendung der FIFO Zeiger in der uart_Struct // .tx_cnt = Schrittzähler / Spaltenindex // .tx_si = Merker für Zwischenergebnisse // .tx_di = Zeilenzähler (0..7)*4 + Zeilenindex 0..3 // uint8_t digit; if (uart0.tx_cnt >= 128) { // Terminal Cursor Positionieren if (uart0.tx_cnt == 128) { // ein 'ESC' senden UDR0 = 0x1b; // und schon mal das Rechnen beginnen uart0.tx_si = uart0.tx_di + 1; } else if (uart0.tx_cnt == 129) { // CSI Folgezeichen senden UDR0 = '['; // und weiterrechnen if (uart0.tx_si < 10) { uart0.tx_cnt++; // Skip '0' Zehner } } else if (uart0.tx_cnt == 130) { // Zeilennummer (1..32) ZEHNER digit = '0'; if (uart0.tx_si >= 20) { uart0.tx_si -= 20; digit += 2; } if (uart0.tx_si >= 10) { uart0.tx_si -= 10; ++digit; } UDR0 = digit; } else if (uart0.tx_cnt == 131) { // Zeilennummer EINER UDR0 = '0' + uart0.tx_si; } else if (uart0.tx_cnt == 132) { // Zahlentrenner UDR0 = ';'; } else if (uart0.tx_cnt == 133) { // Spalte ist immer '1' UDR0 = '1'; } //else if(.tx_cnt == 134) { else { // Kommando Cursorposition UDR0 = 'H'; uart0.tx_cnt = 0xff; // wird } } // .tx_cnt >= 128 // wenn Grafik Spalte 0..127 else { // Pixelbyte aus Grafikbuffer lesen digit = *uart0.tx_buff++; // Zeilenindex 2 o. 3: Highbyte -> LowByte if ((uart0.tx_di & 0x03) >= 2) { digit >>= 4; } // Zeilenindex 1 o. 3: Highnibble -> Lownibble if ((uart0.tx_di & 0x01) != 0) { digit >>= 2; } // Index für Grafik Zeichen digit &= 0x03; // Grafikzeichen senden UDR0 = pgm_read_byte(gfx_char + digit); } if (++uart0.tx_cnt == 128) { // nächster Schritt digit = uart0.tx_di & 0x03; // Zeilenindex retten if ((uart0.tx_di += 0x04) >= 0x20) { uart0.tx_di = 0; // Terminal Zeilenzähler Reset uart0.tx_buff = grafix_buffer; if (++digit < 4) { uart0.tx_di += digit; } } } } // uart0_txd_isr_gfxb void uart0_txd_isr_fifo(){ if (uart0.tx_cnt > 0) { // Zeichen im Buffer vorhanden UDR0 = uart0_txdata[uart0.tx_si]; uart0.tx_si = (uart0.tx_si +1) & UART0_TXMASK; --uart0.tx_cnt; } else { // Disable UDRE Interrupt UCSR1B &= ~(1<<UDRIE); // Disable TXC Interrupt UCSR1B &= ~(1<<TXCIE); } } // ////////////////////////////////////////////////////////////////////////// TODO // void uart0_txd_isr_jobs(){ } // uart0_txd_isr_jobs void uart0_set_mode(uint8_t mode){ // Disable UDRE Interrupt UCSR0B &= ~(1<<UDRIE); // Disable TXC Interrupt UCSR0B &= ~(1<<TXCIE); // UART in Mode 0 Initialisieren uart0_init(uart0.param); // !Reset Terminal über Fifo String uart0_txd_strP(PSTR("\x1b""2c")); while (uart0_txd_strP(0) != 0) { NOP;} if (mode == 1) { // Job Liste // cli(); uart0.mode = mode; uart0.tx_buff = uart0_txjobs; // Ausgabezeiger Start uart0.tx_di = 0; // Job Eingabe indes uart0.tx_si = 0; // Job Ausgabe Index uart0.tx_cnt = 0; // Job Counter UCSR0B |= (1<<UDRIE); // und los geht's // sei(); } if (mode == 2) { // Grafik Buffer senden // cli(); uart0.mode = mode; uart0.tx_buff = grafix_buffer; // Ausgabezeiger Start uart0.tx_di = 0; // Zeilenzähler uart0.tx_si = 0; // Merker uart0.tx_cnt = 128; // Schrittzähler Zeile ausgeben UCSR0B |= (1<<UDRIE); // und los geht's // sei(); } else { // mode = 0 FIFO Betrieb // UART in Mode 0 Initialisieren uart0_init(uart0.param); } } // uart_set_mode void uart1_set_mode(uint8_t mode){ // Disable UDRE Interrupt UCSR1B &= ~(1<<UDRIE); // Disable TXC Interrupt UCSR1B &= ~(1<<TXCIE); // UART in Mode 0 Initialisieren uart1_init(uart1.param); } // uart_set_mode // ////////////////////////////////////////////////////////////////////////// // ISR (USART0_TX_vect){ if (uart0.mode == 2) { uart0_txd_isr_gfxb(); } else if (uart0.mode == 1){ uart0_txd_isr_jobs(); } else if (uart0.mode == 0){ uart0_txd_isr_fifo(); } } // ////////////////////////////////////////////////////////////////////////// // ISR (USART0_UDRE_vect){ if (uart0.mode == 2) { uart0_txd_isr_gfxb(); } else if (uart0.mode == 1){ uart0_txd_isr_jobs(); } else if (uart0.mode == 0){ uart0_txd_isr_fifo(); } } // ////////////////////////////////////////////////////////////////////////// // ISR (USART1_TX_vect){ if (uart1.mode == 2) { // uart1_txd_isr_gfxb(); } else if (uart1.mode == 0){ // uart1_txd_isr_fifo(); } } // ////////////////////////////////////////////////////////////////////////// // ISR (USART1_UDRE_vect){ if (uart1.mode == 2) { // uart1_txd_isr_gfxb(); } else if (uart1.mode == 0){ // uart1_txd_isr_fifo(); } // Disable UDRE Interrupt UCSR1B &= ~(1<<UDRIE); // Disable TXC Interrupt UCSR1B &= ~(1<<TXC); } // EOF
Compiler results:
Werbung
Online
AitanaAlmaguer
Antoniotzj
carmelopetty36638757
KylieSat
warrenhinder6456