Monday 28 February 2011

LED Segment Counter

After a little playing with the program, I've now managed to get the program to count up from 0 to F, then back to 0, while toggling the processing LED every time the LED display is changed.  While this may be a simple program, it did teach me a few things about how to jump around code, (in order to display the value based on an entry in the working register there had to be the value multiplied by 4, then added to the Program Counter).

There's not much I can really say, other than posting the code, which doesn't quite feel like the place here to post, however I may as well post it, although the formatting may be a bit out where tabs are just transferred as spaces. 

So anyway, the Macro Include file, (I put Macro's into a different include file):

;***********************************************************************
; Filename:      LED_Segment.inc
; Date:          28th February 2011
; Author:        M.J.Andrews
; Purpose:       Program to contain macro's for the LED Segment program.
;***********************************************************************

;***********************************************************************
;****                        M A C R O ' S                         ****
;***********************************************************************

; ----------------------------------------------------------------------
; Macro   : TOGGLE_STATUS_LED
; Purpose : Macro to toggle the processing LED.  This is kept flashing
;           while we run the program as it shows that the processor is
;           working correctly and make it obvious if the code gets stuck.
; ----------------------------------------------------------------------
TOGGLE_STATUS_LED MACRO
 btg  LATA, RA0    ; Toggle the LED status
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_LATC
; Purpose : Macro to set the value of the LATC byte which is most of the
;           7-segment display entries.  We also toggle the status LED so
;           that we can see the LED flash to show the processor running.
; ----------------------------------------------------------------------
SET_LATC MACRO LATCValue
 TOGGLE_STATUS_LED
 MOVLW  LATCValue
 MOVWF  LATC
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_0
; Purpose : Set the LED 7-Segment display to "0"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_0 MACRO
 SET_LATC 0x80
 bcf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_1
; Purpose : Set the LED 7-Segment display to "1"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_1 MACRO
 SET_LATC 0xFB
 bcf  LATB, 0
 bsf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_2
; Purpose : Set the LED 7-Segment display to "2"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_2 MACRO
 SET_LATC 0x44
 bcf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_3
; Purpose : Set the LED 7-Segment display to "3"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_3 MACRO
 SET_LATC 0x41
 bcf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_4
; Purpose : Set the LED 7-Segment display to "4"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_4 MACRO
 SET_LATC 0x03
 bcf  LATB, 0
 bsf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_5
; Purpose : Set the LED 7-Segment display to "5"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_5 MACRO
 SET_LATC 0x01
 bsf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_6
; Purpose : Set the LED 7-Segment display to "6"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_6 MACRO
 SET_LATC 0x00
 bsf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_7
; Purpose : Set the LED 7-Segment display to "7"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_7 MACRO
 SET_LATC 0xFB
 bcf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_8
; Purpose : Set the LED 7-Segment display to "8"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_8 MACRO
 SET_LATC 0x00
 bcf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_9
; Purpose : Set the LED 7-Segment display to "9"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_9 MACRO
 SET_LATC 0x01
 bcf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_A
; Purpose : Set the LED 7-Segment display to "A"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_A MACRO
 SET_LATC 0x02
 bcf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_B
; Purpose : Set the LED 7-Segment display to "b"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_B MACRO
 SET_LATC 0x00
 bsf  LATB, 0
 bsf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_C
; Purpose : Set the LED 7-Segment display to "C"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_C MACRO
 SET_LATC 0x8C
 bsf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_D
; Purpose : Set the LED 7-Segment display to "d"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_D MACRO
 SET_LATC 0x40
 bcf  LATB, 0
 bsf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_E
; Purpose : Set the LED 7-Segment display to "E"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_E MACRO
 SET_LATC 0x04
 bsf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_F
; Purpose : Set the LED 7-Segment display to "F"
; ----------------------------------------------------------------------
SET_SEGMENT_TO_F MACRO
 SET_LATC 0x06
 bsf  LATB, 0
 bcf  LATB, 1
 ENDM

; ----------------------------------------------------------------------
; Macro   : SET_SEGMENT_TO_CLEAR
; Purpose : Set the LED 7-Segment display to blank with no LED's lit
; ----------------------------------------------------------------------
SET_SEGMENT_TO_CLEAR MACRO
 SET_LATC 0xFF
 bsf  LATB, 0
 bsf  LATB, 1
 ENDM
And the main application file:

;******************************************************************************
; Filename:      LED Segment.asm                                              *
; Date:          28th February 2011                                           *
; Author:        M.J.Andrews                                                  *
;******************************************************************************

LIST P=18F2455, F=INHX32 ; Directive to define processor
#include <P18F2455.INC>  ; Processor specific variable definitions
#include <LED_Segment.INC> ; Macro's for use with this program

;******************************************************************************
; Configuration bits

CONFIG FOSC = INTOSC_HS ;HS - HS OSCILLATOR
;******************************************************************************
; Variable definitions

  UDATA
WREG_TEMP   RES 1  ; Variable in RAM for context saving
STATUS_TEMP   RES 1  ; Variable in RAM for context saving
BSR_TEMP   RES 1  ; Variable in RAM for context saving

  UDATA_ACS
CNT_INNER   RES 1  ; Delay procedure, Inner Loop Count
CNT_OUTER   RES 1  ; Delay procedure, Outer Loop Count
LED_SEGMENT_DISP RES 1  ; LED Segment counter variable

;******************************************************************************
; EEPROM data

DATA_EEPROM CODE 0xf00000
  DE "Test Data",0,1,2,3,4,5
;******************************************************************************
; Reset vector's

RESET_VECTOR CODE 0x0000
  goto Main ; Go to start of main code
HI_INT_VECTOR CODE 0x0008
  bra HighInt  ; Go to high priority interrupt routine
LOW_INT_VECTOR CODE 0x0018
  bra LowInt  ; Go to low priority interrupt routine

;******************************************************************************
;****                  Start of the Program Code Section                   ****
;******************************************************************************

  CODE
;******************************************************************************
; High priority interrupt routine
;******************************************************************************
HighInt:
  retfie FAST

;******************************************************************************
; Low priority interrupt routine
;******************************************************************************
LowInt:
  movff STATUS,STATUS_TEMP ;save STATUS register
  movff WREG,WREG_TEMP  ;save working register
  movff BSR,BSR_TEMP  ;save BSR register

; *** low priority interrupt code goes here ***
  movff BSR_TEMP,BSR  ;restore BSR register
  movff WREG_TEMP,WREG  ;restore working register
  movff STATUS_TEMP,STATUS ;restore STATUS register
  retfie

;******************************************************************************
;****                           M A I N   C O D E                          ****
;******************************************************************************

Main:
Initialize
 bcf  TRISA, TRISA0   ; RA0 as an output for the "working" led
 bcf     TRISB, TRISB0   ; RB0 as an output for the 7-segment LED
 bcf     TRISB, TRISB1   ; RB1 as an output for the 7-segment LED
 clrf WREG     ; Clear the Working Register
 movwf TRISC     ; W-REG to PORTC to set as all outputs

 movlw 0x00     ; Start with 0 in the Working Register
 movwf LED_SEGMENT_DISP  ; Move the 0 to the Segment counter

Start_Loop
 movff LED_SEGMENT_DISP, WREG ; Copy the value of the counter to W-REG
 call DisplaySegments   ; Call proc to display LED value in W-REG
 call Delay     ; Call the delay procedure so we see value
 incf LED_SEGMENT_DISP  ; Increment the LED counter
 goto Start_Loop    ; Go back to the start of the loop

;******************************************************************************
;****                          P R O C E D U R E S                         ****
;******************************************************************************

; ----------------------------------------------------------------------
; Function: DisplaySegments
; Purpose : Procedure which can be called to display the low 4-bit value
;           from the W-REG as a numeric value on the LED 7-Segment display.
; ----------------------------------------------------------------------

DisplaySegments
 andlw 0x0F     ; Ensure the value in W-REG is 0->F
 mullw 0x04     ; Multiply W-REG to see how far to jump
 movff PRODL, WREG    ; Move the result back to the W-REG

 addwf PCL      ; Add the value to the Program counter
         ; This will skip forward to the goto
         ; command below to display the LED's
 goto  DISP_0
 goto  DISP_1
 goto  DISP_2
 goto  DISP_3
 goto  DISP_4
 goto  DISP_5
 goto  DISP_6
 goto  DISP_7
 goto  DISP_8
 goto  DISP_9
 goto  DISP_A
 goto  DISP_B
 goto  DISP_C
 goto  DISP_D
 goto  DISP_E
 goto  DISP_F

DISP_0 SET_SEGMENT_TO_0   ; Use the Macro to set the LED to '0'
  return
DISP_1 SET_SEGMENT_TO_1   ; Use the Macro to set the LED to '1'
  return
DISP_2 SET_SEGMENT_TO_2   ; Use the Macro to set the LED to '2'
  return
DISP_3 SET_SEGMENT_TO_3   ; Use the Macro to set the LED to '3'
  return
DISP_4 SET_SEGMENT_TO_4   ; Use the Macro to set the LED to '4'
  return
DISP_5 SET_SEGMENT_TO_5   ; Use the Macro to set the LED to '5'
  return
DISP_6 SET_SEGMENT_TO_6   ; Use the Macro to set the LED to '6'
  return
DISP_7 SET_SEGMENT_TO_7   ; Use the Macro to set the LED to '7'
  return
DISP_8 SET_SEGMENT_TO_8   ; Use the Macro to set the LED to '8'
  return
DISP_9 SET_SEGMENT_TO_9   ; Use the Macro to set the LED to '9'
  return
DISP_A SET_SEGMENT_TO_A   ; Use the Macro to set the LED to 'A'
  return
DISP_B SET_SEGMENT_TO_B   ; Use the Macro to set the LED to 'b'
  return
DISP_C SET_SEGMENT_TO_C   ; Use the Macro to set the LED to 'C'
  return
DISP_D SET_SEGMENT_TO_D   ; Use the Macro to set the LED to 'd'
  return
DISP_E SET_SEGMENT_TO_E   ; Use the Macro to set the LED to 'E'
  return
DISP_F SET_SEGMENT_TO_F   ; Use the Macro to set the LED to 'F'
  return

; ----------------------------------------------------------------------
; Function: Delay
; Purpose : Procedure to wait roughly 128*255 program cycles before
;           continuing, so that we can see the changes of the LED's
; ----------------------------------------------------------------------

Delay
 movlw 0x80            ; Initialize outer loop counter (0x40 - 128)
 movwf CNT_OUTER,A     ; Set outer loop variable to the counter
DelayOuter
 movlw 0xFF            ; Initialize inner loop counter (0xFF - 255)
 movwf CNT_INNER,A     ; Set inner loop variable to the counter
DelayInner
 decfsz CNT_INNER,F,A   ; Decrease Inner counter, skip next on 0
 goto DelayInner      ; Go to the next Inner count, (NOP on 0 CNT_INNER)
DelayInner_End
 decfsz CNT_OUTER,F,A   ; Decrease Outer counter, skip next on 0
 goto DelayOuter      ; Go to the next Outer count, (NOP on 0 CNT_OUTER)
DelayOuter_End
 return                  ; Return back to the place which called this proc

;******************************************************************************
;****                      E N D   O F   P R O G R A M                     ****
;******************************************************************************
  END

And the current circuit diagram as updated in KiCAD for the current version.

No comments:

Post a Comment