├── .gitignore ├── Makefile ├── README.md ├── default └── softuart_megaxx4.hex ├── main.c ├── softuart.c └── softuart.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.eep 2 | *.elf 3 | *.hex 4 | *.lss 5 | *.lst 6 | *.map 7 | *.o 8 | *.sym 9 | .dep/ 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blalor/avr-softuart/a7a3563a428846e52f4d32bc86b18dbb5b8c14c8/Makefile -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > This code originated from [Martin Thomas' AVR-Projects page][Martin_THOMAS]. 2 | > It's licensed under a BSD-style license. My intent is to extend this code for 3 | > my own projects and possibly provide an Arduino port. 4 | 5 | [Timer-based AVR Software-UARTS][Martin_THOMAS] 6 | ============================== 7 | 8 | Some AVRs do not have a hardware-UART others have one or two. In case a UART 9 | is needed on "non-UART" AVRs or the available hardware-UARTS are not enough to 10 | fullfill the project-needs a software-UART can be used. The software-UART 11 | available here is based on the "gerneric software uart" by Colin Gittins which 12 | can be downloaded from the iar.com website in the application-notes section. I 13 | have ported/adapted this code to AVRs using avr-gcc/avr-libc and fixed some 14 | smaller mistakes. This code does not need an external interrupt-pin for the 15 | RX-line - any input-pin will do. But the RX pin gets sampled three times the 16 | baudrate so more process-time is needed compared to an "external-int" approach 17 | as presented in various Atmel Application-Notes. 18 | 19 | Get the latest version of this "softuart-library" including a demo-application 20 | [here][20101010] (timestamp 20101010). 21 | 22 | Version History: 23 | 24 | * 20070319: fixed handling of start- and stopbit in receiver-section, 25 | code-cleanup, extended example-applciation 26 | * [20070430][20070430]: added more configuation options for easier adaption to 27 | other AVRs, this time tested with an ATtiny85 28 | * [20101010][20101010]: different minor modifications, included settings for 29 | ATmega164(P|PV|PA), ATmega324, ATmega644 30 | 31 | Copyright (c) 2003, Colin Gittins 32 | Copyright (c) 2005, 2007, 2010, Martin Thomas 33 | All rights reserved. 34 | 35 | [Martin_THOMAS]: http://www.siwawi.arubi.uni-kl.de/avr_projects/#softuart 36 | [20070430]: http://www.siwawi.arubi.uni-kl.de/avr_projects/softuart_gittins_avr_20070430.zip 37 | [20101010]: http://www.siwawi.arubi.uni-kl.de/avr_projects/softuart_gittins_avr_20101010.zip 38 | -------------------------------------------------------------------------------- /default/softuart_megaxx4.hex: -------------------------------------------------------------------------------- 1 | :1000000084C000009DC000009BC0000099C000009B 2 | :1000100097C0000095C0000093C0000091C0000090 3 | :100020008FC000008DC000008BC0000089C00000A0 4 | :1000300087C0000085C0000083C0000081C00000B0 5 | :10004000A8C000007DC000007BC0000079C0000097 6 | :1000500077C0000075C0000073C0000071C00000D0 7 | :100060006FC000006DC000006BC0000069C00000E0 8 | :1000700067C0000065C0000063C000002048656CD8 9 | :100080006C6F200067656E6572696320736F6674BC 10 | :10009000756172742064726976657220636F64653D 11 | :1000A00020627920436F6C696E2047697474696EB1 12 | :1000B000730D0A000D0A536F6674756172742044E3 13 | :1000C000656D6F2D4170706C69636174696F6E0D41 14 | :1000D0000A006164617074656420666F7220417407 15 | :1000E0006D656C2041565220616E6420746869739E 16 | :1000F0002064656D6F206279204D617274696E2095 17 | :1001000054686F6D61730D0A000011241FBECFEF9C 18 | :10011000D8E0DEBFCDBF11E0A0E0B1E0E8E9F3E058 19 | :1001200002C005900D92A630B107D9F711E0A6E004 20 | :10013000B1E001C01D92A433B107E1F702D02AC19A 21 | :100140005FCF1F93CF93DF93BBD0D2D0789484EB53 22 | :1001500090E013D184E890E010D182ED90E00DD1D1 23 | :1001600080E091E0FED0C0E0D0E0DAD0882341F01A 24 | :10017000C2D0182F8BE5DDD0812FDBD08DE5D9D013 25 | :1001800021968FEFCF3FD80781F78CE790E0F5D02D 26 | :10019000EACF1F920F920FB60F9211248F939F9365 27 | :1001A000EF93FF9380912F01813029F580913001E9 28 | :1001B0008150F9F4809132019091330180FF02C0A7 29 | :1001C000599A01C0599880913201909133019695C6 30 | :1001D0008795909333018093320180913101815052 31 | :1001E0008093310180913101882311F410922F0105 32 | :1001F00083E08093300180912D01882309F057C05E 33 | :1002000080910A01882301F1809108018150809337 34 | :100210000801882309F04BC010920A0110922E01A8 35 | :10022000E0912B01F0E080910601E55FFE4F8083B5 36 | :1002300080912B018F5F80932B0180912B01803265 37 | :10024000B0F110922B0133C080912E01882381F4EC 38 | :1002500048992DC081E080932E011092060194E010 39 | :100260009093080198E090930701809309011FC0C3 40 | :10027000809108018150C9F4489B07C08091060114 41 | :1002800090910901892B8093060180910901880FC3 42 | :100290008093090180910701815080930701882391 43 | :1002A00019F481E080930A0183E080930801FF91B3 44 | :1002B000EF919F918F910F900FBE0F901F90189507 45 | :1002C00010922F0110922E0110922D01599A519ADD 46 | :1002D00050989FB7F89489E887BD82E084BD85BDBA 47 | :1002E000EEE6F0E080818260808316BC9FBF0895B7 48 | :1002F00010922D01089590912C0180912B01981757 49 | :10030000E1F3E92FF0E0E55FFE4FE081892F8F5F99 50 | :1003100080932C01803210F010922C018E2F0895C2 51 | :1003200090912B0120E080912C01981321E0822FE5 52 | :100330000895982F80912F018130E1F383E080931D 53 | :1003400030018AE080933101892F90E0880F991F56 54 | :100350009260909333018093320181E080932F016A 55 | :100360000895CF93DF93EC0102C02196E2DF8881EC 56 | :100370008823D9F7DF91CF910895CF93DF93EC01D4 57 | :1003800001C0D7DFFE01219684918823D1F7DF9148 58 | :08039000CF910895F894FFCF0E 59 | :060398002D2D0D0A0000EE 60 | :00000001FF 61 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | AVR Software-Uart Demo-Application 3 | Version 0.4, 10/2010 4 | 5 | by Martin Thomas, Kaiserslautern, Germany 6 | 7 | http://www.siwawi.arubi.uni-kl.de/avr_projects 8 | */ 9 | 10 | /* 11 | Test environment/settings: 12 | - avr-gcc 4.3.3/avr-libc 1.6.7 (WinAVR 3/2010) 13 | - Atmel ATmega324P @ 8MHz internal RC, ATtiny85 @ 1MHz internal RC 14 | - 2400bps 15 | */ 16 | 17 | /* 18 | AVR Memory Usage (-Os, no-inline small-functions, relax) 19 | ---------------- 20 | Device: atmega324p 21 | 22 | Program: 926 bytes (2.8% Full) 23 | (.text + .data + .bootloader) 24 | 25 | Data: 52 bytes (2.5% Full) 26 | (.data + .bss + .noinit) 27 | 28 | 29 | AVR Memory Usage (-Os) 30 | ---------------- 31 | Device: attiny85 32 | 33 | Program: 828 bytes (10.1% Full) 34 | (.text + .data + .bootloader) 35 | 36 | Data: 52 bytes (10.2% Full) 37 | (.data + .bss + .noinit) 38 | 39 | */ 40 | 41 | #define WITH_STDIO_DEMO 0 /* 1: enable, 0: disable */ 42 | 43 | #include 44 | #include 45 | #include "softuart.h" 46 | 47 | 48 | #if WITH_STDIO_DEMO 49 | #include 50 | 51 | // interface between avr-libc stdio and software-UART 52 | static int my_stdio_putchar( char c, FILE *stream ) 53 | { 54 | if ( c == '\n' ) { 55 | softuart_putchar( '\r' ); 56 | } 57 | softuart_putchar( c ); 58 | 59 | return 0; 60 | } 61 | 62 | FILE suart_stream = FDEV_SETUP_STREAM( my_stdio_putchar, NULL, _FDEV_SETUP_WRITE ); 63 | 64 | static void stdio_demo_func( void ) 65 | { 66 | stdout = &suart_stream; 67 | printf( "This output done with printf\n" ); 68 | printf_P( PSTR("This output done with printf_P\n") ); 69 | } 70 | #endif /* WITH_STDIO_DEMO */ 71 | 72 | 73 | int main(void) 74 | { 75 | char c; 76 | static const char pstring[] PROGMEM = 77 | "adapted for Atmel AVR and this demo by Martin Thomas\r\n"; 78 | unsigned short cnt = 0; 79 | #if (F_CPU > 4000000UL) 80 | #define CNTHALLO (unsigned int)(0xFFFF) 81 | #else 82 | #define CNTHALLO (unsigned int)(0xFFFF/3) 83 | #endif 84 | 85 | softuart_init(); 86 | softuart_turn_rx_on(); /* redundant - on by default */ 87 | 88 | sei(); 89 | 90 | softuart_puts_P( "\r\nSoftuart Demo-Application\r\n" ); // "implicit" PSTR 91 | softuart_puts_p( PSTR("generic softuart driver code by Colin Gittins\r\n") ); // explicit PSTR 92 | softuart_puts_p( pstring ); // pstring defined with PROGMEM 93 | softuart_puts( "--\r\n" ); // string "from RAM" 94 | 95 | #if WITH_STDIO_DEMO 96 | stdio_demo_func(); 97 | #endif 98 | 99 | for (;;) { 100 | 101 | if ( softuart_kbhit() ) { 102 | c = softuart_getchar(); 103 | softuart_putchar( '[' ); 104 | softuart_putchar( c ); 105 | softuart_putchar( ']' ); 106 | } 107 | 108 | cnt++; 109 | if (cnt == CNTHALLO) { 110 | cnt = 0; 111 | softuart_puts_P( " Hello " ); 112 | } 113 | 114 | } 115 | 116 | return 0; /* never reached */ 117 | } 118 | -------------------------------------------------------------------------------- /softuart.c: -------------------------------------------------------------------------------- 1 | // softuart.c 2 | // AVR-port of the generic software uart written in C 3 | // 4 | // Generic code from 5 | // Colin Gittins, Software Engineer, Halliburton Energy Services 6 | // (has been available from iar.com web-site -> application notes) 7 | // 8 | // Adapted to AVR using avr-gcc and avr-libc 9 | // by Martin Thomas, Kaiserslautern, Germany 10 | // 11 | // http://www.siwawi.arubi.uni-kl.de/avr_projects 12 | // 13 | // AVR-port Version 0.4 10/2010 14 | // 15 | // --------------------------------------------------------------------- 16 | // 17 | // Remarks from Colin Gittins: 18 | // 19 | // Generic software uart written in C, requiring a timer set to 3 times 20 | // the baud rate, and two software read/write pins for the receive and 21 | // transmit functions. 22 | // 23 | // * Received characters are buffered 24 | // * putchar(), getchar(), kbhit() and flush_input_buffer() are available 25 | // * There is a facility for background processing while waiting for input 26 | // The baud rate can be configured by changing the BAUD_RATE macro as 27 | // follows: 28 | // 29 | // #define BAUD_RATE 19200.0 30 | // 31 | // The function init_uart() must be called before any comms can take place 32 | // 33 | // Interface routines required: 34 | // 1. get_rx_pin_status() 35 | // Returns 0 or 1 dependent on whether the receive pin is high or low. 36 | // 2. set_tx_pin_high() 37 | // Sets the transmit pin to the high state. 38 | // 3. set_tx_pin_low() 39 | // Sets the transmit pin to the low state. 40 | // 4. idle() 41 | // Background functions to execute while waiting for input. 42 | // 5. timer_set( BAUD_RATE ) 43 | // Sets the timer to 3 times the baud rate. 44 | // 6. set_timer_interrupt( timer_isr ) 45 | // Enables the timer interrupt. 46 | // 47 | // Functions provided: 48 | // 1. void flush_input_buffer( void ) 49 | // Clears the contents of the input buffer. 50 | // 2. char kbhit( void ) 51 | // Tests whether an input character has been received. 52 | // 3. char getchar( void ) 53 | // Reads a character from the input buffer, waiting if necessary. 54 | // 4. void turn_rx_on( void ) 55 | // Turns on the receive function. 56 | // 5. void turn_rx_off( void ) 57 | // Turns off the receive function. 58 | // 6. void putchar( char ) 59 | // Writes a character to the serial port. 60 | // 61 | // --------------------------------------------------------------------- 62 | 63 | /* 64 | Remarks by Martin Thomas (avr-gcc/avr-libc): 65 | V0.1 (2/2005) 66 | - stdio.h not used 67 | - AVR-Timer in CTC-Mode ("manual" reload may not be accurate enough) 68 | - Global Interrupt Flag has to be enabled (see demo-application) 69 | - Interface timer_set and set_timer_interrupt not used here 70 | - internal_tx_buffer was defined as unsigned char - thas could not 71 | work since more than 8 bits are needed, changed to unsigned short 72 | - some variables moved from "global scope" into ISR function-scope 73 | - GPIO initialisation included 74 | - Added functions for string-output inspired by P. Fleury's AVR UART-lib. 75 | V0.2 (3/2007) 76 | - adjusted number of RX-bits 77 | - adapted to avr-libc ISR-macro (replaces SIGNAL) 78 | - disable interrupts during timer-init 79 | - used unsigned char (uint8_t) where apropriate 80 | - removed "magic" char checking (0xc2) 81 | - added softuart_can_transmit() 82 | - Makefile based on template from WinAVR 1/2007 83 | - reformated 84 | - extended demo-application to show various methods to 85 | send a string from flash and RAM 86 | - demonstrate usage of avr-libc's stdio in demo-applcation 87 | - tested with ATmega644 @ 3,6864MHz system-clock using 88 | avr-gcc 4.1.1/avr-libc 1.4.5 (WinAVR 1/2007) 89 | V0.3 (4/2007) 90 | - better configuration options in softuart.h. 91 | ->should be easier to adapt to different AVRs 92 | - tested with ATtiny85 @ 1MHz (internal RC) with 2400bps 93 | - AVR-Studio Project-File 94 | V0.4 (10/2010) 95 | - added options for ATmega164P, ATmega32P, ATmega64P 96 | - changed some variable-types from char to unsigned char 97 | - changed some comparisons from <= to == 98 | - small optimization in ISR for RX with temporary variable 99 | - minor modifications in comments and formating 100 | - added compiler options -fno-inline-small-functions, -Wl,--relax 101 | - renamed flag_tx_ready to flag_tx_busy 102 | - replaced softuart_can_transmit() by softuart_transmit_busy() 103 | - tested with ATmega324PV @ 1MHz internal RC and 2400bps 104 | (options for ATtiny25/45/85 still available) 105 | - added 3BSD license 106 | - removed redundant zero-init in declaration of qin and qout 107 | */ 108 | 109 | /* Copyright (c) 2003, Colin Gittins 110 | Copyright (c) 2005, 2007, 2010, Martin Thomas 111 | All rights reserved. 112 | 113 | Redistribution and use in source and binary forms, with or without 114 | modification, are permitted provided that the following conditions are met: 115 | 116 | * Redistributions of source code must retain the above copyright 117 | notice, this list of conditions and the following disclaimer. 118 | 119 | * Redistributions in binary form must reproduce the above copyright 120 | notice, this list of conditions and the following disclaimer in 121 | the documentation and/or other materials provided with the 122 | distribution. 123 | 124 | * Neither the name of the copyright holders nor the names of 125 | contributors may be used to endorse or promote products derived 126 | from this software without specific prior written permission. 127 | 128 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 129 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 130 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 131 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 132 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 133 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 134 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 135 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 136 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 137 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 138 | POSSIBILITY OF SUCH DAMAGE. */ 139 | 140 | 141 | #include 142 | #include 143 | #include 144 | 145 | #include "softuart.h" 146 | 147 | #define SU_TRUE 1 148 | #define SU_FALSE 0 149 | 150 | // startbit and stopbit parsed internally (see ISR) 151 | #define RX_NUM_OF_BITS (8) 152 | volatile static char inbuf[SOFTUART_IN_BUF_SIZE]; 153 | volatile static unsigned char qin; 154 | static unsigned char qout; 155 | volatile static unsigned char flag_rx_off; 156 | volatile static unsigned char flag_rx_ready; 157 | 158 | // 1 Startbit, 8 Databits, 1 Stopbit = 10 Bits/Frame 159 | #define TX_NUM_OF_BITS (10) 160 | volatile static unsigned char flag_tx_busy; 161 | volatile static unsigned char timer_tx_ctr; 162 | volatile static unsigned char bits_left_in_tx; 163 | volatile static unsigned short internal_tx_buffer; /* ! mt: was type uchar - this was wrong */ 164 | 165 | #define set_tx_pin_high() ( SOFTUART_TXPORT |= ( 1 << SOFTUART_TXBIT ) ) 166 | #define set_tx_pin_low() ( SOFTUART_TXPORT &= ~( 1 << SOFTUART_TXBIT ) ) 167 | #define get_rx_pin_status() ( SOFTUART_RXPIN & ( 1 << SOFTUART_RXBIT ) ) 168 | 169 | ISR(SOFTUART_T_COMP_LABEL) 170 | { 171 | static unsigned char flag_rx_waiting_for_stop_bit = SU_FALSE; 172 | static unsigned char rx_mask; 173 | 174 | static unsigned char timer_rx_ctr; 175 | static unsigned char bits_left_in_rx; 176 | static unsigned char internal_rx_buffer; 177 | 178 | unsigned char start_bit, flag_in; 179 | unsigned char tmp; 180 | 181 | // Transmitter Section 182 | if ( flag_tx_busy == SU_TRUE ) { 183 | tmp = timer_tx_ctr; 184 | if ( --tmp == 0 ) { // if ( --timer_tx_ctr <= 0 ) 185 | if ( internal_tx_buffer & 0x01 ) { 186 | set_tx_pin_high(); 187 | } 188 | else { 189 | set_tx_pin_low(); 190 | } 191 | internal_tx_buffer >>= 1; 192 | tmp = 3; // timer_tx_ctr = 3; 193 | if ( --bits_left_in_tx == 0 ) { 194 | flag_tx_busy = SU_FALSE; 195 | } 196 | } 197 | timer_tx_ctr = tmp; 198 | } 199 | 200 | // Receiver Section 201 | if ( flag_rx_off == SU_FALSE ) { 202 | if ( flag_rx_waiting_for_stop_bit ) { 203 | if ( --timer_rx_ctr == 0 ) { 204 | flag_rx_waiting_for_stop_bit = SU_FALSE; 205 | flag_rx_ready = SU_FALSE; 206 | inbuf[qin] = internal_rx_buffer; 207 | if ( ++qin >= SOFTUART_IN_BUF_SIZE ) { 208 | // overflow - reset inbuf-index 209 | qin = 0; 210 | } 211 | } 212 | } 213 | else { // rx_test_busy 214 | if ( flag_rx_ready == SU_FALSE ) { 215 | start_bit = get_rx_pin_status(); 216 | // test for start bit 217 | if ( start_bit == 0 ) { 218 | flag_rx_ready = SU_TRUE; 219 | internal_rx_buffer = 0; 220 | timer_rx_ctr = 4; 221 | bits_left_in_rx = RX_NUM_OF_BITS; 222 | rx_mask = 1; 223 | } 224 | } 225 | else { // rx_busy 226 | tmp = timer_rx_ctr; 227 | if ( --tmp == 0 ) { // if ( --timer_rx_ctr == 0 ) { 228 | // rcv 229 | tmp = 3; 230 | flag_in = get_rx_pin_status(); 231 | if ( flag_in ) { 232 | internal_rx_buffer |= rx_mask; 233 | } 234 | rx_mask <<= 1; 235 | if ( --bits_left_in_rx == 0 ) { 236 | flag_rx_waiting_for_stop_bit = SU_TRUE; 237 | } 238 | } 239 | timer_rx_ctr = tmp; 240 | } 241 | } 242 | } 243 | } 244 | 245 | static void io_init(void) 246 | { 247 | // TX-Pin as output 248 | SOFTUART_TXDDR |= ( 1 << SOFTUART_TXBIT ); 249 | // RX-Pin as input 250 | SOFTUART_RXDDR &= ~( 1 << SOFTUART_RXBIT ); 251 | } 252 | 253 | static void timer_init(void) 254 | { 255 | unsigned char sreg_tmp; 256 | 257 | sreg_tmp = SREG; 258 | cli(); 259 | 260 | SOFTUART_T_COMP_REG = SOFTUART_TIMERTOP; /* set top */ 261 | 262 | SOFTUART_T_CONTR_REGA = SOFTUART_CTC_MASKA | SOFTUART_PRESC_MASKA; 263 | SOFTUART_T_CONTR_REGB = SOFTUART_CTC_MASKB | SOFTUART_PRESC_MASKB; 264 | 265 | SOFTUART_T_INTCTL_REG |= SOFTUART_CMPINT_EN_MASK; 266 | 267 | SOFTUART_T_CNT_REG = 0; /* reset counter */ 268 | 269 | SREG = sreg_tmp; 270 | } 271 | 272 | void softuart_init( void ) 273 | { 274 | flag_tx_busy = SU_FALSE; 275 | flag_rx_ready = SU_FALSE; 276 | flag_rx_off = SU_FALSE; 277 | 278 | set_tx_pin_high(); /* mt: set to high to avoid garbage on init */ 279 | 280 | io_init(); 281 | timer_init(); 282 | } 283 | 284 | static void idle(void) 285 | { 286 | // timeout handling goes here 287 | // - but there is a "softuart_kbhit" in this code... 288 | // add watchdog-reset here if needed 289 | } 290 | 291 | void softuart_turn_rx_on( void ) 292 | { 293 | flag_rx_off = SU_FALSE; 294 | } 295 | 296 | void softuart_turn_rx_off( void ) 297 | { 298 | flag_rx_off = SU_TRUE; 299 | } 300 | 301 | char softuart_getchar( void ) 302 | { 303 | char ch; 304 | 305 | while ( qout == qin ) { 306 | idle(); 307 | } 308 | ch = inbuf[qout]; 309 | if ( ++qout >= SOFTUART_IN_BUF_SIZE ) { 310 | qout = 0; 311 | } 312 | 313 | return( ch ); 314 | } 315 | 316 | unsigned char softuart_kbhit( void ) 317 | { 318 | return( qin != qout ); 319 | } 320 | 321 | void softuart_flush_input_buffer( void ) 322 | { 323 | qin = 0; 324 | qout = 0; 325 | } 326 | 327 | unsigned char softuart_transmit_busy( void ) 328 | { 329 | return ( flag_tx_busy == SU_TRUE ) ? 1 : 0; 330 | } 331 | 332 | void softuart_putchar( const char ch ) 333 | { 334 | while ( flag_tx_busy == SU_TRUE ) { 335 | ; // wait for transmitter ready 336 | // add watchdog-reset here if needed; 337 | } 338 | 339 | // invoke_UART_transmit 340 | timer_tx_ctr = 3; 341 | bits_left_in_tx = TX_NUM_OF_BITS; 342 | internal_tx_buffer = ( ch << 1 ) | 0x200; 343 | flag_tx_busy = SU_TRUE; 344 | } 345 | 346 | void softuart_puts( const char *s ) 347 | { 348 | while ( *s ) { 349 | softuart_putchar( *s++ ); 350 | } 351 | } 352 | 353 | void softuart_puts_p( const char *prg_s ) 354 | { 355 | char c; 356 | 357 | while ( ( c = pgm_read_byte( prg_s++ ) ) ) { 358 | softuart_putchar(c); 359 | } 360 | } 361 | 362 | 363 | 364 | -------------------------------------------------------------------------------- /softuart.h: -------------------------------------------------------------------------------- 1 | #if !defined(F_CPU) 2 | #warning "F_CPU not defined in makefile - now defined in softuart.h" 3 | #define F_CPU 3686400UL 4 | #endif 5 | 6 | #define SOFTUART_BAUD_RATE 2400 7 | 8 | #if defined (__AVR_ATtiny25__) || defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) 9 | #define SOFTUART_RXPIN PINB 10 | #define SOFTUART_RXDDR DDRB 11 | #define SOFTUART_RXBIT PB0 12 | 13 | #define SOFTUART_TXPORT PORTB 14 | #define SOFTUART_TXDDR DDRB 15 | #define SOFTUART_TXBIT PB1 16 | 17 | #define SOFTUART_T_COMP_LABEL TIM0_COMPA_vect 18 | #define SOFTUART_T_COMP_REG OCR0A 19 | #define SOFTUART_T_CONTR_REGA TCCR0A 20 | #define SOFTUART_T_CONTR_REGB TCCR0B 21 | #define SOFTUART_T_CNT_REG TCNT0 22 | #define SOFTUART_T_INTCTL_REG TIMSK 23 | 24 | #define SOFTUART_CMPINT_EN_MASK (1 << OCIE0A) 25 | 26 | #define SOFTUART_CTC_MASKA (1 << WGM01) 27 | #define SOFTUART_CTC_MASKB (0) 28 | 29 | /* "A timer interrupt must be set to interrupt at three times 30 | the required baud rate." */ 31 | #define SOFTUART_PRESCALE (8) 32 | // #define SOFTUART_PRESCALE (1) 33 | 34 | #if (SOFTUART_PRESCALE == 8) 35 | #define SOFTUART_PRESC_MASKA (0) 36 | #define SOFTUART_PRESC_MASKB (1 << CS01) 37 | #elif (SOFTUART_PRESCALE==1) 38 | #define SOFTUART_PRESC_MASKA (0) 39 | #define SOFTUART_PRESC_MASKB (1 << CS00) 40 | #else 41 | #error "prescale unsupported" 42 | #endif 43 | #elif defined (__AVR_ATmega324P__) || defined (__AVR_ATmega324A__) \ 44 | || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) \ 45 | || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega328PA__) \ 46 | || defined (__AVR_ATmega164P__) || defined (__AVR_ATmega164A__) 47 | 48 | #define SOFTUART_RXPIN PIND 49 | #define SOFTUART_RXDDR DDRD 50 | #define SOFTUART_RXBIT PD0 51 | 52 | #define SOFTUART_TXPORT PORTD 53 | #define SOFTUART_TXDDR DDRD 54 | #define SOFTUART_TXBIT PD1 55 | 56 | #define SOFTUART_T_COMP_LABEL TIMER0_COMPA_vect 57 | #define SOFTUART_T_COMP_REG OCR0A 58 | #define SOFTUART_T_CONTR_REGA TCCR0A 59 | #define SOFTUART_T_CONTR_REGB TCCR0B 60 | #define SOFTUART_T_CNT_REG TCNT0 61 | #define SOFTUART_T_INTCTL_REG TIMSK0 62 | #define SOFTUART_CMPINT_EN_MASK (1 << OCIE0A) 63 | #define SOFTUART_CTC_MASKA (1 << WGM01) 64 | #define SOFTUART_CTC_MASKB (0) 65 | 66 | /* "A timer interrupt must be set to interrupt at three times 67 | the required baud rate." */ 68 | #define SOFTUART_PRESCALE (8) 69 | // #define SOFTUART_PRESCALE (1) 70 | 71 | #if (SOFTUART_PRESCALE == 8) 72 | #define SOFTUART_PRESC_MASKA (0) 73 | #define SOFTUART_PRESC_MASKB (1 << CS01) 74 | #elif (SOFTUART_PRESCALE==1) 75 | #define SOFTUART_PRESC_MASKA (0) 76 | #define SOFTUART_PRESC_MASKB (1 << CS00) 77 | #else 78 | #error "prescale unsupported" 79 | #endif 80 | #else 81 | #error "no defintions available for this AVR" 82 | #endif 83 | 84 | #define SOFTUART_TIMERTOP ( F_CPU/SOFTUART_PRESCALE/SOFTUART_BAUD_RATE/3 - 1) 85 | 86 | #if (SOFTUART_TIMERTOP > 0xff) 87 | #warning "Check SOFTUART_TIMERTOP: increase prescaler, lower F_CPU or use a 16 bit timer" 88 | #endif 89 | 90 | #define SOFTUART_IN_BUF_SIZE 32 91 | 92 | // Init the Software Uart 93 | void softuart_init(void); 94 | 95 | // Clears the contents of the input buffer. 96 | void softuart_flush_input_buffer( void ); 97 | 98 | // Tests whether an input character has been received. 99 | unsigned char softuart_kbhit( void ); 100 | 101 | // Reads a character from the input buffer, waiting if necessary. 102 | char softuart_getchar( void ); 103 | 104 | // To check if transmitter is busy 105 | unsigned char softuart_transmit_busy( void ); 106 | 107 | // Writes a character to the serial port. 108 | void softuart_putchar( const char ); 109 | 110 | // Turns on the receive function. 111 | void softuart_turn_rx_on( void ); 112 | 113 | // Turns off the receive function. 114 | void softuart_turn_rx_off( void ); 115 | 116 | // Write a NULL-terminated string from RAM to the serial port 117 | void softuart_puts( const char *s ); 118 | 119 | // Write a NULL-terminated string from program-space (flash) 120 | // to the serial port. example: softuart_puts_p(PSTR("test")) 121 | void softuart_puts_p( const char *prg_s ); 122 | 123 | // Helper-Macro - "automatically" inserts PSTR 124 | // when used: include avr/pgmspace.h before this include-file 125 | #define softuart_puts_P(s___) softuart_puts_p(PSTR(s___)) 126 | --------------------------------------------------------------------------------