Not simple BLDC controller It RUNS! :)

STGMT said:
Are you sure its not simpler to have a software (java maybe) to do that? Looks like a few hours of coding to write a software to do this.
Anyway i believe its not the right time to bother about UI. Its time to burn some fets! :)

Which software do what ? Except for the dumb terminal program everything runs on and is computed by the 30F

I have to proudly say I haven't burned a FET yet :D Though I almost killed a few gate drivers this weekend when I when I jacked the PWM frequency
up to 1 MHz.... 200 kHz is still OK (slight heating), 400 kHz really cooks them.

regarding not blowing any FET's, I don't have a battery yet so I do all testing with my 60 V 2.5 A lab supply (I really mis my 50V 40A supply which
is stored at my dads in Holland :( )

I tried to run a motor this weekend (first simple hall commutation test) but no dice yet. It starts up under 'dumb' commutation
no problem. But once it achieves 'lock' it starts to interpolate the rotor position inbetween the hall sensors edges. This increases
the efficiency by such a large amount that the motor really jerks forwards (so: faster). This confuses the 30F to such an extent
that it looses lock again. So all in all it jerks like crazy. But I also discovered that when I turn the motor voltage down the controller
manages to maintain lock. What was really noticable in this case is that all of a sudden the motor noise drops to almost nothing
when commutation switches from 'dumb' to 'interpolated'....
 
It sounds like you need some filtering on the rotor position.

The way I would do it is to have the rotor position be calculated within it's own little closed-loop feedback system. You calculate the position by theta = theta_0 + omega*dt, where dt is the update interval. Then wrap this inside another loop where omega is generated from acceleration (d/dt omega). The input to the position tracker is then acceleration, which could easily be bang-bang control based on the sign of theta_meas - theta_est. With the second loop, no LPF on omega would be required as the loop has an inherent low-pass characteristic. You might want to implement a max value of omega (although it shouldn't be needed), and would definitely want to put a max value on the magnitude of acceleration (based on the physics of the system). This setup would be super-easy to implement in code, and it also gives you the value of omega without doing (theta1-theta0)/dt.

A side benefit of this would be it's pretty easy to implement the sensorless start-up routine. The usual idea is to apply constant acceleration to the motor, so using the above scheme it's very easy to just set the outer-loop acceleration input to the desired value. When the start-up is completed, control of the input can be handed over to the position estimator, which will then act to correct the position without introducing any jumps/discontinuities/etc in either theta or omega. Continuity is guaranteed because the outputs are the integral of the input. If the maximum allowed value of acceleration is made less than what the motor is physically capable of, then this algorithm will never lose lock with the motor so long as the position estimator provides accurate information. The faster the loop runs (smaller dt), the smoother the outputs will be.

If you wanted to be really fancy, you can use any source you want to generate the sign used for bang-bang control. It could be a combination of Halls (if available) and a sensorless estimator for the Holy Grail of hybrid control.
 
What you're talking about is to use a second order system for the predictor. I tried this but found out it was too eratic.
A second order system typically has some overshoot etc, especially when you want it to settle fast. What's also is going
on is that the magnets in the motor are not evenly spaced so for every motor rotation , because I have 7 alternating magnet
pairs, I get 7 different readings for e-rotation time (even though motor speed is exactly constant). Combined with the
overshoot of a second order system the output of the predictor is basically useless.
Therefore I use a simple 1st order system with a reduced bandwidth,

prediction[n+1] = prediction [n] + (1/8) * (current period time - prediction[n])

Code:
					;use actual (extrapolated) period count to generate new prediction for period count	
    mov tmr2_just_cap, w0
    mul.uu w0, w12, w2                          ;w3:w2 = 00000000 xxxxxxxx yyyyyyyy.uuuuuuuu
    sl w3, #8, w3
    lsr w2, #8, w2
    ior w3, w2, w3                              ;w3 = xxxxxxxx yyyyyyyy

    lsr w3, #3, w0
    add pred_int1
    mov phi_tp, w0
    lsr w0, #3, w0
    sub pred_int1

    mov pred_int1, w0
    mov w0, phi_tp                          ;store in phi_tp

The 1/8 is actually in the Logic Shift Right commands in the second alinea.

As a lock indicator I use the difference between last measured and predicted period time, a difference larger than
12% (1/8th) and lock is declared lost. This measurement / updating of prediction is done after every hall edge. This is why the
algorithm needs to know the spacing between hall signals, it measures the time between two hall edges and then
multiplies with a factor (known from calibration) to arrive at period_time.

Anyway, I found out that the halls also see the switching of the coils. And since the algorithm is edge-triggered a coil-switch
makes a spike on the hall signal which then by the controller is interpreted as a hall-edge. A simple RC filter solved
the earlier reported jerky motion. I will also play a bit with the 1/8th in the prediction algoritm to increase the bandwidth,
combined with maybe a larger error margin before lock is lost.

Best is however to switch to sensorless as soon as possible
 
The whole point of the second-order system is to filter out things like the error in magnet position, coil noise, etc. If you had that much trouble with it you probably had way too much bandwidth. It still sounds like you have too much bandwidth in the current system, too. Except at super-low speed, omega is changing very slowly relative to the signals from the Hall sensors - it's basically constant over a revolution - so the required bandwidth is actually very low. I think you're causing yourself a lot of trouble if you're still worried about not having enough bandwidth.
 
rhitee05 said:
The whole point of the second-order system is to filter out things like the error in magnet position, coil noise, etc. If you had that much trouble with it you probably had way too much bandwidth. It still sounds like you have too much bandwidth in the current system, too. Except at super-low speed, omega is changing very slowly relative to the signals from the Hall sensors - it's basically constant over a revolution - so the required bandwidth is actually very low. I think you're causing yourself a lot of trouble if you're still worried about not having enough bandwidth.

how are you going to keep accurate phase if you're motor accellerates very quickly and you only have a low bandwidth ?
I get only 6 readings per e-revolution so I need to be able to react quickly
 
Ok So last night I finaly got my dispic30f3010 28 pin chip on a peice of bread board and linked it to a set of header pins. What a messs without a proper pcb but for now im just prototyping so its ok. Now I have the pickit3 reconizing it but its going to take me some practice to learn how to program it. Any body with some info and advice is apreatied. Im a newb but not for long! I hope to be on to the next step asap!
Thanks for all the help everyone! So excited its like being a kid a xmass!!! :mrgreen:
 
I rebuild my (opto-coupler isolated) output stage and got it working properly yesterday evening.
Got the 30F to run the motor with full sinewaves on all three motor terminals :D The motor
gets relatively quiet with the sinewaves, it makes a very high tech electronic noise now, like the
bleepbleep going on in the background of a badly coded mp3 song. Must be the low oversampling
ratio (am at 1 kHz sampling freq now) and quantisation noise (use simple rounding, not a class-D
algorithm)....

After it ran I got overly enthousiastic and upped the voltage, which then blew one of my NMOS
transistors again :( FQP33N10's are not very robust, the high side IRF5210's are doing much better...

The main issue I have (due to my ironless motor) it that the hall sensors pick up on the coil
signals. I can filter out the resulting spikes with an RC filter but this then introduces a delay which
is catastrophic for the timing -> I think this is what kills my NMOS transistors at high speeds. I suspect
the RC delay is also why efficiency is bad, I need 12 Watts to spin the motor at a speed where
I used to need only 3 Watts previously with my sensorless - only controller.

I thought about fixing the hall issue but I think it's better to concentrate on making the transition
from sensored to sensorless as soon as possible (with soon I mean, as soon as the motor spins).
I would be very interested to see other people's hall signals with a spinning motor, do they stay nice
and clean or do they get messy as current is put through the coils ?
 
Lebowski said:
I thought about fixing the hall issue but I think it's better to concentrate on making the transition
from sensored to sensorless as soon as possible (with soon I mean, as soon as the motor spins).
I would be very interested to see other people's hall signals with a spinning motor, do they stay nice
and clean or do they get messy as current is put through the coils ?

The 3250w motor i use with external halls the signal remains nice and clean 2.8kw ( this is the max i can load the motor while monitoring the signals ) , I know Thud and some others on this forum were having problems with external hall placement with the larger motors at higher currents so they went for the internal 120 degree spacing and it improved ( but I dont think it was ever got to the bottom of for the reason why )
 
Lebowski said:
The main issue I have (due to my ironless motor) it that the hall sensors pick up on the coil
signals. I can filter out the resulting spikes with an RC filter but this then introduces a delay which
is catastrophic for the timing -> I think this is what kills my NMOS transistors at high speeds. I suspect
the RC delay is also why efficiency is bad, I need 12 Watts to spin the motor at a speed where
I used to need only 3 Watts previously with my sensorless - only controller.

The RC filter will have a fixed time delay, so it should be fairly easy to compensate for that. It's a fixed delay in time, so you'd either have to put in a time delay or use a phase offset that's linear with speed.
 
rhitee05 said:
The RC filter will have a fixed time delay, so it should be fairly easy to compensate for that. It's a fixed delay in time, so you'd either have to put in a time delay or use a phase offset that's linear with speed.

I thought about that, in theory it would work but in practise you would get only a 90% reduction in delay. Capacitors
typically have a 20% spread in their actual value so you'll never be able to match the delays in all three hall signals to
a 30F programmed delay. Plus it's got a McGyver feel to it I don't like :)
 
Obviously not fixing the problem is better than fixing it 90% of the way. It's also obvious that filtering the signals to remove noise is not a hack but compensating for the filter's effects is a completely unacceptable, amateurish thing to do. Silly me.
 
I've been following this thread since it started, and what you guys are accomplishing is incredible. Alot of it has been over my head...so in trying to keep up and understand the issues you guys are dealing with, I've done a fair bit of searching on BLDC basics. I found the following MC app notes pretty useful in helping me understand what you're doing. I realize this isn't really helpful to you guys...but I wanted to share it for the rest of the noobs (self included) following along:

Brushless DC Motor Control Made Easy: http://ww1.microchip.com/downloads/en/AppNotes/00857a.pdf

Motor Control Sensor Feedback: http://ww1.microchip.com/downloads/en/AppNotes/00894a.pdf

Sensorless BLDC Motor Control: http://ww1.microchip.com/downloads/en/AppNotes/00970A.pdf
 
This is a good project and thread. Thanks for sharing.

From my perspective, starting on hall sensors and transitioning smoothly to sensorless as early as feasible makes the most sense. Compensating for incorrect halls is interesting but perhaps not the best investment of effort. Better to fix the halls, at least make them good enough for takeoff and move on. Just my opinion.
 
I think I am going to try burties optic sensor. I will probably just build my controller to run with it to start with. An optic sensor on the out side of the motor is not going to fail from over heating!
 
AN1083 http://ww1.microchip.com/downloads/en/AppNotes/01083a.pdf is another good one to read!
 
Ok guys Im working hard on this now. I am just trying to get my pickit to comunicate with my dspic30f but.... Its not so easy. I did have it reconize it in mplab v8.8 but I asked leb for some advice and he said he is using mplab X beta so I downloaded it to try and it looks easier to use so now Im stuck just trying to get mplab X to reconize the pickit3... Any help would be good this is how this stuff goes for me but I do like the challange... I might see if someone local can tutor me on this stuff.
 
Arlo1 said:
Ok guys Im working hard on this now. I am just trying to get my pickit to comunicate with my dspic30f but.... Its not so easy. I did have it reconize it in mplab v8.8 but I asked leb for some advice and he said he is using mplab X beta so I downloaded it to try and it looks easier to use so now Im stuck just trying to get mplab X to reconize the pickit3... Any help would be good this is how this stuff goes for me but I do like the challange... I might see if someone local can tutor me on this stuff.

did you look at the pdf under

http://ww1.microchip.com/downloads/mplab/X_Beta/installer.html

on the left 'getting started with mplabX_beta' ? there's a step-by-step
tutorial how to set up a new project, starts at page 27. I followed this
and everything worked straight away. Maybe windows is the issue ? (I have Ubuntu)
 
Lebowski said:
Arlo1 said:
Ok guys Im working hard on this now. I am just trying to get my pickit to comunicate with my dspic30f but.... Its not so easy. I did have it reconize it in mplab v8.8 but I asked leb for some advice and he said he is using mplab X beta so I downloaded it to try and it looks easier to use so now Im stuck just trying to get mplab X to reconize the pickit3... Any help would be good this is how this stuff goes for me but I do like the challange... I might see if someone local can tutor me on this stuff.

did you look at the pdf under

http://ww1.microchip.com/downloads/mplab/X_Beta/installer.html

on the left 'getting started with mplabX_beta' ? there's a step-by-step
tutorial how to set up a new project, starts at page 27. I followed this
and everything worked straight away. Maybe windows is the issue ? (I have Ubuntu)
I have made some progress it seems its a problem for a lot of windows 7 users. WHen I create a new project is shows the pickit3 and then I can work from there so now I will try to flash a simple led code to it then test if it can turn on a led.
 
Made some major progress! I can now successfully program my disPIC30f :mrgreen: I just flashed it with some random junk to see the programs work, now to get a code to work to flash an led.... Then I will get onto the actual code for the controller!
 
a cool thing to try and very usefull for later on is to get it to talk to your PC over RS232. I use
the RS232 a lot to get algorithm variables and measurement data out of the PIC.
My (not totally optimal but it works, didn't know the ZE and CPSNE commands back then) subroutines for RS232:

Code:
.include "p30F4011.inc"

.text

.global init_232
;initalise UART2 for RS232 communication
;speed with 120MHz clk: 115200 baud

init_232:
						;select 115200 baud
    mov #15, w0
    mov w0, U2BRG
						;enable, no loopback, no auto-baud, 8bit no parity, 1 stop bit
    mov #0x8000, w0
    mov w0, U2MODE
						;normal TX pin, enable TX, no address detect, interrupt when character RX-ed
    mov #0x0400, w0
    mov w0, U2STA
	
    return

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

.global tx_ram_str_232
;w0: start of string (in RAM)

tx_ram_str_232:
						;save register
    push w1
						;address to w1
    mov w0, w1
trs2_lp:
						;get char
    mov.b [w1++], w0                
						;test for end of string
    cp0.b w0                       
    bra z, trs2_end				;if yes end
							;if no display char
    call tx_char_232                       
    bra trs2_lp
trs2_end:
						;restore registers
    pop w1
    return

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

.global tx_str_232
;w0: start of string (in prog memory), higher 8 bits of address
;w1: start of string (in prog memory), lower 16 bits of address
;string only uses lower 16bits of 24 bits progmem data, must end with 0x00

tx_str_232:
    and #0xff, w0				;clr top 8 bits of w0
						;write TBLPAG
    mov w0, TBLPAG
ts2_lp:		
						;get character, postincrement
    tblrdl.b [w1++], w0
						;terminate TX when w0 is 0x00
    cp w0, #0x00
    btsc SR,#Z
    return
						;send character
    call tx_char_232
						;check tblpag boundary in case message runs over
    cp0 w1						;if w1=0x0000 then ++TBLPAG
    btsc SR, #Z
    inc TBLPAG
						;continue with next character
    bra ts2_lp

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

.global tx_char_232
;w0: contains character

tx_char_232:
    btsc U2STA, #9                              ;make sure no longer tx-ing
    bra tx_char_232
						;tx character
    mov w0, U2TXREG

    return

;*****************************************************************
.global tx_word_232
;w0: contains word to be send, top byte first

tx_word_232:
						;save registers, input value
    push w1
    mov w0, w1
						;send top byte
    swap w1						;swap so top byte is now at bottom
    mov #0x00FF, w0
    and w1, w0, w0					;mask, only bottom byte
    call tx_char_232
						;send lower byte
    swap w1						;swap back
    mov #0x00FF, w0
    and w1, w0, w0					;mask, only bottom byte
    call tx_char_232
						;restore registers
    pop w1
    return

;*****************************************************************
.global clr_scr_232

clr_scr_232:
						;save registers
    push w0
						;send 30 \n characters
    mov #'\n', w0
    do #29, cs3_last
    call tx_char_232
    nop
cs3_last:
    nop
						;restore registers
    pop w0
    return


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

.global rx_str_232
;w0: length of buffer for rx
;w1: start of string in data memory, max w0 characters
;terminates on '\r' (carriage return, = pressing enter)

rx_str_232:
						;store registers
    push w3					;w3 is buffer lenght-1
    push w2						;w2 (0 to 9) is offset character storage address
						;initialise registers
    dec w0, w3					;w3 = w0-1
    clr w2                                          ;start at beginning
rs2_lp:
    call rx_char_232
						;w0 = backspace ?
    cp w0, #'\b'
    bra nz, rs2_no_bs				;continue if not backspace
                                                    ;w2 = 0 ? then do nothing
    cp0 w2
    bra z, rs2_lp
                                                    ;else delete previous char
    mov #' ', w0                                        ;necessary for if we're on last character
    call tx_char_232
    mov #'\b', w0
    call tx_char_232
    mov #'\b', w0
    call tx_char_232
    mov #' ', w0
    call tx_char_232
    mov #'\b', w0
    call tx_char_232
                                                    ;decrement w2
    dec w2, w2
    bra rs2_lp
	
rs2_no_bs:
						;w0 = '\r' ? (enter key = carriage return)
    cp w0, #'\r'
    bra nz, rs2_no_ret				;continue if not return
                                                    ;store \0 and display \n
    clr.b w0
    mov.b w0, [w1+w2]
    mov #' ', w0                                    ;in case we're on last character
    call tx_char_232
    mov #'\n', w0
    call tx_char_232
                                                    ;exit routine
    pop w2
    pop w3
    return
rs2_no_ret:
						;store and display character
    mov.b w0, [w1+w2]
    call tx_char_232
                                                    ;if w2 = w3 send backspace for overwrite (buffer end)
    mov #'\b', w0                                   ;prepare the backspace, just in case it needs to be send
    cp w2, w3
    btsc SR, #Z
    call tx_char_232
                                                    ;if w2 != w3 then w2+=1
    cp w2, w3
    btss SR, #Z
    inc w2, w2
						;next character
    bra rs2_lp

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

.global rx_char_232
;w0: contains character after return

rx_char_232:
						;wait until data available
    btss U2STA, #0
    bra rx_char_232
						;get rx data
    mov U2RXREG, w0
    and #0xff, w0

    return

;*****************************************************************
 
Arlo1 said:
I just flashed it with some random junk !

There you go again, flashing your random junk around... I thought the judge said he would take away your birthday if you did that again :roll:
 
texaspyro said:
Arlo1 said:
I just flashed it with some random junk !

There you go again, flashing your random junk around... I thought the judge said he would take away your birthday if you did that again :roll:
Its all good. I build all my vehicals fast so I don't get caught as easy!

Man I have flashed this thing with a code that is supposed to be able to flash an led but I scoped the board and nothing. I am going to have to dig deeper and really learn the C code for the micro chips. Anyone have some links for me to read?
In mplap 8 I get Error: undefined symbol `BORV_27'
and when looking at the BLDC code in mplab x I get a lot of errors I can fix most but not all.
the most frustrating error is "make: *** No rule to make target `build/default/production/_ext/1016963926/SinusoidalBLDC'. Stop"
 
Arlo, it will be a tough journey, but you are up to it.

Post your code and we'll see what we can do. I can perhaps compile it on my working MPLAB build.
 
Thanks Dave.

What I really need is to understand the code better. for instance I copied this code from the mplab x forum and pasted it but I think its trying to use a pin that is not on the 28 pin dspic30f3010 I have.
Code:
#define __dsPIC30F3010__
#include  "p30F3010.h"
//-----------------------------------------------------------------------------
//Configuration bits
_FOSC(CSW_FSCM_OFF & XT_PLL4);
_FWDT(WDT_OFF);
_FBORPOR (PBOR_OFF & PWRT_16 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//-----------------------------------------------------------------------------
//Program Specific Constants
#define FCY 7372800 //Instruction cycle rate (Osc x PLL / 4)
//=============================================================================
//Main routine
//Set up LEDs and timer, wait for timer periods, and flash one of the two LEDs
int main(void)
{
LATD = 0xfffe; //Initialize LED pin data to off state
TRISD = 0xfffe; //Set LED pin as output
LATDbits.LATD0 = 1; //Turn LED on
T1CON = 0; //Turn off Timer1 and clear settings
TMR1 = 0; //Start Timer1 at zero
PR1 = FCY/256/5; //Set period register value for 1/5 second
T1CON = 0x8030; //Turn on Timer1 with 1:256 prescaler
while(1) //Loop forever
{
while(!IFS0bits.T1IF){} //Wait for timer period
IFS0bits.T1IF = 0; //Clear timer flag for next period
LATDbits.LATD0 ^= 1; //Toggle LED
}
} //End of main()
//=============================================================================
//Error traps
//-----------------------------------------------------------------------------
//Oscillator Fail Error trap routine
void _ISR _OscillatorFail(void)
{
LATDbits.LATD0 = 1; //Turn LED on
while(1); //Wait forever
}
//-----------------------------------------------------------------------------
//Address Error trap routine
void _ISR _AddressError(void)
{
LATDbits.LATD0 = 1; //Turn LED on
while(1); //Wait forever
}
//-----------------------------------------------------------------------------
//Stack Error trap routine
void _ISR _StackError(void)
{
LATDbits.LATD0 = 1; //Turn LED on
while(1); //Wait forever
}
//-----------------------------------------------------------------------------
//Math (Arithmetic) Error trap routine
void _ISR _MathError(void)
{
LATDbits.LATD0 = 1; //Turn LED on
while(1); //Wait forever
}
//-----------------------------------------------------------------------------
It reads clean and will program with mplab8 Mplab x is beta so it maybe problems with that. Although I am building code from scratch just to turn a pin on to learn as fast as possible. I cant wait till I start to realy get it. Its kinda like learning to ride a bike! Although this time dad is not towing me at 35mph with a little mini bike :mrgreen:
EDIT: I forgot I removed the BORV_27 from the middle of the third line of configuration bits. It used to read
Code:
;=============================================================================;
; ;
; Software License Agreement ;
; ;
; The software supplied herewith by Microchip Technology Incorporated ;
; (the "Company") for its dsPIC controller is intended and supplied to ;
; you, the Company's customer, for use solely and exclusively on ;
; Microchip dsPIC products. The software is owned by the Company and/or ;
; its supplier, and is protected under applicable copyright laws. All ;
; rights are reserved. Any use in violation of the foregoing ;
; restrictions may subject the user to criminal sanctions under ;
; applicable laws, as well as to civil liability for the breach of the ;
; terms and conditions of this license. ;
; ;
; THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, ;
; WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ;
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ;
; PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, IN ANY ;
; CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL ;
; DAMAGES, FOR ANY REASON WHATSOEVER. ;
; ;
;=============================================================================;
;
; Use Timer 1 to flash LED
;
;==============================================================================
.equ __30F2010, 1
.include "p30f2010.inc"
;------------------------------------------------------------------------------
;Global Declarations
.global __reset ;The label for the first line of code
.global __OscillatorFail ;Declare Oscillator Fail trap routine label
.global __AddressError ;Declare Address Error trap routine label
.global __StackError ;Declare Stack Error trap routine label
.global __MathError ;Declare Math Error trap routine label
;------------------------------------------------------------------------------
;Configuration bits
config __FOSC, CSW_FSCM_OFF & XT_PLL4
config __FWDT, WDT_OFF
config __FBORPOR, PBOR_OFF & BORV_27 & PWRT_16 & MCLR_EN
config __FGS, CODE_PROT_OFF;------------------------------------------------------------------------------
;Program Specific Constants (literals used in code)
.equ FCY, #7372800 ;Instruction cycle rate (Osc x PLL / 4)
;==============================================================================
;Start of code
.text ;Start of Code section
;------------------------------------------------------------------------------
;Initialize stack pointer and limit register
__reset: mov #__SP_init, W15 ;Initialize the Stack Pointer register
mov #__SPLIM_init, W0 ;Get address at the end of stack space
mov W0, SPLIM ;Load the Stack Pointer Limit register
nop ;Add NOP to follow SPLIM initialization
;------------------------------------------------------------------------------
;Initialize LED output on PORTD bit 0
mov #0xfffe, W0 ;Initialize LED pin data to off state
mov W0, LATD
mov #0xfffe, W0 ;Set LED pin as output
mov W0, TRISD
bset LATD, #0 ;Turn LED on
;------------------------------------------------------------------------------
;Initialize Timer1 for 1/5 second period
clr T1CON ;Turn off Timer1 by clearing control register
clr TMR1 ;Start Timer1 at zero
mov #FCY/256/5,W0 ;Get period register value for 1/5 second
mov W0, PR1 ;Load Timer1 period register
mov #0x8030,W0 ;Get Timer1 settings (1:256 prescaler)
mov W0, T1CON ;Load Timer1 settings into control register
;------------------------------------------------------------------------------
;Loop while waiting for a Timer1 match and toggle LED1 when it happens
MainLoop: btss IFS0, #T1IF ;Check if Timer1 interrupt flag is set
bra MainLoop ;Loop back until set
bclr IFS0, #T1IF ;Clear Timer1 interrupt flag
btg LATD, #0 ;Toggle LED
bra MainLoop ;Loop back
;==============================================================================
;Error traps
;------------------------------------------------------------------------------
;Oscillator Fail Error trap routine
.text ;Start of Code section
__OscillatorFail:
bclr LATD, #0 ;Turn LED on
bra __OscillatorFail ;Loop forever when oscillator failure occurs
;------------------------------------------------------------------------------
;Address Error trap routine__AddressError:
bclr LATD, #0 ;Turn LED on
bra __AddressError ;Loop forever when address error occurs
;------------------------------------------------------------------------------
;Stack Error trap routine
__StackError:
bclr LATD, #0 ;Turn LED on
bra __StackError ;Loop forever when stack error occurs
;------------------------------------------------------------------------------
;Math (Arithmetic) Error trap routine
__MathError:
bclr LATD, #0 ;Turn LED on
bra __MathError ;Loop forever when math error occurs
;==============================================================================
.end ;End of code in this file
 
Back
Top