这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » ATMEGA8 ATMEGA8的疑惑?

共2条 1/1 1 跳转至

ATMEGA8 ATMEGA8的疑惑?

院士
2006-09-17 18:14:16     打赏
ATMEGA8 ATMEGA8的疑惑?



关键词: ATMEGA8     疑惑    

院士
2006-12-22 22:43:00     打赏
2楼
问 我正在使用ATMEGA8,写程序时,通过对bootrst,ivsel的编程可以确定对复位和中断向量表的位置。看了好久,弄不明白改变这位置有什么用的啊。请同仁能否解释一下。
还有一个问题是,ATMEGA8书上说,加载程序区大小最大为1K,而我刚在网上看到说可以到2K,这是怎么回事啊? 1: 写bootrst后,写bootrst后,程序就从boot区开始运行,执行你的boot代码。否则,跳过bot区,直接从app区运行。应该是这样吧? 2: 谢谢你说的没错啊,我想知道这两种程序执行方式有什么特点,也就是说各自有什么优缺点吗?我就不知道什么时候该用哪种方式呢, 3: 参考下面的代码,实现一个Boot Loder;***************************************************************************************
;*说明:
;*      1、本程序修改自AVRfreaks的Design Note #032,你可以到 http://www.AVRfreaks.com 下载
;*      2、本程序支持 atmega-8 和 AVRProg (版本一定要1.37及以上)。
;*      3、Design Note #032上的程序,是为写的,在上不能正常运行。主要问题是在页写和
;*         擦除以后,不能再重新访问RWW。现在改正了这个bug!
;*      4、请确定你的 AVRProg 的版本在1.37及以上,1.37以下的是不支持 Mega8 的。
;*      5、请用等PonyProg等编程器把编译好的代码(Boot2.hex),写入到Mega8中。
;*         同时编程熔断位:BOOTSZ0 BOOTRST
;*      6、若有问题,请发邮件给我: Zhang_Lei@cnnb.net 。
;*      7、我的主页在 http://AVRmcu.topcities.com 。
;***************************************************************************************

;******************** BOOT  LOADER FOR ATmega8 *****************************************
;*
;* File                 : Boot2.asm (Include chip erase counter)
;* Version              : 1.3
;* Compiler             : AVR Studio
;* Target               : ATmega8
;* Output size          : 207 words (414 bytes)
;* Author               : 张磊 ;Email-to: Zhang_Lei@cnnb.net; or zlei@21ic
;*                        website: http://AVRmcu.topcities.com
;***************************************************************************************

;****************************************************
;     定义Mega8识别代码、电子标签字节和其它
;****************************************************

.equ    DT      = 0x77  ; Mega8识别代码(Mega8 bootloader)
.equ    SB1     = 0x07  ; 电子标签字节 1
.equ    SB2     = 0x93  ; 电子标签字节 2
.equ    SB3     = 0x1e  ; 电子标签字节 3
.equ    E2END   = $1FF  ; EEEPROM尾
.equ    UBR     = 12    ; 波特率 = 19.200 bps ,晶振 = 4 MHz。
                        ;AVRProg 能接受的波特率是 19200 和 115200
.nolist                        
.include "m8def.inc"    ; 包含 mega8 器件配置文件
.list

.CSEG
.org            SECONDBOOTSTART         ;($0F00) 2'nd boot block size is 512

;****************************************************
;  复位并等待AVRProg发送ESC
;****************************************************
                sbic PIND,PIND4                         ; if (PIND4为0) then 跳到 Boot_Reset
                rjmp $0000                              ;    else 运行用户代码(地址:$0000)

Boot_Reset:

;**** 初识化堆栈
                ldi     R24,low(RAMEND)
                ldi     R25,high(RAMEND)
                out     SPL,R24
                out     SPH,R25                         ; SP = RAMEND
;**** 初识化串口
                ldi     R24,UBR                         ; 波特率
                out     UBRRL,R24
                ldi     R24,(1<<RXEN)|(1<<TXEN)         ; 使能 TXEN 和 RXEN, 8位
                out     UCSRB,R24                       

L10:            rcall uartGet                           ; repeat (R16 = uartGet)
                cpi R16,27                              ; while (R16 == ESCAPE)
                breq L10
                rjmp    Boot_ID                         ; 若收到ESC,先显示ID,再跳到Boot_Main
                
Boot_Main:      rcall   uartGet                         ; repeat (R16 = uartGet)
                cpi     R16,0x1B                        ; while (R16 == ESCAPE)
                breq    Boot_Main

                cpi     R16,'a'                         ; if(R16=='a') 'a' = Autoincrement?
                brne    L12
                ldi     R16,'Y'                         ; Yes, autoincrement is quicker
                rjmp    L70                             ; uartSend(R16)
                
;*********************************************************************
;  得到地址,并把字节地址(byte address)转换成字地址(word address)的形式
;*********************************************************************

L12:            cpi     R16,'A'                         ; else if(R16=='A') write address
                brne    L14
                rcall   uartGet
                mov     R27,R16                         ; R27 = address high byte
                rcall   uartGet
                mov     R26,R16                         ; R26 = address low byte
                lsl     R26                             ; address=address<<1
                rol     R27                             ; convert from byte address to word address
                rjmp    Send_CR                         ; uartSend('\r')

;****************************************************
; 得到 program data 低字节
;****************************************************
L14:            cpi     R16,'c'                         ; else if(R16=='c') write program memory, low byte
                brne    L16
                rcall   uartGet
                mov     R22,R16                         ; R22 = data low byte
                rjmp    Send_CR                         ; uartSend('\r')

;****************************************************
;得到 program data 高字节,并把它存入临时缓冲区
;****************************************************
L16:            cpi     R16,'C'                         ;else if(R16=='C') write program memory,high byte
                brne    L18

                rcall   uartGet
                mov     R23,R16                         ; R23 = data high byte

                movw    R30,R26                         ; Z pointer = address
                movw    R0,R22                          ; R0&R1 = data
        
                ldi     R24,1                           ; SPMCR = 0x01
                out     SPMCR,R24                       ; page load (fill temporary buffer)
                spm                                     ; Store program memory

                adiw    R26,2                           ; address=address+2
                rjmp    Send_CR                         ; uartSend('\r')
                
;****************************************************
;  擦除芯片   
;****************************************************

L18:            cpi     R16,'e'                         ; else if(R16=='e') Chip erase
                brne    L28
                
; for(address=0; address < (2*SECONDBOOTSTART); address += (2*PAGESIZE))

                clr     R26                             ; page_erase();
                clr     R27
                rjmp    L24                             ; test for end

L20:            movw    R30,R26                         ; Z-pointer = address
                ldi     R24,3                           ; SPMCR = 0x03
                out     SPMCR,R24                       ; page_erase
                spm                                     ; Store program memory
                                                ; do the page erase
                rcall   wait_spm                        ; wait for done
        
                subi    R26,low(-2*PAGESIZE)            ; address += (2*PAGESIZE)
                sbci    R27,high(-2*PAGESIZE)

L24:            ldi     R24,low(2*SECONDBOOTSTART)
                ldi     R25,high(2*SECONDBOOTSTART)
                cp      R26,R24                         ; address < Boot Flash address(byte address) 0x3E00 ?
                cpc     R27,R25
                brlo    L20
        
                ldi     R26,low(E2END-1)                ; increment Chip Erase Counter located at address E2END-1
                ldi     R27,high(E2END-1)               ;
                movw    R22,R26                         ; Save Chip Erase Counter Address in R22
                ldi     R17,1                           ; read EEPROM
                rcall   EepromTalk
                mov     R24,R16                         ; R24 = Chip Erase Counter low byte
                rcall   EepromTalk
                mov     R25,R16                         ; R25 = Chip Erase Counter high byte
                adiw    R24,1                           ; counter ++
                out     EEDR,R24                        ; EEDR = R24 Chip Erase Counter low byte
                movw    R26,R22                         ; R26 = Chip Erase Counter Address
                ldi     R17,6                           ; write EEPROM
                rcall   EepromTalk
                out     EEDR,R25                        ; EEDR = R25 Chip Erase Counter high byte
                rcall   EepromTalk

                rjmp    Send_CR                         ; uartSend('\r')

;****************************************************
;  页写( page write)
;****************************************************
L28:            cpi     R16,'m'                         ; else if(R16== 'm') Write page
                brne    L34
                movw    R30,R26                         ; Z-pointer = address
                ldi     R24,5                           ; SPMCR = 0x05 Write page
                out     SPMCR,R24
                spm                                     ; Store program memory
                rcall   wait_spm
L32:            rjmp    Send_CR                         ; uartSend('\r')
                                

;****************************************************
;* 进入编程模式
;****************************************************
L34:            cpi     R16,'P'                         ; else if(R16=='P') Enter programming mode
                breq    L32                             ; uartSend('\r')
                cpi     R16,'L'                         ; else if(R16=='L') Leave programming mode
                breq    L32                             ; uartSend('\r')

;********************************************************
;返回所使用编程接口方式类型,对于串行接口的返回'S',并口的'P'.
;********************************************************
                cpi     R16,'p'                         ; else if (R16=='p') Return programmer type
                brne    L38

                ldi     R16,'S'                         ; uartSend('S') Serial
                rjmp    L70                             ; uartSend(R16)

;****************************************************
; 读program memory
;****************************************************
L38:            cpi     R16,'R'                         ; else if(R16=='R') Read program memory
                brne    L40

                movw    R30,R26                         ; Z-pointer <= address

                lpm     R24,Z+                          ; read program memory LSB; store LSB in R24 and Z pointer ++
                lpm     R16,Z+                          ; read program memory MSB; store MSB in R16 and Z pointer ++
                rcall   uartSend                        ; uartSend(R16) MSB

                movw    R26,R30                         ; address += 2
                mov     R16,R24                         ; LSB stored in R16
                rjmp    L70                             ; uartSend(R16) LSB

;****************************************************
; 写EEPROM
;****************************************************
L40:            cpi     R16,'D'                         ; else if (R16=='D') Write data to EEPROM
                brne    L42

                rcall   uartGet
                out     EEDR,R16                        ; EEDR = uartGet()

                ldi     R17,6                           ; write EEPROM
                rcall   EepromTalk
                rjmp    Send_CR                         ; uartSend('\r')

;****************************************************
; 读EEPROM
;****************************************************
L42:            cpi     R16,'d'                         ; else if (R16=='d') Read data from EEPROM
                brne    L44

                ldi     R17,1                           ; read EEPROM
                rcall   EepromTalk                      ; R16 = EEPROM data
                rjmp    L70                             ; uartSend(R16)

;****************************************************
; 读熔断位和锁定位
;****************************************************
L44:            cpi     R16,'F'                         ; else if(R16=='F') Read fuse bits
                brne    L46

                clr     R30                             ; Z-pointer = 0000
                rjmp    L50                             ; rcall readFuseAndLock

;****************************************************
; 读锁定位
;****************************************************
L46:            cpi     R16,'r'                         ; else if(R16=='r') Read lock bits
                brne    L48

                ldi     R30,1                           ; Z pointer = 0001
                rjmp    L50                             ; rcall readFuseAndLock

;****************************************************
; 读熔断位高位
;****************************************************
L48:            cpi     R16,'N'                         ; else if(R16=='N') Read high fuse bits
                brne    L52
                ldi     R30,3                           ; Z-pointer = 0003

;****************************************************
; 读熔断位和锁定位
;****************************************************
L50:            rcall   readFuseAndLock
                rjmp    L70                             ; uartSend(R16)

;****************************************************
; 返回支持的芯片
;****************************************************
L52:            cpi     R16,'t'                         ; else if(R16=='t') Return supported devices code
                brne    L54

                ldi     R16,DT                          ; Device Type
                rcall   uartSend                        ; uartSend(DT) send Device Type

                clr     R16
                rjmp    L70                             ; uartSend(0)

;---  grab another char and ignore
L54:                                            ; else if ((R16=='l')||(R16=='x')||(R16=='y')||(R16=='T'))
                cpi     R16,'l'                         ; 'l' = Write Boot Loader lockbits
                breq    L56
                cpi     R16,'x'                         ; 'x' = Set LED
                breq    L56
                cpi     R16,'y'                         ; 'y' = Clear LED
                breq    L56

                cpi     R16,'T'                         ; 'T' = Select device type
                brne    L60


L56:            rcall   uartGet                         ; R16 = uartGet()
; YOU CAN INSERT LEDs CODE HERE
                rjmp    Send_CR                         ; uartSend('\r')

;********************************************************
;* 返回一个7字节ASCII字符串说明编程器类型,我的为"AVRZLM8"  :)    
;********************************************************
L60:            cpi     R16,'S'                         ; else if (R16=='S') Return software identifier
                brne    L62

Boot_ID:        ldi     R30,low(2*Soft_ID)
                ldi     R31,high(2*Soft_ID)
L61:            lpm     R16,Z+
                tst     R16
                breq    L72                             ; branch is end of string ((Z) == 0)
                rcall   uartSend                        ; else send char
                rjmp    L61

;****************************************************
;*  发送两个字节的版本信息   
;****************************************************
L62:            cpi     R16,'V'                         ; else if (R16=='V') Return Software Version
                brne    L64

                ldi     R16,'1'                         ; uartSend('1')
                rcall   uartSend
                ldi     R16,'3'                         ; uartSend('2')
                rjmp    L70                             ; uartSend(R16)

;****************************************************
;* 发送电子标签    
;****************************************************
L64:            cpi     R16,'s'                         ; else if (R16=='s') Return Signature Byte
                brne    L66

                ldi     R16,SB1                         ; uartSend(SB1) Signature Byte 1
                rcall   uartSend
                ldi     R16,SB2                         ; uartSend(SB2) Signature Byte 2
                rcall   uartSend
                ldi     R16,SB3                         ; uartSend(SB3) Signature Byte 3
                rjmp    L70                             ; uartSend(R16)

L66:            ldi     R16,'?'                         ; else uartSend('?')
                rjmp    L70                             ; uartSend(R16)

;****************************************************
;* 发送一个“回车”字符(CR)    
;****************************************************
Send_CR:        ldi     R16,13                          ; uartSend('\r')

;****************************************************
;* 发送一个Ascii字符    
;****************************************************
L70:            rcall   uartSend                        ; uartSend(R16)
L72:            rjmp    Boot_Main

readFuseAndLock:
                clr     R31                             ; Z pointer high byte = 0
                ldi     R24,9                           ; SPMCR = 0x09
                out     SPMCR,R24                       ; read fuse and lock
                lpm     R16,Z                           ; read program memory
                ret

EepromTalk:                                             ; if R17 == 6 then Write, if R17 == 1 then Read
                out     EEARL,R26                       ; EEARL = address low
                out     EEARH,R27                       ; EEARH = address high
                adiw    R26,1                           ; address++
                sbrc    R17,1                           ; skip if R17 == 1 (read Eeprom)
                sbi     EECR,EEMWE                      ; EEMWE = 1 (write Eeprom)
                out     EECR,R17                        ; EECR = R17 (6 write, 1 read)
L90:            sbic    EECR,EEWE                       ; wait until EEWE == 0
                rjmp    L90
                in      R16,EEDR                        ; R16 = EEDR
                ret

uartSend:                                               ; send R16
                sbis    UCSRA,UDRE                      ; wait for empty transmit buffer (until UDRE==1)
                rjmp    uartSend
                out     UDR,R16                         ; UDR = R16, start transmission
                ret

uartGet:        sbis    UCSRA,RXC                       ; wait for incoming data (until RXC==1)
                rjmp    uartGet
                in      R16,UDR                         ; return received data in R16
                ret

;****************************************************
;* 关键是这个子程序!!
;*    Design Note #032上的程序,是为写的,在上不能正常运行。
;*    主要问题是在页写和擦除以后,不能再重新访问RWW。
;*    现在以改正这个bug!  
;****************************************************
wait_spm:       in      R16,SPMCR
                sbrc    R16,SPMEN
                rjmp    wait_spm
                ldi     R16,(1<<RWWSRE) | (1<<SPMEN)
                out     SPMCR,R16
                spm
                ret

Soft_ID: .DB "AVRZLM8", 0 4: 其实Design Note #032没有BUG因为RWW区(应用程序区)通过写RWWSRE位和复位后都会重新开放(可以读),如果在BOOTLOAD程序中没有去读RWW(校验)就无需开放RWW区,上面的程序与Design Note #032 几乎一模一样,就是在最后加入了wait_spm,可以参考原文资料第216页,里面有很详细的介绍,只有数页,还是自己把bootload看明白更好,这样才能不被束缚手脚,举一反三
5: to cxiang20012K指的是字节(byte),1k是字(word),即程序字,由于AVR程序是16位字长,所以1个字就是2个字节,AVR这点在资料或宣传上做得很不好,为了表现自己程序大就用字节,很容易给人误导 6: 同感,如mega8程序空间为8k,实际上为4kX16bit,你只能放4k程序我用义隆的em78p156,1k空间,1kX13bit,真正能放1k程序,货真价实。

另外上面的Boot Loder程序很好用,我调试程序就用它,方便。

提醒大家的是AVRProg 能接受的波特率决不仅仅只是19200和115200,可以尝试,用高的波特率会大大加快下载速度,有切身体会。
7: 呵呵,这个bootloder本来就是改自Design Note #032

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]