// module09.c RGD 10/30/02 // // ***** Base program for Module09: Introduction to Microprocessors ***** // // This program will drive a 10-segment LED Bar Display // // // Use PCW (14-bit compiler) to compile. // Circuit configuration: // HS crystal Oscillator, crystal=4 MHz, 1 MHz instruction cycle, watch dog timer ON, Code Protect OFF // NOTES: // This source code is extremely simple, but it should be sufficient to allow you to play with a microcontroller. // You are encouraged to improve on this code if you want to. Just contact Professor Dennis: yoda@umich.edu // We will set you up with a programmer and some instructions. /* PIC16F84A Pinout: Pin# Name Function --------------------- 17 RA0: This bit is not yet assigned (NC = Not Connected) 18 RA1: This bit is not yet assigned (NC = Not Connected) 1 RA2: This bit is not yet assigned (NC = Not Connected) 2 RA3: This bit is not yet assigned (NC = Not Connected) 3 RA4: This bit is not yet assigned (NC = Not Connected) 6 RB0: This bit is the Least Significant Bit (LSB) for the 10-segment LED Bar Display 7 RB1: This is the next bit for the 10-segment LED Bar Display 8 RB2: This is the next bit for the 10-segment LED Bar Display 9 RB3: This is the next bit for the 10-segment LED Bar Display 10 RB4: This is the next bit for the 10-segment LED Bar Display 11 RB5: This is the next bit for the 10-segment LED Bar Display 12 RB6: This is the next bit for the 10-segment LED Bar Display 13 RB7: This is the Most Significant Bit (MSB) for the for the 10-segment LED Bar Display 4 MCLR: Master Clear (for the microprocessor to function, this must always be at +5V) 5 GND: Ground power) 14 +5V: +5 Volts (power) 15 Osc: Crystal Oscillator Connection (4 MHz) 16 Osc: Crystal Oscillator Connection (4 MHz) */ // NOTE: everything above this line was just a REMARK, it is not compiled or executed. #include <16F84a.H> // This identifies the microcontroller that we are using #fuses HS, WDT, NOPROTECT // This sets up the internal device fuses: HS crystal, WDT ON, Code Protect OFF #use delay (clock=4000000) // 4 MHz crystal: this is the clock speed for the microprocessor // The clock cycles 4 times for each "instruction", so by using a 4 MHz // clock, the microprocessor can execute 1 million instructions per second. #byte PORTA = 0x05 // This just tells the compiler the location of the port A I/O pins #byte PORTB = 0x06 // This just tells the compiler the location of the port B I/O pins unsigned int i; // General use global variable unsigned int j; // General use global variable unsigned int k; // General use global variable unsigned int const dwell = 200; // dwell time in milliseconds // This is a time delay we will use in the program (value must be in the range: 0 - 255) unsigned int const count = 80; // time between counting increments in milliseconds // This is a time delay we will use in the program (value must be in the range: 0 - 255) //////////////////////////////////////////////////////////////////// // SUBROUTINES: These are called by the main program below void init_ports(void) { SET_TRIS_A(0b00011111); // PORTA = all inputs SET_TRIS_B(0b00000000); // PORTB = <4:7> = output, <1:3> = input, <0> = output SETUP_COUNTERS(RTCC_INTERNAL, WDT_1152MS); // set Watch Dog Timer prescaler to 1152 ms // The Watch Dog Timer (WDT) is just an internal timer for the microprocessor that runs // on the side independently. If the microprocessor hangs up or gets confused, the WDT // will reset the microprocessor to the first line of the executable code "main()". // To stop this from happening accidentally, we need to reset the WDT very frequently. // in this case, every second or less. Otherwise, the controller will reset automatically. // Default output values: PORTA = 0b00000010; // BRAKE = ON, Direction set to "0" (arbitrary) OUTPUT_BIT(PIN_B4, 0); // Set motor current bit M1 (LSB) to 0 OUTPUT_BIT(PIN_B5, 0); // Set motor current bit M2 to 0 OUTPUT_BIT(PIN_B6, 0); // Set motor current bit M3 to 0 OUTPUT_BIT(PIN_B7, 0); // Set motor current bit M4 (MSB) to 0 // Default variable values i = 0; j = 0; k = 0; } //// This is a Function ///////////////// void count_up(void) { // this is what the controller does while waiting between steps restart_wdt(); // restart the Watch Dog Timer i = 0; // reset the counter OUTPUT_B(i); // output the 8-bit value "i" to port B (8 pins on the microprocessor) while (i < 255){ // count in a loop from 0-255. This will be shown on the LED Display restart_wdt(); // restart the Watch Dog Timer delay_ms(count); // delay for a set number of milliseconds, equal to "count" (0-255) OUTPUT_B(i); // output the 8-bit value "i" to port B (8 pins on the microprocessor) i = i+1; // increment counter } delay_ms(300); // when done counting, delay for 300 ms before continuing on } //// This is a Function ///////////////// void alternate_flash(void) { // this is what the controller does while waiting between steps restart_wdt(); // restart the Watch Dog Timer i = 0; // reset the counter OUTPUT_B(0b00000000); // output the 8-bit value 00000000 to PORT B while (i < 10){ // count in a loop from 0-255. This will be shown on the LED Display restart_wdt(); // restart the Watch Dog Timer delay_ms(dwell); // delay for a set number of milliseconds, equal to "dwell" (0-255) OUTPUT_B(0b00001111); // output the 8-bit value 00001111 to port B restart_wdt(); // restart the Watch Dog Timer delay_ms(dwell); // delay for a set number of milliseconds, equal to "dwell" (0-255) OUTPUT_B(0b11110000); // output the 8-bit value 11110000 to port B i = i+1; // increment counter } delay_ms(300); // when done counting, delay for 300 ms before continuing on } //// This is a Function ///////////////// void single_bit(void) { // this is what the controller does while waiting between steps restart_wdt(); // restart the Watch Dog Timer OUTPUT_B(0b00000000); // output the 8-bit value 00000000 to PORT B for(i = 1; i <= 15; ++i) { // this is a "for" loop that will repeat 15 times // this loop will cause a single LED to flash ON and OFF 15 times OUTPUT_BIT(PIN_B0, 1); // output a single bit to pin B0 restart_wdt(); // restart the Watch Dog Timer delay_ms(dwell); // delay for a set number of milliseconds, equal to "count" (0-255) OUTPUT_BIT(PIN_B0, 0); // output a single bit to pin B0 restart_wdt(); // restart the Watch Dog Timer delay_ms(dwell); // delay for a set number of milliseconds, equal to "count" (0-255) } delay_ms(300); // when done counting, delay for 300 ms before continuing on } ////////////////////////////////////// ////////////////////////////////////// ////////////////////////////////////// // The microprocessor executabe program starts here, and goes here at RESET void main() { restart_wdt(); // Reset the WDT init_ports(); // Function: Initialize ports delay_ms(300); // Wait a short time before starting up CYCLE: // Label: this is a point in the code that you can "goto" restart_wdt(); // Standard Function: Reset the WDT count_up(); // Function: Make the 10-segment LED display count from 0-255 alternate_flash(); // Function: Alternatively flash elements in the 10-segment display single_bit(); // Function: Send a single "ripple" down the LED display goto CYCLE; // go to yhe label "CYCLE", this will happen forever until you turn off this device } // end of main