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
This lands us on Start, line 207.
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.
Here's the old one (which worked too, but had cargo cult TMR0).
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: