| CODE |
;Andrew Bell and Cory Nazarian ;EE 476 Final Project ;Code for RC Car ;Also see control.asm ;Version 2.0 Uart Communication with Forward and Reverse Motor Control ;and Full turning control ;All known bugs fixed ;Port B is hooked to LED's, and used to show what subroutine were in ;For Driving motor control ;PORT A0 is direction Bit ;PORT A1 is PWM bit ;For Turning motor control ;PORT A2 is direction Bit ;PORT A3 is PWM bit .include "4414def.inc" .device AT90S4414 ;******************************* ;Register Definitions .def temp =r16 ;temporary register .def savSREG =r17 ;save the status register .def TXbusy =r18 ;transmit busy flag .def RXchar =r19 ;a received character .def TXflash =r20 ;text to be sent is in flash if <>0 .def command =r21 .def lcommand=r22 ;last command .def donecmd =r23 ;this register has 1 if done current command, 0 if not .def tmpcmd =r24 ;register to hold command until last command completes .def wreg =r25 ;temp register to be used in isrs .def turnback=r26 ;register contains where wheels were to turn back to orignal position .def doneturn=r27 ;says were done turning, set in tiemr 0 overflow interupt .def count =r28 ;count register fro timer 0 overflow interupt ;******************************* ;Constants .equ baud96 =25;9600 baud constant for 4Mhz crystal .equ PreScal =3 ;set prescalar to divide by 8 .equ TimerOff=0 ;set prescaqlr to 0 to turn off timer0 .equ DoneTurning=60 ;set done turning count to 20 overflows ;All possible directions for the car to be going .equ stop =0b00000001 .equ fwd =0b00000010 .equ rev =0b00000100 .equ left =0b00001000 .equ right =0b00010000 ;Bits in command that directions represent .equ stopb =0 .equ fwdb =1 .equ revb =2 .equ leftb =3 .equ rightb =4 .equ garbagb1=5 .equ garbagb2=6 .equ garbagb3=7 .equ True =1 .equ False =0 ;Constants for turning wheels back to center after turning .equ FrNthr =0b00000000;wheels were not just turned .equ FrLeft =0b00000010;wheels were just turned left .equ FrRight =0b00000100;wheels were just turned right ;Bits in turnback that represent to turn back from right or left .equ FrLeftB =1 ;From left bit .equ FrRightB=2 ;From Right bit .macro addi subi @0, -@1 .endmacro ;******************************* .cseg .org $0000 rjmp RESET ;reset entry vector reti reti reti reti reti reti rjmp TIMER0 ;Timer 0 overflow reti rjmp RXdone ;UART receive done reti reti reti ;define fixed strings to be tranmitted from flash- zero terminated crlf: .db 0x0d, 0x0a, 0x00 ;carrage return/line feed RESET: ldi temp, LOW(RAMEND) ;setup stack pointer out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ldi command,stop ;start car in stopped mode ldi tmpcmd,stop ;start car in stopped mode ldi turnback,FrNthr ;Wheels were not just turned ldi doneturn,False ;load dune turn variable to false ;setup UART -- enable RXdone int, and RX ldi temp, 0b10110000 out UCR, temp ;set baud rate to 9600 ldi temp, baud96 out UBRR, temp ;setup timer0 stuff ldi Temp,exp2(TOIE0);enable timer interrupt out TIMSK, Temp ;setup port a7 for power ser temp out DDRA,temp ldi temp,0b10000000 out PORTA,temp ;intialize text pointer BEFORE turning on interrupts ;because RESET causes the TX empty flag to be SET ldi ZL, LOW(crlf<<1);do shift to convert word-addr to byte ldi ZH, HIGH(crlf<<1) ;setup LED"s for display ser temp ;make port b outputs out DDRB,temp out PORTB,temp ;turn off led's sei ;Figure out which dir to drive the car and turn the car and do it RXloop: mov command,tmpcmd ;move the next command into command cpi donecmd,True ;if weve done current command already, wait for next breq RXLoop ser wreg ;turn all LED's off out PORTB,wreg sbrc command,fwdb ;drive forward rcall DriveForward sbrc command,revb ;drive reverse rcall DriveReverse sbrc command,stopb ;stop car rcall Stopped sbrc command,leftb ;turn left rcall TurnLeft sbrc command,rightb ;turn right rcall TurnRight sbrc command,garbagb1 ;use these 3 bits (not used) to see if out of range rcall OutRange ;when out of range, reciever recieves squared noise sbrc command,garbagb2 ;so one of these 3 bits will be set at some point rcall OutRange ;when it is, stop the car and spin sbrc command,garbagb3 ;note that car needs to be reset here rcall OutRange ldi donecmd,True ;Say weve done the current command sbrc command,leftb ;if this command is turn right or left go back to get next command rjmp noret sbrc command,rightb rjmp noret ;otherwise, see if the last command turned the car, to turn wheels back sbrc turnback,FrLeftB rcall BackFrLeft sbrc turnback,FrRightB rcall BackFrRight noret: rjmp RXloop ;******************************* ;Driving Routines Stopped: ;Stop the car cbi PORTB,0 cbi PORTA,1 ;Turn Driving PWM Bit off ret DriveForward: ;Drive the car forward cbi PORTB,1 sbi PORTA,0 ;Turn driving Dir bit to forward (1) sbi PORTA,1 ;Turn driving PWM bit on ret DriveReverse: ;Drive the car backwards cbi PORTB,2 cbi PORTA,0 ;Turn driving Dir bit to reverse (0) sbi PORTA,1 ;Turn driving PWM bit on ret TurnLeft: ;Turn car left cpi turnback,FrLeft brne noltyet ret noltyet:ldi turnback,FrLeft ;For turning back to middle after done turning left cbi PORTB,5 cbi PORTB,3 sbi PORTA,2 ;Turn turn Dir bit to left (1) sbi PORTA,3 ;Turn turning PWM bit on ;This code turns the motor on until wheels are fully turned to left then turns off pwm ldi temp, PreScal out TCCR0, temp tl: cpi doneturn,True brne tl sbi PORTB,5 cbi PORTA,3 ;Turn turning PWM bit off ldi doneturn,False ;Set doneturn back to false ret TurnRight: ;Turn car right cpi turnback,FrRight brne nortyet ret nortyet:ldi turnback,FrRight ;For turning back to middle after done turning right cbi PORTB,6 cbi PORTB,4 cbi PORTA,2 ;Turn turning Dir bit to right (0) sbi PORTA,3 ;Turn turning PWM bit on ;This code turns the motor on until wheels are fully turned to left then turns off pwm ldi temp, PreScal out TCCR0, temp tr: cpi doneturn,True brne tr sbi PORTB,6 cbi PORTA,3 ;Turn turning PWM bit off ldi doneturn,False ;Set doneturn back to false ret BackFrLeft: ;Turn wheels back to center after turning to left is done ldi count,20 ldi turnback,FrNthr ;Wheels were not just turned cbi PORTB,5 cbi PORTA,2 ;Turn direction to right sbi PORTA,3 ;Turn on the PWM to start turning back to center ;This lets the wheels turn back to center then turns off the pwm ldi temp, PreScal out TCCR0, temp tbl: cpi doneturn,True brne tbl cbi PORTA,3 ;Turn turning PWM bit off ldi doneturn,False ;set doneturn back to false ret BackFrRight: ;Turn wheels back to center after turning to right is done ldi count,20 ldi turnback,FrNthr ;Wheels were not just turned cbi PORTB,6 sbi PORTA,2 ;Turn direction to right sbi PORTA,3 ;Turn on the PWM to start turning back to center ;This lets the wheels turn back to center then turns off the pwm ldi temp, PreScal out TCCR0, temp tbr: cpi doneturn,True brne tbr cbi PORTA,3 ;Turn turning PWM bit off ldi doneturn,False ;set doneturn back to false ret OutRange: ;Out of range routine cbi PORTA,1 ;Turn Driving PWM Bit off cbi PORTA,3 ;Turn turning PWM bit off ret ;******************************* ;interrupt routines RXdone: in savSREG, SREG ;save processor status in tmpcmd, UDR ;get the character ldi donecmd,False ;say we have not done this command out SREG, savSREG ;restore proc status reti ;back to pgm ;******************************* ; Timer 0 overflow handler TIMER0: in savSREG,SREG inc count cpi count,DoneTurning brne notdone ldi wreg, TimerOff ;turn off timer 0 out TCCR0, wreg ldi doneturn,True clr count notdone:out SREG,savSREG reti ;- |
| CODE |
Andrew Bell and Cory Nazarian ;EE 476 Final Project ;Code for controller ;Also see rccar.asm ;Version 2.0 Uart Communication with Forward and Reverse Motor Control ;and Full turning control ;All known bugs fixed ;Port B used as push buttons at this piont .include "4414def.inc" .device AT90S4414 ;******************************* ;Register Definitions .def temp =r16;temporary register .def savSREG =r17;save the status register .def TXbusy =r18;transmit busy flag .def RXchar =r19;a received character .def TXflash =r20;text to be sent is in flash if <>0 .def command =r21 .def lcommand=r22 .def wreg =r23;temp register to be used in isrs ;******************************* ;Constants .equ baud96 =25;9600 baud constant for 4Mhz crystal ;All possible directions for the car to be going .equ stop =0b00000001 .equ fwd =0b00000010 .equ rev =0b00000100 .equ left =0b00001000 .equ right =0b00010000 ;Bits in command that directions represent .equ stopb =0 .equ fwdb =1 .equ revb =2 .equ leftb =3 .equ rightb =4 .macro addi subi @0, -@1 .endmacro ;******************************* .dseg ;define variable strings to be tranmitted from RAM stdir: .byte 3;the direction stored in mem ;******************************* ;******************************* .cseg .org $0000 rjmp RESET;reset entry vector reti reti reti reti reti reti reti reti reti rjmp TXempty;UART buffer empty rjmp TXdone;UART transmit done reti ;define fixed strings to be tranmitted from flash- zero terminated crlf: .db 0x0d, 0x0a, 0x00;carrage return/line feed RESET: ldi temp, LOW(RAMEND);setup stack pointer out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp clr TXbusy ;start out not busy on TX ldi command,stop;start the car in stop mode ldi lcommand,0;make sure last command is not = command at start ;setup UART -- enable TXempty int, TX pin ldi temp, 0b00001000 out UCR, temp ;set baud rate to 9600 ldi temp, baud96 out UBRR, temp ;setup port b for control clr temp out DDRB, temp ser temp out PORTB,temp ;setup port a7 for power ser temp out DDRA,temp ldi temp,0b10000000 out PORTA,temp ;intialize text pointer BEFORE turning on interrupts ;because RESET causes the TX empty flag to be SET ldi ZL, LOW(crlf<<1);do shift to convert word-addr to byte ldi ZH, HIGH(crlf<<1) sei ;now print three strings and wait for incoming character interrupt TXloop: in command,PINB com command cpi command,0 brne notstop ldi command,stop ;if command is 0, set it to stop (0b00000001) notstop:ldi ZL, LOW(stdir) ;ptr to RAM ldi ZH, HIGH(stdir) st Z, command ;the direction to ram inc ZL ;zero string terminator to RAM clr temp st Z, temp ;now the pointer to the variable message in RAM ldi ZL, LOW(stdir) ;ptr to RAM ldi ZH, HIGH(stdir) ld r0,Z out UDR, r0 ;fire off the UART transmit clr TXflash ;the string is in RAM ser TXbusy ;and set the TX busy flag sbi UCR, UDRIE ;enable the TXempty interrupt rcall TXwait rjmp TXloop ;******************************* ;interrupt routines ; UART needs a character TXempty:in savSREG, SREG;save processor status tst TXflash ;Is the string in flash memory? breq TXram ;If not, it is in RAM inc ZL ;get the next char from flash lpm ;and put it in r0 rjmp TXfls TXram: inc ZL ;get the next char from RAM ld r0,Z TXfls: tst r0 ;if char is zero then exit breq TXend out UDR, r0 ;otherwise transmit it rjmp TXexit ;exit until next char TXend: clr TXbusy ;no more chars cbi UCR, UDRIE;clear the TXempty interrupt TXexit: out SREG, savSREG;restore proc status reti ;back to pgm ; TX done -- buffer is empty -- unused here TXdone: in savSREG, SREG;save processor status out SREG, savSREG;restore proc status reti ;back to pgm ;******************************* ;subroutine TXwait: tst TXbusy ;now wait for the tranmission to finish brne TXwait ret ;- |