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.

16F876 project, got usart and tmr0 working tmr1 isnt ASM

Status
Not open for further replies.

Sicarii

New Member
I'm building an Airsoft controlled servo turret and have hit a snag.

I've been baby stepping building up the code layer by layer. Currently the usart is setup to just echo back to my C# application and TMR0 was setup to interrupt every 18 ms so I can generate servo pulses with TMR1. The problem is I can't get TMR1 to cause an interrupt. Currently TMR0 is disable just for debugging purposes.

Also I'm fairly new to ASM and I'm sure by mosts standards my coding practice is a mess, suggestion for improvement are greatly appreciated.

I'm also aware that my interrupt routine isn't clearing the interrupt register for the TMR1 or reloading its MSB or LSB registers, I'm currently just trying to see it fire off the first interrupt in simulator before I delve into writing the code to check which interrupt has been fired and update its registers.

EDIT Crystal used is a 4 meg crystal.
Code:
;
;16F876 Micro Serial Communications, 2 servo, pwm airsoft turret
;
;
	list	p=16f876
	include p16f876.inc
	cblock 0x20
	RX_Word
	TW_Word
	maxL_servo1
	minL_servo1
	maxH_servo1
	minH_servo1
	current_servo1
	w_temp
	status_temp
	dataL
	endc
	org	00
	goto start

	org 04
	goto interrupt


;initialize

start

	bcf	status,rp0
	bcf	status,rp1			;Bank0
	movlw	D'47'
	movwf	minL_servo1
	movlw	D'96'
	movwf	maxL_servo1
	movlw	D'248'
	movwf	minH_servo1
	movlw	D'240'
	movwf	maxH_servo1

	bsf	status,rp0
	bcf	status,rp1			;Bank1

;configure Porta pins as digital I/O

	movlw	0x06
	movwf	adcon1

;configure porta as outputs

	movlw	B'00000000'
	movwf	trisa

;configure USART in async

	bcf	status,rp0
	bcf	status,rp1			;Bank 0
	movlw	B'10010000'		;async channel:  port is on, 8 bit transfer
	movwf	rcsta			;continuous recieving, no address detect
	bsf	status,rp0			;Bank1
	bcf	status,rp1
	movlw	B'00100100'		;setup async channel:  transmit enable, 8 bit
	movwf	txsta			;high speed baud rate
	movlw	0x0c			;setup baudrate of 19200 with 4 meg crystal
	movwf	spbrg
	bcf	status,rp0			;Bank0
	bcf	status,rp1

;configure option_reg for tmr0

	bsf	status,rp0			;Bank1
	bcf	option_reg,t0cs
	bcf	option_reg,t0se
	bcf	option_reg,psa
	bsf	option_reg,ps2
	bsf	option_reg,ps1
	bcf	option_reg,ps0
	bcf	status,rp0			;Bank0

;configure 55hz interrupt

	bcf	intcon,t0if
	bcf	intcon,t0ie			;Enable 1, disable 0
	bsf	intcon,gie
	bsf	intcon,peie
	movlw	D'114'			;55 hz or 18 ms
	movwf	tmr0

;configure	t1con for tmr1

	bcf	t1con,t1ckps1		;
	bcf	t1con,t1ckps0		;
	bsf	t1con,t1oscen		;
	bsf	t1con,t1sync		;
	bcf	t1con,tmr1cs		;
	bsf	t1con,tmr1on		;Enable 1,disable 0
	bcf	pir1,tmr1if			;
	bsf	pie1,tmr1ie			;

;Load start position

	movf	minL_servo1,0
	movwf	tmr1l
	movf	minL_servo1,0
	movwf	tmr1h
	
		
;program start

main
	clrf	dataL
settle
	decfsz	dataL,F
	goto	settle

	movf	rcreg,w
	movf	rcreg,w
	movf	rcreg,w


loop	call	recieve
	movwf	txreg
	goto loop

recieve	btfss	pir1,rcif
	goto	recieve
	movf	rcreg,w
	return

transwt	bsf	status,rp0
wthere	btfss	txsta,trmt
	goto	wthere

	clrf	status
	return

;interrupt service

interrupt
	movwf	w_temp			;content saving
	swapf	status,0
	movwf	status_temp
	movlw	d'100'
	movwf	tmr0

;ADD INTERRUPT CODE HERE


;END INTERRUPT CODE	
;content loading

	swapf	status_temp,0
	movwf	status
	swapf	w_temp,1
	swapf	w_temp,0

;clear interrupt flag

	bcf	intcon,t0if
	retfie

	end
 
Last edited:
Ugh, I've been staring at my code all day. I've tried rewriting it to disable TMR1, set the pre-loader, and then re-enable to no avail. I think the best course of action is to write a bare bones TMR1 program and slowly add code from my current project and see what breaks it.

Like all things it probably something silly and simple :D
 
Last edited:
Woot found it! I wasn't in bank 1 when I set bsf pie1,tmr1ie. Been staring at the tmr1h and tmr1l in watch for hours trying to figure out why they are counting but not interrupting :D

Old
Code:
;configure	t1con for tmr1

	bcf	t1con,t1ckps1		;
	bcf	t1con,t1ckps0		;
	bsf	t1con,t1oscen		;
	bsf	t1con,t1sync		;
	bcf	t1con,tmr1cs		;
	bsf	t1con,tmr1on		;Enable 1,disable 0
	bcf	pir1,tmr1if			;
	bsf	pie1,tmr1ie			;
Correct
Code:
;configure	t1con for tmr1

	bcf	t1con,t1ckps1		;
	bcf	t1con,t1ckps0		;
	bsf	t1con,t1oscen		;
	bsf	t1con,t1sync		;
	bcf	t1con,tmr1cs		;
	bcf	pir1,tmr1if			;
	bsf	t1con,tmr1on		;Enable 1,disable 0
	bsf	status,rp0			;BANK 1
	bsf	pie1,tmr1ie			;
	bcf	status,rp0			;BANK 0
 
hi,
You beat me too it.:D

Also have you noticed this,
Code:
 movf    minL_servo1,0     
movwf    tmr1l     
movf    [B]minL[/B]_servo1,0 ;duplicated !     
movwf    tmr1h
 
Last edited:
Good call, the third line should have been movf minH_servo1,0. Right now my minL minH method seems pretty crude. I'm thinking I need a macro that will accept a value up to 65,535 and set the High eight bits in one temporary variable and the Lower eight bits into another. Then I can check the temp values on the 18ms interrupt and update before starting the 1-2ms timer 1 interrupt.

Start 55 Hz interrupt -> [Interrupt occured]Disable TMR0 -> Update delay temp variables -> Update and enable TMR1 and send data line high -> [Interrupt occured] Send data line low, disable TMR1, enable TMR0, start all over again.

Chuck McMantis has a webpage about something similiar at http://http://www.mcmanis.com/chuck/Robotics/projects/pic-16bit.htm that seems like exactly what I need. Hopefully I can slip away from the wife and kids later today and nerd it up a little more :D
 
Last edited:
Will do Nigel, also is configuring registers bit by bit as in my code considered bad practice? Generally after Ive proven out a program Ill go back and assign to the register in one go with binary or hex, the bit method just forces me focus on exactly what I'm setting up during development.
 
hi,
I would suggest you keep using the correct Bit tags, it will help you and others to debug/understand your code.:)
 
Will do Nigel, also is configuring registers bit by bit as in my code considered bad practice? Generally after Ive proven out a program Ill go back and assign to the register in one go with binary or hex, the bit method just forces me focus on exactly what I'm setting up during development.

Doing it a bit at a time is fine, and as you say, it helps to make it clear what's going on.

Once everything is working OK you can always go back and make it a single write to save a few lines of code if you want - but leave all the comments for each bit, so you still know what it's doing.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top