MPLABICDCode
The main program code should be under "Source File" in MPLAB. Your main Swordfish program file should always reside in the same folder as you MPLAB project file. That is, the program in "Source Files" must be in the same folder as the MPLAB *.mcp and *.mcw files.
' select device and clock... Device = 18F1320 Clock = 8 ' enable ICD - always set before including the Junebug module - if ' you are not using the ICD, you must disable or remove this option ' in order for your program to work correctly... #option ICD = true ' include the Junebug module - this module will manage LEDs and ' button presses for you. It will also correctly configure for internal ' oscillator, based on the 'clock' value above (4 or 8MHz only) Include "junebug.bas" ' local variables... Dim Index As Byte Dim Delay As Word Dim DoCount As Boolean ' program start... Index = 0 DoCount = false Delay = 100 While true LED = Index ' press button 1 to start and stop counting... If IsPressed(Btn1) Then DoCount = Not DoCount ' if button 2 is pressed, slow down the count speed... ElseIf IsPressed(Btn2) Then Inc(Delay, 10) If Delay > 500 Then Delay = 500 EndIf ' if button 3 is pressed, speed up the count speed... ElseIf IsPressed(Btn3) Then Dec(Delay, 10) If Delay < 10 Then Delay = 10 EndIf EndIf ' if counting is enabled, increment the counter and ' delayms(Delay) - Delay will vary depending on how ' much you have decreased or increased using Btn2 or Btn3 ' respectively... If DoCount Then Inc(Index) DelayMS(Delay) EndIf Wend
Module Code
Here is the module code, which should be under "Other Files"
Module Junebug // default configuration fuses... Config OSC = INTIO2, WDT = OFF, LVP = OFF // if you want to use ICD, then set '#option ICD = true' in your main program // before you include this module... #if IsOption(ICD) And ICD #option ISR_SHADOW = false #variable _maxram = _maxram - $C // constrain RAM #variable _maxrom = _maxrom - $1C0 // constrain ROM Config DEBUG = ON // DEBUG fuse ON #endif // private module constants... Const TIMER_REFRESH = 500, // 500 = 2 ms, 250 = 1ms TIMER_RELOAD As Word = 65536 - _clock * TIMER_REFRESH, // calculate reload constant TIMER_DEBOUNCE As Byte = 2500 / TIMER_REFRESH // button debounce (10ms) // private module variables... Dim TMR1 As TMR1L.AsWord, // timer 1 as a word TMR1IF As PIR1.0, // timer 1 interrupt flag TMR1IE As PIE1.0, // timer 1 interrupt enable smState As Byte, // LED state machine variable LastButton As Byte, // holds the state of the last PORTB button press Debounce As Byte // debounce counter variable // public module constants... Public Const Btn1 = 1, Btn2 = 2, Btn3 = 4 // public module variables... Public Dim LED As Byte, // LED, bits 0..5 Button As Byte // button press, bits 0..2 { **************************************************************************** * Name : ISR (PRIVATE) * * Notes : High priority interrupt handler for Timer 1 events. The ISR is * * : fired every 1 or 2ms (depending on TIMER_REFRESH, see above) * * : LED HANDLING * * : As the LEDs on the Junebug are 'charlieplexed', you can only * * : normally have one LED on at a time. However, by time slicing * * : very quickly between each LED state, you can give the illusion * * : that all LEDs are on at the same time. Just set LED.0..5 in * * : main program to switch on * * : BUTTON HANDLING * * : PORTB is scanned and if a button is pressed, the ISR will * * : manage debouncing (10ms). Using an ISR to scan for a button * * : ensure that no button press events are ever missed, even if * * : your main program is performing another task. Use either * * : Button.0..2 in your main program to test for a button press. * * : alternatively, make a call to IsPressed() - see below * **************************************************************************** } Public Interrupt ISR() Dim PortState As Byte // clear timer 1 interrupt flag and reload timer counter... TMR1 = TMR1 + TIMER_RELOAD TMR1IF = 0 // disable all LEDS, then check each LED bit in turn - if set to // one, the LED is switched on TRISA = TRISA Or %11000001 If (smState And LED) <> 0 Then Select smState Case 1 High(PORTA.0) Low (PORTA.6) Case 2 Low (PORTA.0) High(PORTA.6) Case 4 High(PORTA.6) Low (PORTA.7) Case 8 Low (PORTA.6) High(PORTA.7) Case 16 Low (PORTA.0) High(PORTA.7) Case 32 High(PORTA.0) Low (PORTA.7) End Select EndIf // next LED state... smState = smState << 1 If smState.6 = 1 Then smState = 1 EndIf // read PORTB and mask non-button pins... PortState = PORTB And %00100101 // check for button debounce... If Debounce > 0 Then Dec(Debounce) // if debounce has expired and the button press state remains the same, // we need to set the correct bits for our public 'button' variable If (Debounce = 0) And (PortState = LastButton) Then If PortState.0 = 0 Then Button.0 = 1 EndIf If PortState.2 = 0 Then Button.1 = 1 EndIf If PortState.5 = 0 Then Button.2 = 1 EndIf EndIf // no debounce, see if a button has been pressed... ElseIf PortState <> LastButton Then Debounce = TIMER_DEBOUNCE LastButton = PortState EndIf End Interrupt { **************************************************************************** * Name : IsPressed (PUBLIC) * * Notes : Returns true if a button has been pressed. You should pass * * : the pre-defined constants Btn1, Btn2 or Btn3 to this routine. * * : The 'Button' bit is automatically cleared whan a call is made * * : this routine. If you use the 'Button' variable directly in * * : your program, you will need to clear its state flag manually * * **************************************************************************** } Public Function IsPressed(pButton As Byte) As Boolean Disable(ISR) result = (Button And pButton) > 0 Button = Button And Not pButton Enable(ISR) End Function // the first piece of code we must always execute is to select // either internal 4 or 8Mhz clock - this depends on the 'clock' value // set in the main program... #if _clock = 4 OSCCON = $62 #elseif _clock = 8 OSCCON = $72 #endif // initialise the module... smState = 1 // initialise LED state machine LED = 0 // all LEDs are off Button = 0 // no buttons pressed INTCON2.7 = 0 // enable weak pullups on PORTB Debounce = 0 // clear debounce ADCON1 = %11110101 // all digital, except RA1 and RA3 TMR1 = TIMER_RELOAD // initialise timer 1 TMR1IF = 0 // clear timer interrupt flag TMR1IE = 1 // enable timer 1 interrupts T1CON = $01 // prescale 1:1, switch timer on Enable(ISR) // enable interrupt handler