//----------------------------------------------------------------------------- // E-T-C Climber 2007 'Makenaide!' //----------------------------------------------------------------------------- // Copyright (C) 2007 Earth-Track-Controllers.com // // AUTH: Akira Tsuchida // DATE: 24 JUN 2007 // MODIFIED:04 AUG 2007 (Add Motor brake for testing) // 16 AUG 2007 (Remove all debug steps) // 08 SEP 2007 (Add new circuit, LEDs, Motor 1,4 Enable) // 16 SEP 2007 (Add all analog input processing) // 05 OCT 2007 (Change to 12 volt system from 24 volt system, // individual motor controller health monitor) // // This program brings 'Makenaide' (E-T-C Climber 2007) to the top of a Ribbon. // And returns it back safely to the ground. // // Target: C8051F330 // // Tool chain: KEIL Eval 'c' // //----------------------------------------------------------------------------- // Includes //----------------------------------------------------------------------------- #include // SFR declarations #include #include //----------------------------------------------------------------------------- // Global CONSTANTS //----------------------------------------------------------------------------- #define SYSCLK 24500000 / 8 // SYSCLK frequency in Hz #define BAUDRATE 115200 // Baud rate of UART in bps #define PRINT_RATE 20 // Times per second to update on UART #define OVERFLOWS_NEEDED (SYSCLK / 65536 / PRINT_RATE) #define ADC_CLOCK 100000 // SAR clock #define ADC_SAMPLE_RATE 10 // Timer 2 overflow rate in Hz (Original 100) #define ADC_COUNTS 1024 // Number of ADC counts #define MAX_BLINK_RATE 40 // Max blink rate in Hz for Timer mode #define MIN_BLINK_RATE 1 // Min blink rate in Hz for Timer mode #define BLINK_DIFF (MAX_BLINK_RATE - MIN_BLINK_RATE) // For easy calculations // Firmware states #define TIMER_MODE 0 // Uses the Timer to blink the LED #define PWM_MODE 1 // Use a PCA channel to PWM the LED //----------------------------------------------------------------------------- // C8051F330 I/O Mapping //----------------------------------------------------------------------------- sbit Posn = P0^0; // 0: Top/Bottom, 1: Not Top/Bottom sbit P_Set = P0^1; // Motor Speed Set (Analog output to Motor Amp) sbit Motor_2_Health = P0^2; // 0: Normal, 1: Failure sbit PV_S_V_Mon = P0^3; // Analog input from PV_S (Secondary) sbit Motor_3_Health = P0^4; // 0: Normal, 1: Failure //sbit RC0 = P0^4; // Remote control //sbit RC1 = P0^5; // Remote control //sbit RC2 = P0^6; // Remote control //sbit RC3 = P0^7; // Remote control sbit P_LED = P0^5; // Primary LED (Blue) 0: On, 1: Off sbit S_LED = P0^6; // Secondary LED (Green) 0: On, 1: Off sbit Motor_1_4_Pwr = P0^7; // 0: Enable, 1: Inhibit (Secondary system) sbit Motor_Speed = P1^0; // Analog Input from Motor Amp (Motor Speed) sbit A_Brake = P1^1; // 0: Apply, 1: Release sbit Dir = P1^2; // (Motor Amp SW1 = Off) 0:Up, 1: Down //sbit LED = P1^3; sbit Motor_2_3_Pwr = P1^3; // 0: Enable, 1: Inhibit (Primary System) sbit Motor_1_Health = P1^4; // 0: Normal, 1: Failure sbit P_Brake = P1^5; // 0: Release, 1: Apply sbit PV_P_V_Mon = P1^6; // Analog input from PV_P (Primary) sbit Beam_Mon = P1^7; // Analog input from Photo Sensor sbit Motor_4_Health = P2^0; // 0: Normal, 1: Failure //sbit RC_Rdy = P2^0; // Remote control data ready //----------------------------------------------------------------------------- // 16-bit SFR Definitions for 'F330 //----------------------------------------------------------------------------- sfr16 TMR2RL = 0xca; // Timer2 reload value sfr16 TMR2 = 0xcc; // Timer2 counter sfr16 TMR3RL = 0x92; // Timer3 reload value sfr16 TMR3 = 0x94; // Timer3 counter sfr16 ADC0 = 0xbd; // ADC Data Word Register //----------------------------------------------------------------------------- // Function PROTOTYPES //----------------------------------------------------------------------------- void SYSCLK_Init (void); void DAC_Init(void); void Port_IO_Init(void); void Init_Device(void); void TIMER0_Init (void); void TIMER2_Init (int counts); void TIMER3_Init (void); void ADC0_Init (void); void UART0_Init (void); void E_Stop (void); void Initial_Start (void); void Ascend (void); void Top_Stop (void); void Unpowered_Descend (void); void Descend (void); void Landing (void); void Restart (void); void Gen_Wait (void); void Print_String (char pstring[]); // ISRs defined: TIMER0_ISR, TIMER3_ISR, ADC0_ISR. //----------------------------------------------------------------------------- // Global Variables //----------------------------------------------------------------------------- bit Blink_State = TIMER_MODE; // Starts with blinking the LED int Blink_Rate = 0; // From MIN_BLINK_RATE to MAX_BLINK_RATE bit update = 0; // Forces a UART update long Num_LED_Flashes = 0; // Simply counts the number of times int Voltage_PV_P_V_Mon = 0; //Voltage from Primary PV panels int Voltage_PV_S_V_Mon = 0; //Voltage from Secondary PV Pnels int Voltage_Beam_Mon = 0; //Voltage of cds photo sensor output int Voltage_Climber_Speed = 0; //Voltage of Motor Speed int Timer_10_Sec = 0; //Timer value for 10 sec timer at the top(Emergency) int Free_running_timer = 0; // Timer value for monitoring PV voltage int Climber_Mode = 0; //Climber mode // 0: Initial Start // 1: Ascend // 2: Top Stop // 3: Descend // 4: Landing // 5: E-Stop // 6: Restart // 7: Unpowered_Descend int ADC_input_number = 0; //Analog Input Number // 0: PV_P_V_Mon // 1: PV_S_V_Mon // 2: Beam_Mon // 3: Climber Speed //----------------------------------------------------------------------------- // MAIN Routine //----------------------------------------------------------------------------- void main (void) { // disable watchdog timer PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer // enable) SYSCLK_Init (); // Initialize system clock to // 24.5MHz Init_Device (); // TIMER0_Init (); // Initialize Timer0 for UART update TIMER2_Init (SYSCLK / 12 / ADC_SAMPLE_RATE); // Init Timer2 for ADC TIMER3_Init (); // Init timer used to blink LED ADC0_Init (); // Enable ADC0 UART0_Init (); // Enable UART using global settings while (1) { // spin forever Initial_Start (); Ascend (); Top_Stop (); Descend (); Landing (); while (Posn == 1){} // 1: Limit sw is not pressed <> } } //----------------------------------------------------------------------------- // Initial_Start //----------------------------------------------------------------------------- // void Initial_Start (void) { Climber_Mode = 0; // P_LED = 1; // 1: Off <> S_LED = 1; // 1: Off Motor_2_3_Pwr = 1; // 1: Inhibit Motor_1_4_Pwr = 1; // 1: Inhibit Dir = 0; // 0: Up // P_Set_Value = TBD; // Set Value (V) = 5 x P_SET ***********TBD************ // IDA0H = 0xff; // Set DAC output to 1023/1024 x 2mA = 2mA IDA0H = 0x1f; // Set DAC output to 255/1024 x 2mA = 0.5mA IDA0L = 0xc0; EA = 1; // enable global interrupts P_Brake = 1; // 1: Apply A_Brake = 1; // 1: Release while (Voltage_Beam_Mon < 12){} // < 1.2V // while (Posn == 1){} // 1: Limit sw is not pressed <> // // while (Voltage_PV_P_V_Mon < 11){} // < 11V (Disabled because of CPU fail) while (Voltage_PV_S_V_Mon < 11){} // < 11V } //----------------------------------------------------------------------------- // Ascend //----------------------------------------------------------------------------- // void Ascend (void) { Climber_Mode = 1; Gen_Wait (); //<> // P_LED = 0; //<> S_LED = 0; Motor_2_3_Pwr = 0; // 0: Enable (Motor Starts!!) Motor_1_4_Pwr = 0; // 0: Enable (Motor Starts!!) P_Brake = 0; // 0: Release while (Posn == 1){ // 1: Not Top if (Motor_1_Health == 1) { E_Stop (); Climber_Mode = 1; } if (Motor_2_Health == 1) { E_Stop (); Climber_Mode = 1; } if (Motor_3_Health == 1) { E_Stop (); Climber_Mode = 1; } if (Motor_4_Health == 1) { E_Stop (); Climber_Mode = 1; } /// if (Voltage_PV_P_V_Mon < 10) { /// if (Voltage_PV_S_V_Mon < 10) { /// E_Stop (); /// Climber_Mode = 1; /// } /// } if (Voltage_PV_S_V_Mon < 10) { //<> E_Stop (); //<> Climber_Mode = 1; //<> } //<> // if (RC = 0x1) { // E_Stop (); // Climber_Mode = 1; // } } } void Top_Stop (void) { Climber_Mode = 2; IDA0H = 0x00; // Set DAC output to 0/1024 x 2mA = 0mA IDA0L = 0x00; P_Brake = 1; // 1: Apply Dir = 1; // 1: Down Timer_10_Sec = 101; //LED Blink pattern for 5 sec while (Timer_10_Sec > 1) { if (Voltage_Beam_Mon > 10) { return; } } Unpowered_Descend (); } void Unpowered_Descend (void) { Climber_Mode = 7; P_Brake = 1; // 1: Apply } void Descend (void) { long int i = 0; Climber_Mode = 3; IDA0H = 0x1f; // Set DAC output to 63/1024 x 2mA = 0.12mA (Torque = TBD) IDA0L = 0xc0; P_Brake = 0; // 0: Release while (Posn == 1){ // 1: Not Top/Bottom if (Voltage_Beam_Mon <= 10) { Unpowered_Descend (); } } } void Landing (void) { long int i = 0; Climber_Mode = 4; IDA0H = 0x00; // Set DAC output to 00/1024 x 2mA = 0.00mA IDA0L = 0x00; P_Brake = 1; // 1: Apply Motor_2_3_Pwr = 1; // 1: Inhibit Motor_1_4_Pwr = 1; // 1: Inhibit // P_LED = 1; //<> S_LED = 1; Gen_Wait (); // Wait for TBD msec Motor_2_3_Pwr = 0; // 0: Enable to reset controller Motor_1_4_Pwr = 0; // 0: Enable to reset controller Gen_Wait (); // Wait for TBD msec Motor_2_3_Pwr = 1; // 1: Inhibit Motor_1_4_Pwr = 1; // 1: Inhibit } void E_Stop (void) { long int i = 0; Climber_Mode = 5; A_Brake = 0; // 0: Apply if (Motor_1_Health == 1) { Motor_1_4_Pwr = 1; // 1: Inhibit Gen_Wait (); A_Brake = 1; // 1: Release Restart (); } if (Motor_2_Health == 1) { Motor_2_3_Pwr = 1; // 1: Inhibit Gen_Wait (); A_Brake = 1; // 1: Release Restart (); } if (Motor_3_Health == 1) { Motor_2_3_Pwr = 1; // 1: Inhibit Gen_Wait (); A_Brake = 1; // 1: Release Restart (); } if (Motor_4_Health == 1) { Motor_1_4_Pwr = 1; // 1: Inhibit Gen_Wait (); A_Brake = 1; // 1: Release Restart (); } P_Brake = 1; // 1: Apply Motor_2_3_Pwr = 1; // 1: Inhibit Motor_1_4_Pwr = 1; // 1: Inhibit Timer_10_Sec = 101; while (Timer_10_Sec > 1) { if (Voltage_PV_P_V_Mon > 10) { Restart (); return; } if (Voltage_PV_S_V_Mon > 10) { Restart (); return; } } Unpowered_Descend (); while (1){ } } void Restart (void) { long int i = 0; Climber_Mode = 6; Motor_2_3_Pwr = 0; // 0: Enable (Motor Starts!!) Motor_1_4_Pwr = 0; // 0: Enable (Motor Starts!!) P_Brake = 0; // 0: Release } //----------------------------------------------------------------------------- // Interrupt Service Routines //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // TIMER0_ISR //----------------------------------------------------------------------------- // // This ISR is triggered upon a Timer0 overflow. It is used to update the // UART with the status of the LED. // //----------------------------------------------------------------------------- void TIMER0_ISR (void) interrupt 1 { static int overflows = 0; // Timer0 is used to schedule the number of times per second the status is // printed to the UART. Since Timer0 and Timer1 share a SYCLK prescaler, it // is easier to use the prescaler only for Timer1 (UART baud rate) and run // Timer0 from SYSCLK. Running Timer0 from SYSCLK requires keeping track // of the number of Timer0 overflows to schedule a reasonable UART update // rate. Updating on every Timer0 overflow would print too fast. // The benefit is that there is more flexibility in scheduling the update // rate as it is no longer any dependent on the fixed UART prescaler. overflows++; if (overflows == OVERFLOWS_NEEDED) // Time to print { putchar ('\f'); // Clear screen Print_String ("Current Mode: "); if (Climber_Mode == 0){ Print_String ("Initial Start, "); } if (Climber_Mode == 1){ Print_String ("Ascend, "); } if (Climber_Mode == 2){ Print_String ("Top Stop, "); } if (Climber_Mode == 3){ Print_String ("Descend, "); } if (Climber_Mode == 4){ Print_String ("Landing, "); } if (Climber_Mode == 5){ Print_String ("E-Stop, "); } if (Climber_Mode == 6){ Print_String ("Restart, "); } if (Climber_Mode == 7){ Print_String ("Unpowered Descend, "); } Print_String ("Dir: "); if (Dir == 0){ Print_String ("Up, "); } if (Dir == 1){ Print_String ("Down, "); } Print_String ("10 sec timer: "); putchar ((Timer_10_Sec / 10) + 0x30); // Tens digit putchar ((Timer_10_Sec % 10) + 0x30); // Ones digit Print_String ("sec"); Print_String ("\n"); Print_String ("PV_P: "); putchar ((Voltage_PV_P_V_Mon / 10) + 0x30); // Ten's digit putchar ((Voltage_PV_P_V_Mon % 10) + 0x30); // One's digit Print_String (" [V], PV_S: "); putchar ((Voltage_PV_S_V_Mon / 10) + 0x30); // Ten's digit putchar ((Voltage_PV_S_V_Mon % 10) + 0x30); // One's digit Print_String (" [V], Beam: "); putchar ((Voltage_Beam_Mon / 10) + 0x30); // Tens digit Print_String ("."); putchar ((Voltage_Beam_Mon % 10) + 0x30); // Ones digit Print_String (" [V], Climber Speed: "); putchar ((Voltage_Climber_Speed / 10) + 0x30); // Tens digit Print_String ("."); putchar ((Voltage_Climber_Speed % 10) + 0x30); // Ones digit Print_String (" [m/sec]\n"); update = 0; overflows = 0; // Reset the count } } //----------------------------------------------------------------------------- // ADC0_ISR //----------------------------------------------------------------------------- // // ADC0_ISR is triggerered upon the completion of an ADC conversion. The ISR // calculates the Blink_Rate or PWM_Duty_Cycle based on the voltage // across the potentiometer. // // Blink mode: // A full-scale reading will configure the Timer to blink the LED at // // A zero reading will configure the Timer the LED to blink at // //----------------------------------------------------------------------------- void ADC0_ISR (void) interrupt 10 { long int i = 0; AD0INT = 0; // Clear conversion complete flag if (ADC_input_number == 0) { Voltage_PV_P_V_Mon = 30*ADC0/1024; ADC_input_number = 1; // PV_S_V_Mon AMX0P = 0x03; // P0.3 is the positive input return; } if (ADC_input_number == 1) { Voltage_PV_S_V_Mon = 30*ADC0/1024; ADC_input_number = 2; // Beam_Mon AMX0P = 0x0f; // P1.7 is the positive input return; } if (ADC_input_number == 2) { Voltage_Beam_Mon = 33*ADC0/1024; ADC_input_number = 3; // Climber Speed AMX0P = 0x08; // P1.0 is the positive input return; } if (ADC_input_number == 3) { Voltage_Climber_Speed = 30*ADC0/1024; ADC_input_number = 0; // PV_P_V_Mon AMX0P = 0x0e; // P1.6 is the positive input return; } } //----------------------------------------------------------------------------- // TIMER3_ISR //----------------------------------------------------------------------------- // // This ISR is triggered upon a Timer3 overflow. The ISR simply toggles // the state of the LED and keeps track of the number of times the LED blinks. // //----------------------------------------------------------------------------- void TIMER3_ISR (void) interrupt 14 { int timer = 0; TMR3CN &= ~0x80; // Clear Timer3 Flags Free_running_timer -= 1; if (Timer_10_Sec != 0) { Timer_10_Sec -= 1; } if (Climber_Mode == 2) { if (Timer_10_Sec >50) { timer = Timer_10_Sec /10; if (timer % 10 ==0) { // P_LED = 0; S_LED = 1; } if (timer % 10 ==3) { // P_LED = 1; S_LED = 0; } if (timer % 10 ==5) { // P_LED = 0; S_LED = 0; } if (timer % 10 ==8) { // P_LED = 1; S_LED = 1; } } } if (Climber_Mode != 4) { // Climber_Mode 4: Landing timer = Free_running_timer /10; if (timer % 10 ==0) { if (Voltage_PV_P_V_Mon < 11){ // P_LED = !P_LED; //<> } else { // P_LED = 0; //<> } if (Voltage_PV_S_V_Mon < 11){ S_LED = !S_LED; } else { S_LED = 0; } } } } //----------------------------------------------------------------------------- // Initialization Subroutines //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // SYSCLK_Init //----------------------------------------------------------------------------- // // This routine initializes the system clock to use the internal 24.5MHz / 8 // oscillator as its clock source. Also enables missing clock detector reset. // void SYSCLK_Init (void) { OSCICN = 0x80; // configure internal oscillator for // its lowest frequency // 24.5 MHz/8 VDM0CN = 0x80; // Enable VDD Mon Gen_Wait (); // need to wait 100 usec to stabilize VDD Mon RSTSRC = 0x06; // enable missing clock detector // enable resetting by low VDD } // Initialization function for device, // Call Init_Device() from your main program void Init_Device(void) { DAC_Init(); Port_IO_Init(); } // Peripheral specific initialization functions, // Called from the Init_Device() function void DAC_Init() { IDA0CN = 0xF2; // 2.0mA full-scale output current // IDA0CN = 0xF1; // 1.0mA full-scale output current // IDA0CN = 0xF0; // 0.5mA full-scale output current } void Port_IO_Init() { // P0.0 - Unassigned, Open-Drain, Digital // P0.1 - Skipped, Open-Drain, Digital // P0.2 - Unassigned, Open-Drain, Digital // P0.3 - Unassigned, Open-Drain, Analog // P0.4 - TX0 (UART0), Open-Drain, Digital // P0.5 - RX0 (UART0), Open-Drain, Digital // P0.6 - Unassigned, Open-Drain, Digital // P0.7 - Unassigned, Open-Drain, Digital // P1.0 - Unassigned, Open-Drain, Analog // P1.1 - Unassigned, Open-Drain, Digital // P1.2 - Unassigned, Open-Drain, Digital // P1.3 - Unassigned, Open-Drain, Digital // P1.4 - Unassigned, Open-Drain, Digital // P1.5 - Unassigned, Open-Drain, Digital // P1.6 - Unassigned, Open-Drain, Analog // P1.7 - Unassigned, Open-Drain, Analog P0MDIN = 0xF7; // Assign P0.3 to Analog P1MDIN = 0x3E; // Assign P1.0, P1.6, P1.7 to Analog P0SKIP = 0x02; // Enable IDA (D/A Conv) XBR0 = 0x01; // Enable UART0 XBR1 = 0x40; // Enable Crossbar } //----------------------------------------------------------------------------- // TIMER0_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Initializes the Timer in 16-bit reload mode using SYSCLK as the time base. // //----------------------------------------------------------------------------- void TIMER0_Init (void) { // Initialize Timer0; set global variable for number overflows to reach // interrupt rate set by TMOD |= 0x01; // Mode 1 - 16-bit counter CKCON |= 0x04; // Use SYSCLK as timebase TL0 = 0; // Clear Timer0 low byte TH0 = 0; // Clear Timer0 high byte IE |= 0x02; // Enable Timer0 Interrupts TR0 = 1; // Enable Timer 0 } //----------------------------------------------------------------------------- // TIMER2_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : // 1) int counts - number of milliseconds of delay // range is postive range of integer: 0 to 32767 // // Configure Timer2 to 16-bit auto-reload and generate an interrupt at // interval specified by using SYSCLK/12 as its time base. // //----------------------------------------------------------------------------- void TIMER2_Init (int counts) { TMR2CN = 0x00; // Stop Timer2; Clear TF2; // use SYSCLK/12 as timebase CKCON &= ~0x30; // Timer2 clocked based on T2XCLK; TMR2RL = -counts; // Init reload values TMR2 = 0xffff; // Set to reload immediately ET2 = 0; // Disable Timer2 interrupts TR2 = 1; // Start Timer2 } //----------------------------------------------------------------------------- // TIMER3_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Configure Timer3 to 16-bit auto-reload and generate an interrupt at // interval specified by using SYSCLK/12 as its time base. // // Initially sets Timer3 to overflow at the maximum blink rate. The Timer3 ISR // is used to toggle the LED. // //----------------------------------------------------------------------------- void TIMER3_Init (void) { TMR3CN = 0x00; // Stop Timer3; Clear flags; // use SYSCLK/12 as timebase CKCON &= ~0xC0; // Timer3 clocked based on T3XCLK; TMR3RL = -25520; //(SYSCLK / 12 / MIN_BLINK_RATE); // Init reload values TMR3 = 0xffff; // Set to reload immediately EIE1 |= 0x80; // Enable Timer3 interrupts TMR3CN |= 0x04; // Start Timer3 Free_running_timer = 0; } //----------------------------------------------------------------------------- // ADC0_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // This function initializes the ADC to measure potetiometer connected // to P1.6 in single-ended mode. Also enables the internal voltage reference. // //----------------------------------------------------------------------------- void ADC0_Init (void) { ADC0CN = 0x42; // Disable ADC0 // Not Normal Track Mode // Enable conversion on Timer2 overflow AMX0P = 0x0E; // P1.6 is the positive input AMX0N = 0x11; // GND is the negative input ADC_input_number = 0; // PV_P_V_Mon ADC0CF = (SYSCLK/ADC_CLOCK) << 3; // ADC conversion clock <= 3MHz ADC0CF &= ~0x04; // Make ADC0 right-justified EIE1 |= 0x08; // Enable ADC0 conversion-complete // interrupts REF0CN = 0x0A; // VREF = VDD, bias generator is on. AD0EN = 1; // Enable ADC0 } //----------------------------------------------------------------------------- // UART0_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Configure the UART1 using Timer1, for and 8-N-1. // //----------------------------------------------------------------------------- void UART0_Init (void) { SCON0 = 0x10; // SCON0: 8-bit variable bit rate // level of STOP bit is ignored // RX enabled // ninth bits are zeros // clear RI0 and TI0 bits if (SYSCLK/BAUDRATE/2/256 < 1) { TH1 = -(SYSCLK/BAUDRATE/2); CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx CKCON |= 0x08; } else if (SYSCLK/BAUDRATE/2/256 < 4) { TH1 = -(SYSCLK/BAUDRATE/2/4); CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01 CKCON |= 0x09; } else if (SYSCLK/BAUDRATE/2/256 < 12) { TH1 = -(SYSCLK/BAUDRATE/2/12); CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00 } else { TH1 = -(SYSCLK/BAUDRATE/2/48); CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10 CKCON |= 0x02; } TL1 = TH1; // Init Timer1 TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload TMOD |= 0x20; TR1 = 1; // START Timer1 TI0 = 1; // Indicate TX0 ready } //----------------------------------------------------------------------------- // Support Functions //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // General wait function //----------------------------------------------------------------------------- void Gen_Wait (void) { long int i = 0; for (i = 0 ; i < 6000 ; i++) { // Wait for TBD msec } } //----------------------------------------------------------------------------- // Print_String //----------------------------------------------------------------------------- // // Return Value : None // Parameters : // 1) char pstring[] - null terminated character string // // Prints the strings stored in pstring to the UART. // //----------------------------------------------------------------------------- void Print_String (char pstring[]) { unsigned char i = 0; while (pstring[i]) { putchar(pstring[i++]); } } //----------------------------------------------------------------------------- // End Of File //-----------------------------------------------------------------------------