- français
- English
Mon petit boot loader
Regarde s'il y a une connexion RS232 de branché, si oui part dans un petit interprèteur de commandes, si non démarre l'application principale.
;********************************************************************************** ;* Title : zBLOADER ;* Version : 1.1a ;* Last updated : zf 070808.2307 ;* Target : Atmel AVR ATtiny45 ;* ;* Support : www.zufferey.com ;* ;* si connexion RS232 présente part en mode commandes ;* si non exécute l'application principale ;********************************************************************************** .include "tn45def.inc" ;***** Pin definitions .equ RxD =3 ;Receive pin is PB3 .equ TxD =4 ;Transmit pin is PB4 ;***** Global register variables .def bitcnt =R16 ;bit counter .def temp =R17 ;temporary storage register .def TxByte =R18 ;Data to be transmitted .def RxByte =R19 ;Received data .def adr =R20 ;Adresse pour l'EEPROM ;***** Constantes .equ sb =1 ;Number of stop bits (1, 2, ...) ; constante b pour 1 MHz RC oscillator: ; 9600 bps - b=14 ; 4800 bps - b=31 ; 19200 bps - b=5 ; 28800 bps - b=2 .equ b =30 ; baud rate: 4800 bps .cseg .org 0 rjmp Reset .org 30 rjmp Reset ;***** Divers strings VersionSTR: .DB "zBLOADER 1.1a 070808.2307",13,10,10,0 HelloWorldSTR: .DB "Hello World",13,10,0 HelpSTR: .DB "a: test BCD, b: test ADC, c: test multi/div, C:cls, G:go app, h:help, H:HelloWorld, v:version",13,10,0,0 ;***** RS232init RS232init: ; sbi PORTB,TxD ;Init port pins en RS232 mode cbi PORTB,TxD ;Init port pins en TTL mode sbi DDRB,TxD sbi PORTB,RxD ;met la pull up cbi DDRB,RxD ret ;***** putchar putchar: ldi bitcnt,9+sb ;1+8+sb (sb is # of stop bits) com Txbyte ;Inverte everything sec ;Start bit putchar0: brcc putchar1 ;If carry set ; cbi PORTB,TxD ; send a '0' en RS232 mode sbi PORTB,TxD ; send a '0' en TTL mode rjmp putchar2 ;else putchar1: ; sbi PORTB,TxD ; send a '1' en RS232 mode cbi PORTB,TxD ; send a '1' en TTL mode nop putchar2: rcall UART_delay ;One bit delay rcall UART_delay lsr Txbyte ;Get next bit dec bitcnt ;If not all bit sent brne putchar0 ; send next ;else ret ; return ;***** putstring putstring: lpm Txbyte,Z+ cpi Txbyte,0 brne putstring1 ret putstring1: rcall putchar ;And transmit the data rjmp putstring ;***** putbin putbin: rcall bin2BCD16 ;result: tBCD2:tBCD1:tBCD0 = $054321 mov TxByte,tBCD2 rcall putbin1 mov TxByte,tBCD1 rcall putbin2 mov TxByte,tBCD0 rcall putbin2 ret putbin2: swap TxByte rcall putbin1 swap TxByte rcall putbin1 ret putbin1: push TxByte andi TxByte,15 ldi r17,'0' add TxByte,r17 rcall putchar pop TxByte ret ;***** getchar getchar: ldi bitcnt,8+sb ;8 data bit + 1 stop bit getchar1: ; sbic PINB,RxD ;Wait for start bit en RS232 mode sbis PINB,RxD ;Wait for start bit en TTL mode rjmp getchar1 rcall UART_delay ;0.5 bit delay getchar2: rcall UART_delay ;1 bit delay rcall UART_delay clc ;clear carry ; sbic PINB,RxD ;if RX pin high en RS232 mode sbis PINB,RxD ;if RX pin high en TTL mode sec ; dec bitcnt ;If bit is stop bit breq getchar3 ; return ;else ror Rxbyte ; shift bit into Rxbyte rjmp getchar2 ; go get next getchar3: ret ;****** UART_delay UART_delay: ldi temp,b UART_delay1: dec temp brne UART_delay1 ret ;*************************************************************************** ;* ;* "bin2BCD16" - 16-bit Binary to BCD conversion ;* ;* This subroutine converts a 16-bit number (fbinH:fbinL) to a 5-digit ;* packed BCD number represented by 3 bytes (tBCD2:tBCD1:tBCD0). ;* MSD of the 5-digit number is placed in the lowermost nibble of tBCD2. ;* ;* Number of words :25 ;* Number of cycles :751/768 (Min/Max) ;* Low registers used :3 (tBCD0,tBCD1,tBCD2) ;* High registers used :4(fbinL,fbinH,cnt16a,tmp16a) ;* Pointers used :Z ;* ;*************************************************************************** .equ AtBCD0 =13 ;address of tBCD0 .equ AtBCD2 =15 ;address of tBCD1 .def tBCD0 =r13 ;BCD value digits 1 and 0 .def tBCD1 =r14 ;BCD value digits 3 and 2 .def tBCD2 =r15 ;BCD value digit 4 .def fbinL =r16 ;binary value Low byte .def fbinH =r17 ;binary value High byte .def cnt16a =r18 ;loop counter .def tmp16a =r19 ;temporary value bin2BCD16: ldi cnt16a,16 ;Init loop counter clr tBCD2 ;clear result (3 bytes) clr tBCD1 clr tBCD0 clr ZH ;clear ZH (not needed for AT90Sxx0x) bBCDx_1:lsl fbinL ;shift input value rol fbinH ;through all bytes rol tBCD0 ; rol tBCD1 rol tBCD2 dec cnt16a ;decrement loop counter brne bBCDx_2 ;if counter not zero ret ; return bBCDx_2:ldi r30,AtBCD2+1 ;Z points to result MSB + 1 bBCDx_3: ld tmp16a,-Z ;get (Z) with pre-decrement subi tmp16a,-$03 ;add 0x03 sbrc tmp16a,3 ;if bit 3 not clear st Z,tmp16a ; store back ld tmp16a,Z ;get (Z) subi tmp16a,-$30 ;add 0x30 sbrc tmp16a,7 ;if bit 7 not clear st Z,tmp16a ; store back cpi ZL,AtBCD0 ;done all three? brne bBCDx_3 ;loop again if not rjmp bBCDx_1 ;*************************************************************************** ;* ;* "mpy16u" - 16x16 Bit Unsigned Multiplication ;* ;* This subroutine multiplies the two 16-bit register variables ;* mp16uH:mp16uL and mc16uH:mc16uL. ;* The result is placed in m16u3:m16u2:m16u1:m16u0. ;* ;* Number of words :14 + return ;* Number of cycles :153 + return ;* Low registers used :None ;* High registers used :7 (mp16uL,mp16uH,mc16uL/m16u0,mc16uH/m16u1,m16u2, ;* m16u3,mcnt16u) ;* ;*************************************************************************** ;***** Subroutine Register Variables .def mc16uL =r16 ;multiplicand low byte .def mc16uH =r17 ;multiplicand high byte .def mp16uL =r18 ;multiplier low byte .def mp16uH =r19 ;multiplier high byte .def m16u0 =r18 ;result byte 0 (LSB) .def m16u1 =r19 ;result byte 1 .def m16u2 =r20 ;result byte 2 .def m16u3 =r21 ;result byte 3 (MSB) .def mcnt16u =r22 ;loop counter ;***** Code mpy16u: clr m16u3 ;clear 2 highest bytes of result clr m16u2 ldi mcnt16u,16 ;init loop counter lsr mp16uH ror mp16uL m16u_1: brcc noad8 ;if bit 0 of multiplier set add m16u2,mc16uL ;add multiplicand Low to byte 2 of res adc m16u3,mc16uH ;add multiplicand high to byte 3 of res noad8: ror m16u3 ;shift right result byte 3 ror m16u2 ;rotate right result byte 2 ror m16u1 ;rotate result byte 1 and multiplier High ror m16u0 ;rotate result byte 0 and multiplier Low dec mcnt16u ;decrement loop counter brne m16u_1 ;if not done, loop more ret ;*************************************************************************** ;* ;* "div16u" - 16/16 Bit Unsigned Division ;* ;* This subroutine divides the two 16-bit numbers ;* "dd8uH:dd8uL" (dividend) and "dv16uH:dv16uL" (divisor). ;* The result is placed in "dres16uH:dres16uL" and the remainder in ;* "drem16uH:drem16uL". ;* ;* Number of words :19 ;* Number of cycles :235/251 (Min/Max) ;* Low registers used :2 (drem16uL,drem16uH) ;* High registers used :5 (dres16uL/dd16uL,dres16uH/dd16uH,dv16uL,dv16uH, ;* dcnt16u) ;* ;*************************************************************************** ;***** Subroutine Register Variables .def drem16uL=r14 .def drem16uH=r15 .def dres16uL=r16 .def dres16uH=r17 .def dd16uL =r16 .def dd16uH =r17 .def dv16uL =r18 .def dv16uH =r19 .def dcnt16u =r20 ;***** Code div16u: clr drem16uL ;clear remainder Low byte sub drem16uH,drem16uH;clear remainder High byte and carry ldi dcnt16u,17 ;init loop counter d16u_1: rol dd16uL ;shift left dividend rol dd16uH dec dcnt16u ;decrement counter brne d16u_2 ;if done ret ; return d16u_2: rol drem16uL ;shift dividend into remainder rol drem16uH sub drem16uL,dv16uL ;remainder = remainder - divisor sbc drem16uH,dv16uH ; brcc d16u_3 ;if result negative add drem16uL,dv16uL ; restore remainder adc drem16uH,dv16uH clc ; clear carry to be shifted into result rjmp d16u_1 ;else d16u_3: sec ; set carry to be shifted into result rjmp d16u_1 ;***** RESET reset: ldi r16, LOW(RAMEND) ;Setup of stack pointer ldi r17, HIGH(RAMEND) out SPL, r16 out SPH, r17 rcall RS232init sbic PINB,RxD ;Test si une prise RS232 est connectée rjmp Application ldi Txbyte,12 rcall putchar rjmp VersionDISP CommandLoop: ldi Txbyte,'>' rcall putchar rcall getchar cpi Rxbyte,'a' breq ApplicationA cpi Rxbyte,'b' breq ApplicationB cpi Rxbyte,'c' breq ApplicationC cpi Rxbyte,'C' breq ClearScr cpi Rxbyte,'G' breq Application cpi Rxbyte,'h' breq HelpDISP cpi Rxbyte,'H' breq HelloWorldDISP cpi Rxbyte,'v' breq VersionDISP ldi Txbyte,7 ;fait un beep si pas reconnu rcall putchar rjmp CommandLoop ;Clear terminal (FromFeed) ClearScr: ldi Txbyte,12 rcall putchar rjmp CommandLoop ;Envoie une virgule puis un espace sur le port RS232 CommaSpaceDISP: ldi Txbyte,',' rcall putchar ldi Txbyte,' ' rcall putchar ret ;Envoie le Help sur le port RS232 HelpDISP: ldi Zl,low(HelpSTR*2) ldi Zh,high(HelpSTR*2) rcall putstring rjmp CommandLoop ;Envoie Hello Word sur le port RS232 HelloWorldDISP: ldi Zl,low(HelloWorldSTR*2) ldi Zh,high(HelloWorldSTR*2) rcall putstring rjmp CommandLoop ;Affiche la version du système VersionDISP: ldi Zl,low(VersionSTR*2) ldi Zh,high(VersionSTR*2) rcall putstring rjmp CommandLoop ;Fait clignoter le portB2 Application: .def Delay =r17 ; Delay variable 1 .def Delay2 =r18 ; Delay variable 2 sbi DDRB,2 ; met le PORTB2 en sortie Application1: sbi PORTB,2 ; Set PORTB2 rcall DLY1 cbi PORTB,2 ; Clear PORTB2 rcall DLY1 rjmp Application1 ; Repeat loop forever DLY1: ldi Delay2, 0 DLY2: dec Delay brne DLY2 dec Delay2 brne DLY2 ret ;Application A pour les tests ApplicationA: ldi fbinL,low(54300) ldi fbinH,high(54300) rcall putbin rjmp CommandLoop ;Application B pour les tests ApplicationB: ;init the ADC ldi r16,0b10001111 ;internal 1.1V ref, ADC4 is input (Thermal) out ADMUX,r16 ldi r16,0b11000111 ;adc on, start adc, no interrupt, CLK = sysclk / 128) out ADCSRA,r16 ;wait for conversion complete W4ADC: sbic ADCSRA,ADSC rjmp W4ADC in fbinL,ADCL in fbinH,ADCH rcall putbin rjmp CommandLoop ApplicationC: ;***** Multiply Two Unsigned 16-Bit Numbers (11 * 37) ldi mc16uL,low(11) ldi mc16uH,high(11) ldi mp16uL,low(37) ldi mp16uH,high(37) rcall mpy16u mov fbinL,m16u0 mov fbinH,m16u1 rcall putbin rcall CommaSpaceDISP ;***** Divide Two Unsigned 16-Bit Numbers (407/11) ldi dd16uL,low(407) ldi dd16uH,high(407) ldi dv16uL,low(11) ldi dv16uH,high(11) rcall div16u mov fbinL,dres16uL mov fbinH,dres16uH rcall putbin rjmp CommandLoop
(c) www.zufferey.com
- Ce wiki
- Cette page