This time we’ll take a closer look at using the flash memory and grabbing data from the program memory. This is used for a wide variety of things such as sine lookup tables. In this example we’ll display some letters (for example your name) on a seven segment display attached to PORTB. I’ve used a Kingbright one if you’d like to do the same, check out the datasheet for the SC56-11GWA.
We start by adding a software flag variable and putting the letter data in the program memory. I’ve put in “FEZ” in the following code bit:
intFlag equ 0x29 org 0x820 DATA 0x71, 0x79, 0x5B
The org directive will tell the compiler to put whatever is coming next in the program memory starting at the address given, 0x820 in this case. The DATA command says which data should be put there. Make sure your other org parameters are correct else you will overwrite other bits of data (the compiler should warn you about this). If you have no idea how 0x71 corresponds to the letter F, I suggest you check out the datasheet of the 7segment display and the following part:
CLRF PORTB MOVLW 0x00 ; Value used to initialize data direction MOVWF TRISB ; Set RB as outputs for 7-segment ; RB0 segment 0 0 ; RB1 segment 1 5 1 ; ... 6 ; RB6 segment 6 4 2 ; 3 7
We configure PORTB as output (do the same for PORTA and C because you should never have floating inputs!). The numbers correspond to the pin of PORTB I connected.
We’d like to be able to see the letters on the display so we need to add some delay, unlike last time where we use software and waste cpu cycles we’re using Timer 0. Time to configure its registers!
movlw 0x20 ; Disable peripheral - enable TRM0 interrupts movwf INTCON MOVLW 0x87 ; 0b10000111; Presscaler 1:256 MOVWF T0CON MOVLW 0x80 ; 0b10000000 MOVWF EECON1
A prescaler of 1:256 should be enough, this will make TRM0 overflow about once a second. When it overflows an overflow flag is set and an interrupt is generated, we’ll take a look at that in a minute. The EECON1 is associated with flash & EEPROM memory, take a look at the PIC’s datasheet to see how it’s configurated.
inter BTFSS INTCON,TMR0IF ; Check if TMR0 has overflowed, if not, just return RETFIE BCF INTCON, TMR0IF ; Mandatory clearing of the TMR0 overflow flag BSF intFlag, 0 ; Set our own software flag RETFIE
Every time TMR0 overflows it’ll generate an interrupt, but other things can generate one too so we need to check if it was actually the timer who caused it. You HAVE to clear the flag yourself, it isn’t done by the hardware once it is set.
Now we have our registers set and our interrupt routine finished, let’s take a look at the main program:
CLRF TBLPTRU ; Set the inital Tabel Pointer values MOVLW 0x08 MOVWF TBLPTRH MOVLW 0x1F MOVWF TBLPTRL
Since we put our data at 0x820 we want the table pointer to point one memory address before the one we want, it’ll become clear why that is with the following part of the code:
Main BTFSS intFlag, 0 ; Check if we set the software flag in the interrupt GOTO Main BCF intFlag, 0 ; Here too, we need to clear it if it was set INCF TBLPTRL ; increment the pointer by one more address TBLRD*+ ; Read the data which TBLPTR is pointing to & increment TBLPTR MOVF TABLAT, w ; Move the readout to W MOVWF PORTB MOVLW 0x25 CPFSEQ TBLPTRL ; Have we read out the 3rd letter? Jump back to the first GOTO Main MOVLW 0x1F MOVWF TBLPTRL ; Set the initial value again GOTO Main
So what happens here? We first check to see if we have our software flag high to know TMR0 has overflowed, next we clear it, then we increment the TBLPTR once more so it’s at 0x820. TBLRD*+ will read the data the TBLPTR is pointing at, it’ll also increment the TBLPTRL’s value by one (for some reason it incremented it by one for me, although it probably should increment by 2, not sure why that’s happening). The data is read to TABLAT (table latch), which can then be moved to the working register and moved to PORTB (you can do this in one command by using MOVFF). Once we’ve had all 3 letters, we have to put TBLPTRL back to its initial value so we can start allover.
Now connect your 7-segment display to PORTB and check if it’s working! Also a quick note, I’m using 18F2550 PICs but you can just as easily use a 2553.
If you’re satisfied with the result, continue to tutorial 3.