Society of Robots - Robot Forum

Software => Software => Topic started by: amando96 on July 23, 2010, 09:26:29 AM

Title: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 23, 2010, 09:26:29 AM
Hi,
I'm following these (http://www.mstracey.btinternet.co.uk/pictutorial/progtut1.htm) tutorials, but they are for the 16F84, the codes don't do anything on the 16F628.
I assume they have different register addresses or something.
Code: [Select]
;*****Set up the Constants****

STATUS         equ       03h                 ;Address of the STATUS register
TRISA             equ       85h                 ;Address of the tristate register for port A
PORTA           equ       05h                 ;Address of Port A
COUNT1        equ       08h                 ;First counter for our delay loops
COUNT2        equ       09h                 ;Second counter for our delay loops

;****Set up the port****

                        bsf                   STATUS,5       ;Switch to Bank 1
                        movlw              00h                    ;Set the Port A pins
                        movwf              TRISA              ;to output.
                        bcf                   STATUS,5       ;Switch back to Bank 0

;****Turn the LED on****

Start               movlw               02h                   ;Turn the LED on by first putting
                       movwf               PORTA            ;it into the w register and then                                                                            ;on the port

;****Start of the delay loop 1****

Loop1          decfsz              COUNT1,1       ;Subtract 1 from 255
                     goto                  Loop1              ;If COUNT is zero, carry on.
                     decfsz             COUNT2,1        ;Subtract 1 from 255
                     goto                 Loop1                ;Go back to the start of our loop.                                                                          ;This delay counts down from                                                                           ;255 to zero, 255 times

;****Delay finished, now turn the LED off****

                    movlw              00h                     ;Turn the LED off by first putting
                    movwf              PORTA              ;it into the w register and then on                                                                         ;the port

;****Add another delay****

Loop2        decfsz             COUNT1,1           ;This second loop keeps the
                   goto                 Loop2                   ;LED turned off long enough for
                   decfsz             COUNT2,1           ;us to see it turned off
                   goto                 Loop2                   ;

;****Now go back to the start of the program

                   goto                 Start                       ;go back to Start and turn LED                                                                            ;on again

;****End of the program****

end                                                                   ;Needed by some compilers,                                                  ;and also just in case we miss                                                  ;the goto instruction.

When I look at the 16F628 datasheet I see that 08h, and 09h where counter1 and 2 are, don't exist(unimplemented) This means I have to put them somewhere else right?

I would risk to say that instead of 08h I will put 9Ah, and instead of 09h I put 9Bh am I heading the right way?

Because 08h is EEDATA on the 16F84
09h is EEADR on the 16F84

On the 16F628 EEDATA is 9Ah, and EEADR is 9Bh.
What more do I have to change to make that work on the PIC16F628?

Thanks a lot.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 23, 2010, 11:06:15 AM
I'll assume you are using MPLAB and MASM from Microchip.

There is a much better method than using the EQU for the register addresses. There are header files for each PIC that have all of the registers names. These files are under the folder where MPLAB & MASM are installed. You can ope these to see the exact naming but almost all register names and bit names are the same as in the data sheets.

To use the headed file do:

#include <p16f628.inc>
or
#include <p16f628a.inc>
if you are using the A version of the PIC.

Now you don't need the EQU statement for any of the SFR's and the code becomes more portable to other PICs. You still need a way to reserve RAM for your own variables.
The next piece you need to check on going from the 16F84 to the 16F628 is the added features like UART, Comparator, etc. Carefully read the data sheet as any pin that can have an analog function is set to be analog on power up. Therefore you MUST disable that feature to use the pin for digital IO.

The code in the tutorial you are using is quite archaic. A better tutorial is:
http://www.gooligum.com.au/tutorials.html (http://www.gooligum.com.au/tutorials.html)
That does explain and use the header file.

Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 24, 2010, 04:45:02 PM
Hello thanks for your answer,

Yeah, shortly after opening this thread I realized that was quite old  :-\
Used CBLOCK, and then declared variables.

I have successfully "converted" the code though :P

I do however have a new doubt.
Code: [Select]
;*****Set up the Constants****

LIST P=16F628, R=DEC    ; Use the PIC16F628 and decimal system

#include "P16F628.INC"  ; Include header file

__config  _INTRC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON

CBLOCK 0x20             ; Declare variable addresses starting at 0x20
COUNT1,COUNT2
ENDC

;****Set up the port****
MOVLW 0x07
MOVWF CMCON
BSF              STATUS,RP0       ;Switch to Bank 1
MOVLW            0x1F
MOVWF            TRISA
MOVLW            00h              ;Set the Port B pins
MOVWF            TRISB            ;to output.
BCF              STATUS,RP0       ;Switch back to Bank 0



;****Main****

Start
BTFSC PORTA,0
FALSE RLF  PORTB
      CALL delay
      GOTO Start         
     
TRUE  RRF  PORTB
      CALL delay         
  GOTO  Start


;****50ms delay****
delay MOVLW 50
      MOVWF COUNT1
Outer MOVLW 200
      MOVWF COUNT2
Inner NOP
      NOP
      DECFSZ COUNT2,F
      GOTO Inner ; Inner Loop = 5uS
      DECFSZ COUNT1,F
      GOTO Outer
      RETURN
END                     

I want it to rotate right if the button isn't pressed, and rotate left if the button is pressed.

All it does right now is rotate right when the button is pressed, and when I stop pressing the button it no longer rotates at all, just one LED stays on.

Using MPLAB and WinPIC.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 24, 2010, 05:48:00 PM
Yep, that is what the code will do.
Some comments one your code.

Start                                 ;
BTFSC PORTA,0                ; Bit Test F Skip if Clear, bit 0
FALSE RLF  PORTB            ; Rotate Left if BTFSC doesn't skip
      CALL delay                 ; call delay if BTFSC does skip and after RLF
      GOTO Start                ; got back the Start
      
TRUE  RRF  PORTB           ; Never gets to this code.
      CALL delay          
     GOTO  Start

The Labels "FALSE" & "TRUE" are never used and can be deleted in the above code without changing the way the code executes.

To use the BTFSC and BTFSS instructions you need to have a way to select two branches of execution. Try this:

Start
BTFSC PORTA,0
    GOTO RotRight    ;
     RLF  PORTB        ; rlf if bit 0 is clear
      CALL delay
      GOTO Start        
  
RotRight    
      RRF  PORTB      ; rrf if bit 0 is set
      CALL delay          
      GOTO  Start

but do work out why this works and the posted code doesn't. The MPLAB Simulator is a good tool to see how your code executes. Always step through your code in the Simulator first. I catch 95% of my coding errors with the Simulator.
Also try to comment every line of code. I know this seems to be a pain but it does help you catch errors and 6 months later you'll you'll forgot what the code does unless its commented explaining what it is doing.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 24, 2010, 07:07:42 PM
haha, I was so close, but yet so far!  :D

Thanks  a lot  :)
It did create a weird side effect though, instead of it chasing one led at a time, it's chasing 2.
This is how it should be:

00000001
00000010
00000100
00001000
...
etc

But it's doing this:

00000011
00001100
00110000
11000000

I have no idea why, I'll try setting PORTB at 00h before i start the code.
I'm not comfortable using MPLAB SIM, I'm doing some more reading on that,
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 25, 2010, 10:49:54 AM
You are learning.
Now you just ran into the R-M-W (Read-Modify-Write) issue with output ports.
Here is a link explaining the issue and solutions:
http://www.microchip.com/forums/tm.aspx?high=&m=478014&mpage=1#478014 (http://www.microchip.com/forums/tm.aspx?high=&m=478014&mpage=1#478014)

There is some info in the Data Sheet about RMW but the above link is more complete.
That link is from the Flying With Hardware thread in the Microchip User's forum. There is also a Flying with Software thread. Here are the links:
http://www.microchip.com/forums/tm.aspx?m=358912 (http://www.microchip.com/forums/tm.aspx?m=358912)
http://www.microchip.com/forums/m391727.aspx (http://www.microchip.com/forums/m391727.aspx)

have fun.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 26, 2010, 09:03:55 AM
Aha! it's lighting the LEDs up one by one  ;D

Do you know how to use the MPlab simulator?

I keep getting this error:
Code: [Select]
CORE-W0014: Halted due to PC incrementing over the Maximum PC address and wrapping back to Zero
The program builds successfully, and I can burn it to the PIC, and it works, but it doesn't work on the simulator...  ???
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 26, 2010, 09:34:29 AM
Post the code. In the code you posted above it always goes back to checking the input. I'll guess that your code now can execute past the end of main.
The code should always have a loop in main.

;***********main************

; init ports and peripherals

MainLoop:

    ; code to read and write ports

    ; other code

    GOTO MainLoop

; ---end main---

Or another part of your code is escaping.

Are you single stepping in the SIM or just clicking RUN?
I believe you can still single step in the SIM without getting that error message.
Open the help in MPLAB and read about the SIM.

Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 26, 2010, 05:33:49 PM
Reinstalled mplab and it worked, have no idea what it was, but it's working now, if it happens again i'll have to dig deeper and find the source.

I don't have the code here, it's in the other computer(the one with the serial port) maybe it was just a bug, or bad settings.

Working on PWM right now  :)
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 26, 2010, 07:46:11 PM
Ok. Many have complained about MPLAB being buggy but so far its always worked for me. What version are you using?

Another Microchip document you may find helpful is the Mid-Range Family Reference Manual. It has some better explanations on the PIC peripherals than the data sheets. The PWM module is one it explains well.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 27, 2010, 01:21:49 AM
It does explain well there (http://ww1.microchip.com/downloads/en/devicedoc/33023a.pdf), but there's one thing I still don't get, how do I choose which pin to send the PWM signal to? Or is RB3/CCP1 the only pin able to have PWM?

I have this:
Code: [Select]
fadein
MOVLW  0x01       
MOVWF  CCPR1L  ; Put 1 into CCPR1L so it's not skipped straight away
INCFSZ CCPR1L  ; Increase CCPR1L
CALL   pause
GOTO   fadein  ; skipped if CCPR1L is 0
GOTO   fadeout ; goes to fadeout if CCPR1L is = 0

fadeout
MOVLW  0xFF
MOVWF  CCPR1L  ;Put 255 into CCPR1L so it's not skipped straight away
DECFSZ CCPR1L  ; decrease CCPR1L
CALL   pause
GOTO   fadeout ; skipped if CCPR1L is 0
GOTO   fadein  ; goes to fadein if CCPR1L is = 0
It should work
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 27, 2010, 07:06:59 AM
Correct, RB3/CCP1 is the only pin able to have PWM.

Code: [Select]
fadein
MOVLW  0x01       
MOVWF  CCPR1L  ; Put 1 into CCPR1L so it's not skipped straight away
INCFSZ CCPR1L  ; Increase CCPR1L
CALL   pause
GOTO   fadein  ; skipped if CCPR1L is 0
GOTO   fadeout ; goes to fadeout if CCPR1L is = 0

This code isn't quite right.
The INCFSZ instruction skips the CALL instruction if CCPR1L is zero not the GOTO fadein line.
Also the GOTO fadein goes back and writes 0x01 into CCPR1L every time through the loop so it will just get stuck writing a 0x01 then incrementing then writing a 0x01 and never exit.
The INCFSZ instruction does the increment first then tests for zero so the value could be initialized with a 0x00 and not skip.
Step through this in the SIM and you'll see.

Your comments do make it easy to see what you expect the code to do. Nice job.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 27, 2010, 10:04:10 AM
Hi,

Just before seeing your message I added another subroutine, after loading the starting point for CCPR1L.
Code: [Select]
fadein

MOVLW  0x01    
MOVWF  CCPR1L ; Put 1 into CCPR1L so it's not skipped straight away    
fadein2
 
INCFSZ CCPR1L  ; Increase CCPR1L
GOTO   fadein2  ; skipped if CCPR1L is 0
GOTO   fadeout ; goes to fadeout if CCPR1L is 0

fadeout

MOVLW  0xFF
MOVWF  CCPR1L ;Put 255 into CCPR1L so it's not skipped straight away
fadeout2
        
DECFSZ CCPR1L  ; decrease CCPR1L
GOTO   fadeout2 ; skipped if CCPR1L is 0
GOTO   fadein     ; goes to fadein if CCPR1L is 0
However this still doesn't work! In the simulator CCPR1L is incremented and decremented, but in the actual PIC it's only being incremented, and then goes back to being incremented... Lke this:

1
2
3
4
5
6
...
255
0
1
2
3
....


I thought that code would give something like:

1
2
3
4
5
...
255
254
253
252
...
3
2
1

I'll read and test it more, hopefully have it working :)

I do want PWM on more LEDs, nothing some multiplexing won't solve...

thanks for the responses by the way!  ;D

Possible problems
- No return at the end of the subroutines.
- No comma, and 1 after DECFSZ, and INCFSZ, Gonna try that now.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 27, 2010, 01:24:05 PM
In assembler you do need a return instruction at the end of sub-routines.

I think the default if the , 1 is not used is that the new value is back into the register. This is done by the assembler and you could look at the hex program code to see what the assembler does without the , 1. I like to explicitly have the destination in the code so always use either , f or , w. These should be defined in the header file and are easier to remember than  a 1 or 0.
Ok, I just tried your code and the assembler gave this message:
Message[305] C:\OLD_DRIVE_1-2010\DATA SHEETS\MICROCHIP\NEW SOFTWARE\F84_TEST.ASM 32 : Using default destination of 1 (file).
So if the , 1 is not stated then it is assumed.

Yes, your code does increment and then decrements CCPR1L. How are you determining that it is not decrementing when run on the PIC?
Is the duty cycle of the PWM output changing?

One problem I see is that you are probably incrementing CCPR1L through all values during only one PWM period. You had a delay in your first version of this code, in the wrong place but the delay is a good idea. Try putting it back in but arrange the code GOTO's to include the delay.
What is the time of the PWM period? I'd allow several periods to go by before changing the duty (CCPR1L). The new CCPR1L value is only latched into CCPR1H and used when TMR2 matches PR2 which is once per PWM period.

Another method is to use the TMR2 interrupt but maybe this is best left for the next lesson.

Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 27, 2010, 02:58:53 PM
It still doesn't work with the return.  :-X
Quote
How are you determining that it is not decrementing when run on the PIC?

I have a 20ms delay in the code, so 20X255 = 5.1s to go from off to on, and from on to off it goes abruptly.(Wrote the code at the top without copy/paste, forgot the delay :P )

I have the delay after DECFSZ.

EDIT:
Put the delay before increasing, and decreasing F, it works!  :D
Still not perfect, it seems to be skipping something that it shouldn't, but it looks okay  ;D
Code: [Select]
fadein

MOVLW  0x01     
MOVWF  CCPR1L ; Put 1 into CCPR1L so it's not skipped straight away   

fadein2
CALL pause ;20ms
INCFSZ CCPR1L  ; Increase CCPR1L
GOTO   fadein2  ; skipped if CCPR1L is 0
GOTO   fadeout ; goes to fadeout if CCPR1L is 0

fadeout
MOVLW  0xFF
MOVWF  CCPR1L ;Put 255 into CCPR1L so it's not skipped straight away

fadeout2
CALL pause ;20ms       
DECFSZ CCPR1L  ; decrease CCPR1L
GOTO   fadeout2 ; skipped if CCPR1L is 0
GOTO fadein


I also came up with this:
Code: [Select]
Loop
    INCF CCPR1L  ;Increase duty cycle
    MOVF     REG1,F  ;Move CCPR1L value to REG1 for maths
Loop1
    call pause   ; pause...
    MOVLW   255      ;Move 255 to W
    SUBWF    REG1,F  ;Subtract W(255) with F
    BTFSC     REG1,F  ;if CCPR1L is 255, subtracting 255 will give us 0, so it skips, and goes to fadeout.
    GOTO      Loop1
    GOTO fadeout

fadeout
        CALL pause
DECF CCPR1L
GOTO fadeout
        GOTO Loop

Never got it to work though.

Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 27, 2010, 08:38:03 PM
Ok, the delays on both dec and inc are needed. Do you understand why?

You are making very good progress learning that PIC.
In the second code you just posted you are using a subtract instruction. These are the most confusing instructions in the PIC. Take your time to study to doc on subtraction and then use the SIM to figure out what it really does. I think you can get it to work.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on July 28, 2010, 06:02:44 AM
Quote
Do you understand why?
each instruction takes very little time, 200ns in this case if i'm not mistaken, so 200ns+255 = 51 micro seconds, the human eye can't see it happening.

I think I know why it doesn't look perfect yet.
Code: [Select]
fadein2
CALL pause ;20ms
INCFSZ CCPR1L  ; Increase CCPR1L
GOTO   fadein2  ; skipped if CCPR1L is 0
GOTO   fadeout ; goes to fadeout if CCPR1L is 0

When it gets to 0, the LED is off for 20ms , can't let it go off for that long.
Quote
These are the most confusing instructions in the PIC

Definitely :P but quite useful.

If it gets too much I will get a C compiler, already know a fair bit of C.

Gonna get that code with SUBWF to work, after not letting the duty cycle reach 0 for 20ms, so it's a smooth transition both increasing and decreasing the duty cycle.

Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on July 28, 2010, 07:39:02 AM
Quote
Quote
Do you understand why?
each instruction takes very little time, 200ns in this case if i'm not mistaken, so 200ns+255 = 51 micro seconds, the human eye can't see it happening.

That's true but there is another factor. What is the period of the PWM, the PR2 value when you set up the CCP module?
If its less the the time between setting a new, dec/incr, value in CCPR1L then that value is not used. CCPR1L is only loaded into CCPR1H at the end of a complete PWM period or when the TMR2 timer matches the PR2 register. Re-read the data sheet and study the block diagram.
So to have a pulse width for each of the dec/incr value you need the code to wait at least one PWM period before writing a new value.

To learn the Subtract instructions, SUBLW & SUBWF, write code to use them and try different value. Make this a separate program just for testing the subrtact instructions. Use the SIM to watch what happens in each register and also watch the Status flags, C, DC & Z. Keep notes on the values and results and also do the binary math manually.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: amando96 on August 04, 2010, 04:55:12 PM
Hi,
Got away from assembly, and started to program it in C, because it's a higher level, it seems like less of a headache, I'm not giving up on assembly, it seems like good knowledge to have, but in C I think I'll move forwards faster.

I have been using arduino C so far, which is simpler than C...
I got this small code from the internet, and modified it just to play around and get to know this type of C better.
Code: [Select]
#include <pic.h>
#include <HTC.h>
__CONFIG(0x3FF0);

void delay(void);

void main(void) {
TRISB = 0x00;
while (1)
{
PORTB++;
delay();
}
}

void delay(void) {
unsigned int i;
for (i=0; i<10000; i++);
}

As soon as the binary count gets to 15(00001111) it resets back to 0, I'm not sure what causes this.
What does the "__CONFIG(0x3FF0); " mean? by googling it all I found was the website where I got the code from, and I didn't find an explanation there.
Title: Re: Changing ASM code for PIC16F84 to PIC16F628.
Post by: waltr on August 04, 2010, 06:15:53 PM
Look in the PIC data sheet in the Special Features of the CPU, Ch14. The configuration bits are explained there. I'll leave it for you to decode the bits.

It looks like you are using the Hi Tech compiler so there is a much better way to set the config bits in your code. the line would look like this:

__CONFIG( UNPROTECT & LVPDIS & BORDIS & MCLREN & WDTDIS & HS);

Now it is very clear as to what the config bits are and what is or is not enabled.
You will need to use the DS and look in the pic16f62xa.h file that is located in the HiTech's include folder to learn the names for the config bits. That include file also has all the names for the registers and the bits in the registers.

If I didn't give you the Googlium tutorials link it is:
http://www.gooligum.com.au/tutorials.html (http://www.gooligum.com.au/tutorials.html)
It does go over using the HiTech compiler and even the use of the config statement..