; Copyright 2006 Yamane Akira ; ATmeg48 Self Programming Example ; フラッシュ・メモリに置かれているメッセージ(data1)をPCのCOMポート ; (ハイパーターミナルを用いる)で ; 書き換えるプログラム(データシートのプログラム例を参考に ; 書き換えた。) ; Programmed by A. Yamane (2006/1) .include "m48def.inc" .equ PAGESIZEB = PAGESIZE*2 ;PAGESIZEB is page size in BYTES, not words .def temp1=r16 .def temp2=r17 .def looplo=r24 .def loophi=r25 .def spmcrval=r20 .org 0x0000 Reset: rjmp main .org 0x0080 Rx_char: ; UART Rx 1char lds R2, UCSR0A sbrs R2, 7 ; UCSR0AレジスタのRXC0ビットが1 rjmp Rx_char ; になるまで待つ lds temp1, UDR0 ; データを読み、temp1に載せて戻す ret Tx_char: ; UART Tx 1Char lds R2,UCSR0A sbrs R2, 5 ; UCSR0AレジスタのUDRE0ビットが1 rjmp Tx_char ; になるまで待つ sts UDR0, temp1 ; UARTデータ・レジスタにデータをセット ret string_out: lpm temp1, Z+ ; data1のデータをr16へ取り出しZポインターを+1 cpi remp1, 0xFF ; データがFFかを調べる breq end_s_out ; もしFFであったならばend_s_outへブランチ rcall Tx_char ; FFでなければ、1文字USARTへ出力 rjmp String_out ; 繰り返す end_s_out: ret main: ; initialize Stack ldi temp1, low(RAMEND) out SPL, temp1 ldi temp1, high(RAMEND) out SPH, temp1 ; initialize IO ser temp1 out PORTB, temp1 out PORTC, temp1 out PORTD, temp1 out DDRB, temp1 ; UART Init clr temp1 ; Disable, while setting sts UCSR0B, temp1 sts UCSR0A, temp1 ldi temp2, 0x06 sts UCSR0C, temp2 ldi temp2, 0x19 ; Baud Rate = 19200 sts UBRR0L, temp2 ldi temp2, 0x00 sts UBRR0H, temp2 ldi temp2, 0x18 sts UCSR0B, temp2 ; data1に入っているメッセージを表示 Page_out: ldi r16,0x0d ; キャリッジ・リターン rcall Tx_char ldi r16,0x0a ; ライン・フィード rcall Tx_char ldi ZH, high(data1<< 1) ; Zポインターの値をdata1にセット ldi ZL, low(data1<< 1) ; Wordアドレスとバイトアドレスの変換 ; のため1ビットシフト rcall string_out ; バッファを消去(0xFF) ldi looplo, low(PAGESIZEB)-1 ;init loop variable ldi YL, low(Buffer) ; バッファーアドレスをY-regへロード ldi YH, high(Buffer) ldi temp1, 0xFF clrloop: st Y+, temp1 dec looplo brbc 1, clrloop ; バッファへ文字列を入力 DATA_IN: ldi looplo, low(PAGESIZEB)-1 ldi YL, low(Buffer) ; バッファーアドレスをY-regへロード ldi YH, high(Buffer) ldi r16,0x0d ; キャリッジ・リターン rcall Tx_char ldi r16,0x0a ; ライン・フィード rcall Tx_char ldi temp1, 0x3E ; プロンプトを出力 rcall Tx_char d_in_buffer: rcall Rx_char cpi temp1, 0x1B ; もしESCを入力したら breq Write_page ; Write_pageへ dec looplo ; もしページサイズを超えたら brbs 1, Write_page ; Write_pageへ rcall Tx_char st Y+, temp1 ; 入力した1文字をバッファへロード、アドレス+1 rjmp d_in_buffer ; Write_page: ldi r16,0x0a ; ライン・フィード rcall Tx_char ldi ZL, low(data1<<1) ; メッセージ・アドレスをZregへロード ldi ZH, high(data1<<1) ; Page Erase ldi spmcrval, (1<