Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ASM code and tips.

Status
Not open for further replies.

RedCore

New Member
Here is a ASM program I have written. I'm basically looking for tips and help with structure or anything. I havent been able to test this yet as I dont have a PIC/Programmer. I have simulate it with MPLAB IDE and everything looks fine other than when I loop to wait for TXIF to get set (The serial transmission was complete) the simulate loops forever.. But i suspect this to be a problem with something else. (Simulation or something?)

I would mainly like any tips with anything you see or if you have a better way of doing it.. Dont hesitate to say "Thats a stupid way to do..."

Code:
      	;Testing and Simulation


	LIST	P=PIC16F877		;tell assembler what chip we are using
	include "P16F877.inc"		;include the defaults for the chip
	__config 0x3D18			;sets the configuration settings 
					;(oscillator type etc.)

;Yay for Variables!

	TEMPW	EQU     H'20'   	;This is the start of the General Registers.

	Motor0	EQU	H'21'		; Motor0 speed
	Motor1	EQU	H'22'		; Motor0 speed


	org	0x0000			;org sets the origin, 0x0000
	goto 	main			;this is where the program starts running	



	org	0x0004			;org sets the origin, 0x0004
	goto	IntH			;this is where interrupts are vectored	



main
	movlw	0x07
	movwf	CCP1CON			;turn off CCP

	;select bank 1
   	bsf 	STATUS,		RP0	;set RP0
	bcf 	STATUS,		RP1	;clear RP1



	;set PortX(all ports) all outputs

   	movlw 	b'00000000'
   	movwf 	TRISE
   	movwf 	TRISD
   	movwf 	TRISC
   	movwf 	TRISB
	movwf	TRISA
	bsf	TRISB,		0	; Using RB0/INT as interrupt here.

	;Lets Timer0 this baby.  Yeah uh I dont have a internal clock..
	;  I'll fix this someday.
	bcf	OPTION_REG,	T0CS	; Use interal CS for T0


	bsf	OPTION_REG,	INTEDG	; Interrupt Edge trigger.


	;Lets play with INTCON (Interrupts)  Either banks

;   	movlw 	b'10010000'		;Enable Interrupts. Timer0 overflow.
;   	movwf 	INTCON			;Maybe better to do bitwise ops?

	bsf	INTCON, 	GIE
	bsf	INTCON, 	INTE
	bcf	INTCON, 	INTF



	; Serial stuff

	movlw	d'30'
	movwf	SPBRG			; Set the baud rate.

	;TXSTA
   	bcf	TXSTA,		TX9	;8bit transmission
	bsf	TXSTA,		TXEN	;Transmit Enable bit
	bcf	TXSTA,		SYNC	;Asynchro mode   idk?
	bcf	TXSTA,		BRGH	;low speed baud rate


	;select bank 0
   	bcf 	STATUS,		RP0	;clear RP0
	bcf 	STATUS,		RP1	;clear RP1


	;RCSTA  - Its in bank 0
   	bsf	RCSTA,		SPEN	;Serial Port Enable. Do I need this? sure..
	bcf	RCSTA,		RX9	;8bit receive
	bcf	RCSTA,		CREN	;Continous Receive disable





	;Move forward... forever..
	call	Forward


Loop	
	movlw	0xff
	movwf	PORTA			;set all bits on
	movwf	PORTC

	movlw	0x00
	movwf	PORTA
	movwf	PORTC			;set all bits off
	goto	Loop			;go back and do it again




Forward
	movlw	b'111111'
	movwf	Motor0
	movwf	Motor1
	call	gomotor0
	call	gomotor1
	return
	

gomotor0

	call	SerStart
	call	SerChk

	movlw	b'0000001'
	movwf	TXREG

	call	SerChk

	movfw	Motor0
	movwf	TXREG
	return

gomotor1

	call	SerStart
	call	SerChk

	movlw	b'0000001'
	movwf	TXREG

	call	SerChk

	movfw	Motor0
	movwf	TXREG
	return





SerStart

	movlw	0x80
	movwf	TXREG

	call	SerChk

	movlw	0x00
	movwf	TXREG	

	return


SerChk
	btfss 	PIR1,		TXIF	;Test if the data has been sent to buffer
	goto	$-1			; Does this work?
	return


;----Our Interrupt Handler will go here.----;

IntH
	movwf	TEMPW

	nop	
	nop
	nop
	nop

	bcf	INTCON,		INTF	;Lets set thing back..
	movfw	TEMPW              	;Restore w
	RETFIE
	




	end
 
In the IntH routine I think you should have something like this:

movwf w_safe ; save context
swapf STATUS,W ;
movwf status_safe ;

;ISR code

swapf status_safe,W ; restore context
movwf STATUS ;
swapf w_safe, F ;
swapf w_safe,W ;

retfie
 
Code:
SerChk
    btfss     PIR1,        TXIF    ;Test if the data has been sent to buffer
    goto    $-1            ; Does this work

Would a "goto SerChk" be better than a "goto $-1" make it easier to read?
 
Thanks for the reply guys. I didnt want to implement saving the status register unless i was sure it might change. As for the $-1 i mainly wanted to play with the PC(In my first implentation it was necessary, now.. not so much)

One thing I do want to do is change how i handle the motor speed. I have Motor0/1 to store the current motor speed but what i want to implement is a loop that checks to see if the current motor speed(CurMotor0/1) is the same as Motor0/1 if it is not then it updates the motors by sending the data to the motor controller, else it does not update. The problem with that is I see no way to check if the two registers are the same without doing alot of individual bit tests. Easier method???
 
I have simulate it with MPLAB IDE and everything looks fine other than when I loop to wait for TXIF to get set (The serial transmission was complete) the simulate loops forever.. But i suspect this to be a problem with something else.
It works in the SIM as it should. It's just that it takes apx 5000 instruction cycles. Rather than clicking on the mouse 5000 times in MPLAB, right click at the "return" function (bolded below) and choose "run to Cursor". If you have the "debugger/stopwatch" enabled you'll see that it takes apx 4955 cycles for the PIR1 TXIF bit to get set:

SerChk
btfss PIR1, TXIF ;Test if the data has been sent to buffer
goto $-1 ; Does this work?
return
 
Thanks for helping kchriste. I've changed this section of code and I tried running the simulation as you said and still it seems to loop forever.

I added this and the appropriate variables and a call to ths update in my main loop. The rest is basically unchanged.

Also, Since it takes soo many cycles to complete the serial output.. Should I worry about motor0 turning on long before motor1 causing the robot to turn?
This could be a problem..

Code:
	;Check to see if we want the speed changed. If so, Change it.
UpdateMotors

updm0
	movfw	CurMtr0			; Current motor speed in W
	xorwf	Motor0,		0	; Xor Current motor speed with wanted motor speed
	btfsc 	STATUS,		Z	;Test if the last operation resulted in 0
	goto	updm1			;Skip to motor1 check if we dont need to update M0
	call	SerStart
	call	SerChk
	movlw	b'0000001'
	movwf	TXREG
	call	SerChk
	movfw	Motor0
	movwf	TXREG

updm1
	movfw	CurMtr1			; Current motor speed in W
	xorwf	Motor1,		0	; Xor Current motor speed with wanted motor speed
	btfsc 	STATUS,		Z	;Test if the last operation resulted in 0
	return				;Return if we dont need to update M1
	call	SerStart
	call	SerChk
	movlw	b'0000011'
	movwf	TXREG
	call	SerChk
	movfw	Motor1
	movwf	TXREG

	return
 
Hi RedCore,

Instead of jumping to an INT handler from address 0x04 using Goto, why not place the INT handler right at address 0x04 and so you only need a single jump instruction at address 0x00 to jump to the Main program at reset.

There are other advantages and consideration in doing so but you will find out why very soon.
 
Thanks for helping kchriste. I've changed this section of code and I tried running the simulation as you said and still it seems to loop forever.
No problem. When you update your code and need help with it , paste the entire code. If I try to reconstruct it based on my interpretation I will most likely get different code from what you have and any advice I give will be meaningless and only confuse matters.
Also, Since it takes soo many cycles to complete the serial output.. Should I worry about motor0 turning on long before motor1 causing the robot to turn?
There are two solutions to this.
Easy way (And not as efficient but may be good enough):
Send the left and right motor values via the serial port AFTER updating BOTH motor speeds.
Harder way:
Send your serial data via a circular buffer and ISR routine so serial data processes happen in the background....
 
RedCore said:
Also, Since it takes soo many cycles to complete the serial output.. Should I worry about motor0 turning on long before motor1 causing the robot to turn?
This could be a problem..

It's not a concern at all, mechanical processes (like the motors) are so incredibly slow that the PIC can do hundreds of thousands of instructions between motor updates.
 
kchriste: This is my full code. The reason the program loops when checking TXIF is becuase in debugger->settings->limitations, It says "Serial I/O is not simulated". I'm not sure why. I'm also not sure what you mean when you say Circular buffer, but I'll figure it out.
Thanks.

Nigel: Thanks for the info, helps alot..

Also, I appreciated yall taking the time to help, I know yall have plenty of other things to do. Thanks for helping the community out.


Code:
;***********************************************;
;	First PIC program			;
;	   					;
;	Implented a Motor Controller		;
;						;
;						;
;						;
;************************************************
    					;Testing and Simulation
	LIST	P=PIC16F877A		;tell assembler what chip we are using
	include "P16F877A.inc"		;include the defaults for the chip
	__config 0x3D18			;sets the configuration settings 
					;(oscillator type etc.)


;****** Variables **************************************************************

	TEMPW	EQU     H'20'   	;This is the start of the General Registers.

	Motor0	EQU	H'21'		; Motor0 speed
	Motor1	EQU	H'22'		; Motor1 speed

	CurMtr0	EQU	H'23'		; Current Motor0 speed
	CurMtr1	EQU	H'24'		; Current Motor1 speed


	org	0x0000			;org sets the origin, 0x0000
	goto 	main			;this is where the program starts running	



	org	0x0004			;org sets the origin, 0x0004
	goto	IntH			;this is where interrupts are vectored	



main
   	bsf 	STATUS,		RP0	;set   RP0
	bcf 	STATUS,		RP1	;clear RP1	This selects Bank 1

   	movlw 	b'00000000'		;Set all ports to output
   	movwf 	TRISE
   	movwf 	TRISD
   	movwf 	TRISC
   	movwf 	TRISB
	movwf	TRISA
	bsf	TRISB,		0	; Using RB0/INT as interrupt here.

	bcf	OPTION_REG,	T0CS	; Use interal CS for T0
	bsf	OPTION_REG,	INTEDG	; Interrupt Edge trigger.

	bsf	INTCON, 	GIE	;Global Interrupt Enable   (set)
	bsf	INTCON, 	INTE	;External Interrupt Enabel (set)
	bcf	INTCON, 	INTF	;External Intterupt flag

	movlw	d'30'
	movwf	SPBRG			;Set the baud rate.

   	bcf	TXSTA,		TX9	;8bit transmission
	bsf	TXSTA,		TXEN	;Transmit Enable bit
	bcf	TXSTA,		SYNC	;Asynchro mode   idk?
	bcf	TXSTA,		BRGH	;low speed baud rate

   	bcf 	STATUS,		RP0	;clear RP0
	bcf 	STATUS,		RP1	;clear RP1	This will select bank 0

   	bsf	RCSTA,		SPEN	;Serial Port Enable. Do I need this? sure..
	bcf	RCSTA,		RX9	;8bit receive
	bcf	RCSTA,		CREN	;Continous Receive disable

	movlw 	0x00			;Set the default speed for M0
   	movwf 	CurMtr0	 		;Set the default speed for M1
   	movwf 	CurMtr1			

	movlw 	0x30			;Set the default speed for M0
   	movwf 	Motor0	 		;Set the default speed for M1
   	movwf 	Motor1			

Loop	
	movlw	0xff
	movwf	PORTA			;set all bits on

	call UpdateMotors		; Update the motor speeds if needed

	movlw	0x00
	movwf	PORTA			;set all bits off
	goto	Loop			;go back and do it again




	
UpdateMotors				;Check to see if we want the speed changed. If so, Change it.

updm0
	movfw	CurMtr0			; Current motor speed in W
	xorwf	Motor0,		0	; Xor Current motor speed with wanted motor speed
	btfsc 	STATUS,		Z	;Test if the last operation resulted in 0
	goto	updm1			;Skip to motor1 check if we dont need to update M0
	call	SerStart
	call	SerChk
	movlw	b'0000001'
	movwf	TXREG
	call	SerChk
	movfw	Motor0
	movwf	TXREG
	movwf	CurMtr0

updm1
	movfw	CurMtr1			; Current motor speed in W
	xorwf	Motor1,		0	; Xor Current motor speed with wanted motor speed
	btfsc 	STATUS,		Z	;Test if the last operation resulted in 0
	return				;Return if we dont need to update M1
	call	SerStart
	call	SerChk
	movlw	b'0000011'
	movwf	TXREG
	call	SerChk
	movfw	Motor1
	movwf	TXREG
	movwf	CurMtr1
	return


SerStart
	call 	SerChk
	movlw	0x80
	movwf	TXREG
	call	SerChk
	movlw	0x00
	movwf	TXREG	
	return

SerChk
	btfss 	PIR1,		TXIF	;Test if the data has been sent to buffer
	goto	$-1			;Does this work?
	return


;----Our Interrupt Handler will go here.----;

IntH
	movwf	TEMPW

	nop	
	nop
	nop
	nop

	bcf	INTCON,		INTF	;Lets set thing back..
	movfw	TEMPW              	;Restore w
	RETFIE
	




	end
 
kchriste: This is my full code. The reason the program loops when checking TXIF is becuase in debugger->settings->limitations, It says "Serial I/O is not simulated". I'm not sure why. I'm also not sure what you mean when you say Circular buffer, but I'll figure it out.
When I SIM your latest code, it still loops when checking for TXIF to be set for apx 4955 cycles which is to be expected. So serial IO is kind of half assed simulated in that the data doesn't go anywhere and nothing can be recieved.
Circular buffer:
http://www.vias.org/cppcourse/chap20_05.html
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top