//====================================================== // (c)2008-9 Matthew Ford // Forward Computing and Control Pty. Ltd. // www.forward.com.au // All rights reserved // // You may freely copy and distribute this program for // commercial and non-commercial use provided:- // i) this copyright notice remains attached // ii) you clearly mark any changes you make to the code //====================================================== // // The constants N and C determine the data rate. C selects clock frequency // the following expression yields the data rate: // // Clk_freq // BAUD = ------ x 1/N // C // // // Absolute minimum value for N*C is about 10 (which causes the // timer to interrupt to be set again before the interrupt is finished). // Absolute maximum is 170. // (Caused by the 1.5bit-lenght that is necessary to receive bits correctly.) // // The RS232 uses SERIAL_OUT_PIN as the transmit pin // The receive pin is SERIAL_IN_PIN // You need to adjust the other .equ to match the pins you choose. // // // Since this RS232 module is half duplex, it can either send or recieve data. // It can't do both simoutaneausly. // // To use first call RS232_INIT. (with interrupts disabled) // Then either call RS232_SET_TO_RECEIVE to wait for a character to arrive // or RS232_TRANSMIT to transmit the bytes to have previously stored in the // RS232_BUFFER_?? To transmit you also need to set the RS232_SEND_COUNT // which is the number of bytes to be send from 1 to RS232_MAX_SEND_BUFFER // // Mod 1 -- added cli to RS232_SET_TO_RECEIVE and RS232_TRANSMIT // Mod 2 -- Corrected test at start of PIN_CHANGE_INT, Corrected number of Globals, corrected minor comments, added more defines // // //************************************************************************* // .include "tn84def.inc" // set the uC clock calibration // I have allowed for two steps incase you need to move the default more the 0x20 // my default was 0x9E so only one step was needed // in this case just set step 2 to equal step 1 .equ OSC_CAL_STEP_1 = 0xA5 // first adjustment from the default .equ OSC_CAL_STEP_2 = 0xA5 // second adjustment from the default. // 9600 at 8MHz .equ N=103 // == ((8000000/9600) / C) - 1 .equ C=8 // counter prescaler == Divisor // ((0< low -> high on pin input (ie 1 -> 0) idle is 1 // So check for port input == 1 at top and just return if not. // Otherwise start the timer to sample in 1.5 bits // Disable this pin interrupt and clear the interrupt flag // // RS232_STATUS_SET_TO_RECEIVE is cleared by this routine // RS232_STATUS_BUSY is set by this routine // RS232_STATUS_SEND is cleared by this routine // // When receive completes RS232_STATUS_DATA_RECEIVED will be set // Clear this flag when you have handled the data // //************************************************************************* PIN_CHANGE_INT: SAVE_SREG // save Temp and SREG // see if pin low or high sbic SERIAL_IN_PORTIN, SERIAL_IN_PIN // if SERIAL_IN_PIN low == 1 (set) just return rjmp END_PIN_CHANGE_INT // else want to get the timer started as close as possible // to the leading edge on the input // start it with divide by 8 // this assumes that OCR0A is set to some resonably high value // and that timer0 is cleared, RS232_INIT and RS232_STOP should do this in Temp, TCCR0B sbr Temp, (1< 9 stop // else set up to send next bit cpi RS232BitCount, 9 breq TIMER0_CMP_A_STOP_BIT // == 9 send stop bit brsh TIMER0_CMP_A_STOP_SEND // > 9 stop // else set next bit to next bit in byte // the code below takes the same time for either 0 or 1 next bit lds Temp, RS232_SEND_BYTE sbrc Temp,0 sbr RS232StatusReg,(1< '9' then should be A..F? brlo END_CONVERT_TEMP_TO_HEX // no not > '9' subi Temp,-7 ; add 7 for A to F END_CONVERT_TEMP_TO_HEX: ret /******************************************/ // LOAD_SEND_BUFFER // Must call this with interrupts disabled // as EEPROM reads should not be interrupted // // Utility function to initialize the transit buffer // with the chars // Received 0x crlf // // uses r16,r17,r26,r27,r30,r31 /******************************************/ LOAD_SEND_BUFFER: ldi ZH, high(RS232_BUFFER_1+1) // add 1 due to -X in ST -X,Temp below ldi ZL, low(RS232_BUFFER_1+1) // add 1 due to -X in ST -X,Temp below ldi XH, high(example_data) ldi XL, low(example_data) // Set pointer to EEPROM data ldi Temp, 15 mov Temp2, Temp LOAD_SEND_BUFFER_LOOP: sbic EECR,EEPE //if EEPW not clear rjmp LOAD_SEND_BUFFER_LOOP // wait more out EEARH, XH out EEARL, XL // Set the EEPROM's address sbi EECR,EERE // Send the Read strobe in Temp,EEDR // Put data in temp register st -Z, Temp adiw XH:XL, 1 //inc eeprom address dec Temp2 brne LOAD_SEND_BUFFER_LOOP ret //************************************************************************* // // Test/Example Program // // An example program to test of the RS232 code // If the 'a' key is pressed on the PC keyboard,the message // Received 0x61 // will be sent back and displayed. // //************************************************************************* RESET: // disable interrupts // set clock to 8Mhz i.e. remove div8 that is set by programmer ldi Temp, (1<