TMR0 Problem

Jugurtha

Member
Hello,

Here's the code for the stepper motor controller at the end of this post. The forum has not line numbering, so here's the link to a paste :

https://pastebin.com/wYxeYszV


Lines 179 to 181

Code:
  clrf TMR0               ;Clearing TMR0
           
    goto START          ;Here we go..

This lands us on Start, line 207.

Code:
START   btfsc   TMR0,7 ; Bit Test File TMR0, 7 Skip Next Instruction If Clear.
                       ; In the original code, it was BTFSS. Which doesn't make sens.
                       ; Because we've just cleared TMR0, so TMR<7>=0 , so GOTO START
                       ; gets executed in a never ending loop.
                       ; Although, I have to figure out this TMR0 thing later.
                       ; Its purpose, and all.
 
                       ; Test the 7th bit of TMR0, and skip the goto START if it's 0
                               
                                           ; 4.1 TMR0 Operation (Page 17 of Datasheet):
                                           ; Counter Mode or Timer Mode.
 
 
                                goto START ; Only if TMR0<7>=1
                                clrf TMR0  ; Clear TMR0 (All bits 0)


Bear with me: TMR0 is set on Timer Mode (OPTION_REG:5 cleared).

From the datasheet, TMR0 is incremented each instruction cycle, but I do not see any change. It's always 0.

This, and if it did .. It would never reach 128 as we're checking the 7th bit of TMR0 .. So why include the btsfc TMR0, 7 if it's a condition that will never happen. Why not just execute that instruction ?

Second question: At the end of the code, the original code that was provided by the teacher. You'll notice that it was a btfss TMR0, 7.

This didn't work, hence me changing it to BTFSC TMR0,7..

So the natural question is .. Questionning my assumptions and going "Wait a minute .. Why did I even left that TMR0". So I commented every instruction involving it, and the code runs fine (Checked in Proteus and in MPLAB).

So, was that really a trick from him and it's useless, or am I ignorant (my logic seems fine thought) as to the use of TMR0 here ? I don't think we need it in this application.

What do you think. It works, but why did he put it there?

Here's the neat new code (removed all comments and removed TMR0 stuff) and it works.

Code:
	errorlevel -302	

	LIST p=16F84A              
	#include "p16F84A.inc"	   
    

	__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC       
    
	

#define RIGHTBUTTON PORTA,0
#define LEFTBUTTON  PORTA,1



#define SETPHASE0 retlw B'00001001'
#define SETPHASE1 retlw B'00001010'
#define SETPHASE2 retlw B'00000110'
#define SETPHASE3 retlw B'00000101'


		cblock 0x0C           

	  		STEP:1  

    	endc
     
	
		org 0x00    

	    	goto ENTRYPOINT

        org 0x04    
    
	ENTRYPOINT
    
    

    banksel TRISB           
	
    movlw 0x00               
    movwf TRISB              
       
    movlw 0xFF               
	movwf TRISA              
    
    movlw 0x96               
	movwf OPTION_REG         
 
	banksel PORTB 
    
	movlw 0x00
    movwf TRISB 
    
	clrf STEP	
	
    goto START	



SEQUENCE	 addwf PCL,f 
   
	SETPHASE0           
	SETPHASE1           
	SETPHASE2           
	SETPHASE3           

START	


RIGHT	
        
        btfsc	RIGHTBUTTON 
        goto 	LEFT
		incf	STEP,f  
		movlw	0x04    
		subwf	STEP,w  
	
		btfsc	STATUS,C 
		clrf	STEP     
		movf	STEP,w   
		call	SEQUENCE 

        movwf PORTB     
		
        goto	 START


LEFT	

        btfsc	LEFTBUTTON 
		goto 	START
		decf	STEP,f  
		movlw	0x03    
		btfsc	STEP,7  
		
        movwf	STEP    
 		movf	STEP,w  


		call	SEQUENCE 

        movwf PORTB

		
        goto	START

	end



Here's the old one (which worked too, but had cargo cult TMR0).


Code:
;***********************************************************************************
;*                            Stepper Motor Control v1.5                           *
;*                             PIC16F84A & ULN2003                                 *
;*                                                                                 *
;*                         Jugurtha Hadjar & Raouf Moualdi.                        * 
;*                 4ème Année Ingénieur Instrumentation U.S.T.H.B                  *
;*                                                                                 *
;*          Université des Sciences et de la Technologie Houari Boumédiène.        *
;*                                                                                 *
;*               Contact: Remove capital letters from the address.                 *
;*              REMOVEMEjugurtha.haSPAMdjarSPAM@REMOVEMEhotmail.com                *
;*                             http://docs.com/@jhadjar                            *
;***********************************************************************************

;***********************************************************************************
;* Description:                                                                    *
;* TEC 585 Project00: Stepper Motor Control using PIC1684A                         *
;* A ULN2003 (7 Darlington Array) is used as an interface.                         *
;* Two push-buttons to make the motor rotate to the LEFT or to the RIGHT.          *
;*                                                                                 *
;* Original code provided courtesy of my teacher, Mr Bouchefra, and put as a       *
;* comment for memo at the end of this file, to keep track of modifications.       *
;* It contains errors intentionally slipped by the teacher to stimulate learning.  *
;*                                                                                 *
;***********************************************************************************



	errorlevel -302	; Kill bank selection warnings.
			; I had to deal with 205: Found directive in column 1 which means
			; directives must not be in the first column of the code. Use tab.

;***********************************************************************************
;*                                   THE SETUP                                     *
;***********************************************************************************

	LIST p=16F84A              ;Which processor ?                                             
	#include "p16F84A.inc"	   ;Where's the file?                                             
                                        												  

	__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC       
    
	;Code Protection OFF
	;Watchdog Timer  OFF
	;Power Up Timer  ON
        ;RC Oscillator.
        ;__CONFIG H'3FF9'


;************************************************************************************
;*		              CONFIGURATION BITS				    *
;************************************************************************************

; PAGE 21 of the DATASHEET DS35007A - PIC16F84A, Chapter 6.1 - Configuration Bits
; Programmed   : Read 0
; Unprogrammed : Read 1

; Mapped in memory location 2007h: (Test/Configuration memory space 2000h-3FFFh)

; Bit 13:4  CP: Code Protection Bit (0: Protected, 1: CP off)
; Bit 3 : ~PWRTE(Active Low): Power-Up Timer Enable Bit (1: Disabled, 0: Enabled) 
; Bit 2 : WDTE: Watchdog Timer Enable Bit (1: WDT Enabled, 0: WDT Disabled)
; Bit 1:0 : FOSC1:FOSC0 Oscillator Selection Bits:
;			11 RC : Resistor/Capacitor
;			10 HS : High Speed Crystal/Resonator
;			01 XT : Crystal/Resonator
;			00 LP : Low Power Crystal            

; See Page 22 of said datasheet.
; In our case, the word is : 3FF9, we dismiss two bits since it's a 14bit core
; 11 1111 1111 1001
; We notice the Oscillator selection bits are wrong, they should be 11.
; The word should be : 3FFBh instead of 3FF9h  (This was confirmed in Proteus ISIS

	

;************************************************************************************
;*                                  EQUATES                                         *
;************************************************************************************

;STEP   EQU 0x0C      ; This line doesn't pretty much have a meaning,
					  ; SINCE we would do a CLRF STEP before the loop.
					 


; Assigning names to PINs so that if we'd like to change their disposition, we will
; only have to change them in here, instead of replacing all occurences in the code.
					 
#define RIGHTBUTTON PORTA,0
#define LEFTBUTTON  PORTA,1

;#define RIGHTLED    PORTB,6
;#define LEFTLED     PORTB,7



;**********************************
;       Stepper Motor Phases      *
;---------------------------------*

;Assigning names to phases to see the program flow better.

#define SETPHASE0 retlw B'00001001'
#define SETPHASE1 retlw B'00001010'
#define SETPHASE2 retlw B'00000110'
#define SETPHASE3 retlw B'00000101'
;*********************


;**********************************************************************************               
;* See chapter 2.2 Data Memory Organization, Page 6 & 7, Figure 2-1.			  *
;* TRISB is the PORTB data direction register. It's on 8 bits.                    *
;* Clearing TRISB configures the PORTB as an OUTPUT.(Bits can be set/cleared      *
;* individually to configure each I/O port separately. RB0,RB1,...,RB7            *
;**********************************************************************************




		cblock 0x0C           
		                
	  		STEP:1         ; The byte at 0x0C:STEP.
                     
    	        endc
     
	
		org 0x00              	   ;Reset Vector. See Page 5: Program Memory Map and Stack

	    	goto ENTRYPOINT

        org 0x04                   ;Interrupt Vector, see Page 5.
        


ENTRYPOINT
    
    ; TRISA & TRISB are the Data Direction Registers, used to set whether a pin (thus a port)
    ; is an input or an output.    


    banksel TRISB            ; Selecting Bank 1 (TRISB is in BANK1)
			     ; This is equivalent to doing BSF STATUS, RP0
    	
    movlw 0x00               ; Load W with 0x00 
    movwf TRISB              ; All bits to 0. (TRISB=00000000)  PORTB OUTPUT.
                             
                    
    ;banksel TRISA           ; This wasn't needed since we're already in BANK1.
    
    movlw 0xFF               ; Load W with 0xFF. 
    movwf TRISA          ; All bits to 1. (TRISA=11111111)  PORTA INPUT.
                              
    movlw 0x96               
    movwf OPTION_REG     ; Configure OPTION_REG (81h in Bank1).
	
	; PAGE 15: Each of PORTB pins has a weak pull-up. These are disabled automatically
	; when the port is configured as an output, which is the case here.
 
;******************************************************************************************
;*                             OPTION_REG Description                                     * 
;*----------------------------------------------------------------------------------------*
;* Bit7:RBPU(active low) PORTB Pull-Up Enable Bit (1, Disabled)                           *
;* Bit6:INTEDG, Interrupt Edge Select Bit(0, Interrupt on falling edge B0/INT)            *
;* Bit5:T0CS, TMR0 Clock Source Select Bit (0, Internal Instruction Cycle Clock)          *
;* Bit4:T0SE, TMR0 Source Edge Select Bit(1, Increment on Hi-to-Lo transition on RA4)     *
;* Bit3:PSA,PRESCALER Assignment Bit(0, Prescaler assigned to TMR0 module)                *
;* Bit2:0: PRESCALER Select Bits (110, 1:128)                                             *
;******************************************************************************************




	banksel PORTB ; Selecting Bank0
    
	movlw 0x00
        movwf TRISB ;All PORTB pins to 0.
    
	clrf STEP		;Clearing STEP at 0x0C 
	clrf TMR0		;Clearing TMR0
	    
    goto START		;Here we go..


;******************************************************************************************
;*                        MOTOR SEQUENCE: PHASES (In Program Memory)                      *
;******************************************************************************************
        
            ;Computed GOTO. We add w to PCL.        
            ;This is the sequence used to control the motor.
            ;It's a Table in the program memory
			;When a call gets with an offset value loaded in w
			;We then add the Program Counter low 8bits to that value,
			;The result is branching to the new value of PCL.
			;See Application Note 556 "Implementing a Table Read"
			;Stan D'Souza , Microchip Inc .

SEQUENCE	 addwf PCL,f    ; Adds W to the PC Low 8 bits. The location
                                ; of the next instruction is computed that way.
        
	SETPHASE0           ;Return With Literal in W 0x09. With an initial w of 0x00
	SETPHASE1           ;Return With Literal in W 0x0A. With an initial w of 0x01
	SETPHASE2           ;Return With Literal in W 0x06. With an initial w of 0x02
	SETPHASE3           ;Return With Literal in W 0x05. With an initial w of 0x03

;***************************************************************************************

START	btfsc   TMR0,7 ; Bit Test File TMR0, 7 Skip Next Instruction If Clear. 
                       ; In the original code, it was BTFSS. Which doesn't make sens.
                       ; Because we've just cleared TMR0, so TMR<7>=0 , so GOTO START
                       ; gets executed in a never ending loop.
                       ; Although, I have to figure out this TMR0 thing later. 
                       ; Its purpose, and all.

                       ; Test the 7th bit of TMR0, and skip the goto START if it's 0
				
					   ; 4.1 TMR0 Operation (Page 17 of Datasheet):
					   ; Counter Mode or Timer Mode.


				goto START ; Only if TMR0<7>=1
				clrf TMR0  ; Clear TMR0 (All bits 0)




;**************************************************************************************
;*                                RIGHT SUBROUTINE                                    *
;**************************************************************************************
;This makes the motor turn right when RA0 is pulled down.(button pushed and kep down) 

RIGHT	
        
        btfsc	RIGHTBUTTON ;Test RA0. If it's Zero, skip to Incf. If it's 1, goto left.
        goto 	LEFT
		incf	STEP,f  ;Increment the value held in STEP (address 0x0C)
		movlw	0x04    ;Move literal to W (0x04-->w)
		subwf	STEP,w  ;Substract w from f, the result goes to w. f-w--->w
		     						
		btfsc	STATUS,C ;Test the Carry bit(flag) of STATUS register
		clrf	STEP     ;Clear STEP
		movf	STEP,w   ;STEP---->w
		call	SEQUENCE ;Wondering what this does ? 

        movwf PORTB     ;w---->PORTB. Outputs whatever value was in w to PORTB pins.
		
        goto	 START

;**************************************************************************************
;*                                 LEFT SUBROUTINE                                    *
;**************************************************************************************
;This makes the motor turn lefht when RA0 is pulled down.(button pushed and kept down)*

LEFT	

        btfsc	LEFTBUTTON ;Test RA1, Goto start if it's 1.
		goto 	START
		decf	STEP,f  ;f-1---->f
		movlw	0x03    ;0x03--->w
		btfsc	STEP,7  ;Test STEP<7> , skip next instruction if clear.
		
                movwf	STEP    ;Why are we doing this ? movwf STEP then movf STEP, w. Killing time ?
 		movf	STEP,w  ;It's because movwf STEP gets executed only the first time
                                ;When STEP=0-1 (decf STEP) = 0xFF = 11111111

		call	SEQUENCE ;We call SEQUENCE, where we'll add the low 8 bits of the 
                                 ;Program counter to W to do a computed goto.
        movwf PORTB              ;Loads PORTB with the value of w.
                         
		
        goto	START

	end	







;****************************************************************************
;                     LOG: Code Updates, Rambling & Rants                   *
;****************************************************************************
;
;
;Tuesday December 8th, 2011:
;I put the RIGHT subroutine as a comment, so that there's only the LEFT subroutine
;that will be executed.
;RA1 is pulled up to 5V by a 10K resistor, and as long as the push-button isn't pushed
;RA1 is logical 1, so the BTFSC PORTA,1
;                         GOTO  START
;It always hooks to START and starts all over again.
;Now We push the push-button (LEFT), we pull down RA1. And the program skips GOTO START
;because RA1 is 0. And the program does its stuff.
;PORTB = 00000101 , 00000110, 00001010, 00001001, then cycles again 00000101,. 

;Then I'll put the LEFT subroutine as a comment, and do the same thing to check it out.
;RIGHT and LEFT subroutine work.



;Friday December 9th, 2011:
;-Added some macros and got rid of 'hardcoded' literals to make the code
; more easily reusable elsewhere.
;-Changed the place of LOG to the end of file for clarity.
;-Defined RA0 as RIGHTBUTTON, and RA1 as LEFTBUTTON.


;Saturday December 10th, 2011
;Some bugs slipped in the code and went undetected.
;The code compiled successfully, but I didn't test it
;if it works. It didn't, but does now.

;-Bugs in v1.3 fixed in v1.4:
; -SEQUENCE was in the wrong place (before GOTO START)
; -mSelectBank1 macro was declared as such 
;  but invoked as mBankSelect1 and didn't work obviously.
; -mOPTION_REGConfigure was invoked as such, but the register
;  in the macro was CONFIG_REG, which doesn't exist as far
;  as I know.

;RULE1: -In macros, Always start with a VERB. This way, if invoking 
;        a macro doesn't start with a verb, I'll immediately know.(crossing fingers)
;        -Macros start with a lower case 'm'.

;Thursday December 13th, 2011: v1.5
; -Macros related to Bank Selection were deleted, as there already
;  is a directive  to deal with that. "banksel". 
;  Thanks to Jon Wilder on ETO for bringing this to my attention.


;                              ********************************
;                              *      BANK RELATED MACROS     *
;                              ********************************
    
    ;mSelectBank0 macro
	;			 bcf STATUS,RP0
    ;             endm        

	;mSelectBank1 macro
    ;             bsf STATUS,RP0
    ;             endm

;******************************************
;* RP0 is the Bank Select Bit (in STATUS).*
;* We chose the Bank1 by setting it to 1. *
;* And chose Bank0 by setting RP0 to 0  . *
;******************************************











;*****************************************************************************
;*                          ORIGINAL CODE                                    *
;*****************************************************************************

;LIST p=16F84A

;#include p16F84A.inc
;;_CONFIG H'3FF9'
;__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC

;Pas EQU 0x0C

;	org 0x00
;	bsf STATUS, RP0
;	clrf TRISB


;    movlw B'11111111'
;	 movwf TRISA
;		movlw B'10010110'
;		movwf OPTION_REG
;	bcf STATUS,RP0
;	clrf PORTB
;		clrf Pas
;		clrf TMR0
;		goto Debut

;Table	addwf PCL,f
;			    retlw B'00001001'
;			    retlw B'00001010'
;			    retlw B'00000110'
;               retlw B'00000101'

;Debut	btfss   TMR0,7
;				goto Debut
;				clrf TMR0

;Droite	btfsc	PORTA,0
;		goto 	Gauche
;		incf	Pas,f
;		movlw	0x04
;		subwf	Pas,w
;		btfsc	STATUS,C
;		clrf	Pas
;		movf	Pas,w
;		call	Table
;		movwf	PORTB
;		goto	Debut

;Gauche	btfsc	PORTA,1
;		goto 	Debut
;		decf	Pas,f
;		movlw	0x03
;		btfsc	Pas,7
;		movwf	Pas
;		movf	Pas,w
;		call	Table
;		movwf	PORTB
;		goto	Debut
;end
;****************************************************************************
 
Last edited:
With 0x96 as the option_reg value, there is a prescale of 128 on TMR0. So that means that TMR0 will change in the simulator, but only after 128 steps.

I think that TMR0 is simply used as a start-up timer, with the original btfss command.

When TMR0 is cleared at the start, bit 7 is clear, so the code keeps cycling back to "START", until TMR0 has counted up to 128, which takes 128 x 128 = 16384 cycles.

I don't know enough about the application to know why a start-up delay was wanted as there is one already on the 16F84
 
Thanks for your answer, Diver..

Eventually, like I said .. We don't need it here. I removed it and everything works fine. However, we can need it to "wait" before two pulses to let the rotor settle in its new position.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…