;--------------------------------------------------------------------- ; FM radio tuner (RDA5807M) コントローラ ; ; 2019.09.19 naka ; 1. 概要 ; RDA5807MをI2Cでつなぎ、チャンネル(周波数)設定などを行い、 ; 局名、周波数を小型LCDディスプレイに表示する。 ; ; 選局情報はPICのFlash Memoryに覚えておき次回電源オン時に復帰する。 ; ; 2. ピンアサイン ; ; (1). RA0 [in]: SW Channel Up (ICSP DAT) ; (2). RA1 [in]: SW Channel Down (ICSP CLK) ; (3). RA2 [out]: LED(デバッグ時に使用) ; (4). RA3 [in] : (VPP) ; (5). RA4 [in] : I2C SDA ; (6). RA5 [in] : I2C SCL ; ; 3. ToDo(やってもよいかと思うこと) ; ・音量コントロール ; 当初、100円位の安いアンプを繋ぎ、ボリウムはRDA5807Mの設定で ; コントロールしようと考えていた。しかしダイソーの300円USBスピーカに ; ボリウム付きアンプが載っていたので、それをそのまま利用した。 ; ・ステレオ/モノラル表示 ; RDA5807Mには受信状態によってステレオ/モノラルのフラグがある ; のでそれを表示する。 ; ・モノラル受信 ; 強制モノラル受信もできるようなので、電波状態がよくないときに ; モノラル受信モードにする。 ; ・信号レベル表示 ; 電波の信号レベルをレベルインジケータのように表示する。 ; LCDには任意の図形を登録できるので、その機能を使う。 ; ; 4. 備考 ; ・動作クロック :内蔵OSC 8MHz ; ;--------------------------------------------------------------------- ;--------------------------------------------------------------------- ; デバイス定義 ;--------------------------------------------------------------------- LIST P=PIC12F1501 INCLUDE "P12F1501.INC" __CONFIG _CONFIG1, _FOSC_INTOSC & _CP_OFF & _BOREN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDTE_OFF & _CLKOUTEN_OFF & 0x3FFF __CONFIG _CONFIG2, _WRT_OFF & _STVREN_ON & _LVP_OFF & 0x3FFF ERRORLEVEL -302 ;アセンブル時のバンク警告メッセージ抑制 ;--------------------------------------------------------------------- ; 変数レジスタの定義 ;--------------------------------------------------------------------- WAIT1 EQU H'20' WAIT2 EQU H'21' CNT EQU H'22' TMP EQU H'23' TMP2 EQU H'24' I2CADDR EQU H'25' FREQH EQU H'26' FREQL EQU H'27' CHANNEL EQU H'70' ; どのBANKからも読み書きできる場所 ; ;--------------------------------------------------------------------- ; マクロ定義 ;--------------------------------------------------------------------- LCDTEXT MACRO text MOVLW HIGH text MOVWF FSR1H MOVLW LOW text MOVWF FSR1L ENDM ; ;--------------------------------------------------------------------- ; フラッシュ(不揮発記憶用) ;--------------------------------------------------------------------- ORG 380H ; HEFメモリ DW 0x000 ; Channel初期値 ; ;--------------------------------------------------------------------- ; リセットベクタ ;--------------------------------------------------------------------- ORG 00H ; リセット時の飛び込み先 GOTO MAIN ; ; ORG 04H ; 割り込み時の飛び込み先 ;--------------------------------------------------------------------- ; 割り込み処理(SW RA0,RA1の立下り割り込み) ;--------------------------------------------------------------------- INTRUPT CLRF INTCON ;全割込み禁止 CALL W20MS ; BANKSEL IOCAF BTFSC IOCAF,0 GOTO INT_UP BTFSC IOCAF,1 GOTO INT_DOWN CLRF IOCAF BANKSEL 0 GOTO INT_RET ; INT_UP ; 選局アップ BCF IOCAF,0 BANKSEL 0 BTFSC PORTA,0 ; SW low 確認 GOTO INT_RET INCF CHANNEL,F MOVF CHANNEL,W SUBLW D'10' BTFSC STATUS,Z CLRF CHANNEL ; CHANNEL = 0〜9 CALL CHSELECT BTFSS PORTA,0 GOTO $-1 GOTO INT_SET ; INT_DOWN ; 選局ダウン BCF IOCAF,1 BANKSEL 0 BTFSC PORTA,1 ; SW low 確認 GOTO INT_RET DECF CHANNEL,F MOVF CHANNEL,W SUBLW D'255' BTFSS STATUS,Z GOTO $+3 MOVLW D'9' ; CHANNEL = 0〜9 MOVWF CHANNEL CALL CHSELECT BTFSS PORTA,1 GOTO $-1 ; INT_SET CALL ERASFLSH ; CHANNEL情報をFlashに記憶 CALL WRITFLSH ; CALL W20MS ; INT_RET MOVLW B'10001000' ; 割り込み許可 GIE,IOCIE MOVWF INTCON ; RETFIE ;--------------------------------------------------------------------- ; メイン処理 ;--------------------------------------------------------------------- MAIN CALL INIT ; LCDTEXT MSGDT ; 電源オン時の起動メニュー(LCD) CALL DSPTXT CALL W05S ; CALL READFLSH ; 前回のチャンネル情報を復帰 CALL CHSELECT ; SLEEP GOTO $-1 ; MSGDT DT "FM Radio"," Ver.1" ; ;--------------------------------------------------------------------- ; 初期化 ;--------------------------------------------------------------------- INIT CLRF INTCON ;全割込み禁止 ; BANKSEL PORTA CLRF PORTA BANKSEL LATA CLRF LATA BANKSEL ANSELA CLRF ANSELA ; digital I/O BANKSEL TRISA MOVLW B'00000011' ; RA0,RA1 input MOVWF TRISA BANKSEL OSCCON MOVLW B'01110010' ; 8MHz MOVWF OSCCON ; BANKSEL OPTION_REG CLRF OPTION_REG BANKSEL IOCAP CLRF IOCAP MOVLW B'00000011' ; RA0,RA1 Negative edge interupt MOVWF IOCAN BANKSEL 0 ; CLRF CHANNEL ; 後でflashから復元された値が入る ; CALL LCDINIT ; MOVLW B'10001000' ; 割り込み許可 GIE,IOCIE MOVWF INTCON RETURN ; ;--------------------------------------------------------------------- ; 選局(CHANNEL) ;--------------------------------------------------------------------- CHSELECT MOVLW HIGH FMDATA ; 局名テーブル MOVWF FSR1H MOVLW LOW FMDATA MOVWF FSR1L ; MOVF CHANNEL,W MOVWF TMP ; BCF STATUS,C ; 18倍(テーブルサイズが18byte/局) RLF TMP,W ; 2 MOVWF TMP MOVWF TMP2 RLF TMP,F ; 4 RLF TMP,F ; 8 RLF TMP,W ; 16 ADDWF TMP2,W ADDWF FSR1L,F ; 局名テーブルに加算 CLRW ADDWFC FSR1H,F ; キャリー加算 CALL DSPTXT ; 曲名表示 ; CALL GETFREQ ; 周波数取り出し CALL SETFREQ ; 周波数設定 RETURN ; GETFREQ MOVF INDF1,W MOVWF FREQH ADDFSR FSR1,1 MOVF INDF1,W MOVWF FREQL RETURN ; ; 周波数設定値の計算方法 ; 例) ; TOKYO FM 80.0MHz = 100KHz x CHAN + 76.0MHz ; CHAN= D'40' = H'28' = B'00001010,00' FMDATA ; 1局あたり18byte ; LCD 1行目 LCD 2行目 周波数 局No. DT "NACK5 "," 79.5MHz",B'00001000',B'11011000' ; 0 DT "TOKYO FM"," 80.0MHz",B'00001010',B'00011000' ; 1 DT "J-WAVE "," 81.3MHz",B'00001101',B'01011000' ; 2 DT "NHK YKH "," 81.9MHz",B'00001110',B'11011000' ; 3 DT "NHK TKO "," 82.5MHz",B'00010000',B'01011000' ; 4 DT "YOKOHAMA"," 84.7MHz",B'00010101',B'11011000' ; 5 DT "InterFM "," 89.7MHz",B'00100010',B'01011000' ; 6 DT "TBS FM "," 90.5MHz",B'00100100',B'01011000' ; 7 DT "BUNKA FM"," 91.6MHz",B'00100111',B'00011000' ; 8 DT "NIPPON "," 93.0MHz",B'00101010',B'10011000' ; 9 ; ;--------------------------------------------------------------------- ; 周波数設定 ;--------------------------------------------------------------------- SETFREQ MOVLW H'20' ; I2Cアドレス CALL I2CWSTART ; ; Reg 0x02 MOVLW B'11010000' ; DHIZ,DMUTE,MONO,BASS,RCLK,RCLK,SEEKUP,SEEK MOVWF datao CALL TX MOVLW B'00000001' ; SKMODE,CLK_MODE[2:0],RDS_EN,NEW_METHOD,SOFT_RESET,ENABLE MOVWF datao CALL TX ; ; Reg 0x03 MOVF FREQH,W ; CHAN[9:2] MOVWF datao CALL TX MOVF FREQL,W ; CHAN[1:0],DIRECT MODE, TUNE,BAND[1:0],SPACE[1:0] MOVWF datao CALL TX ; Reg 0x04 MOVLW B'00000000' ; RSVD[15:12],DE,RSVD,SOFTMUTE_EN,AFCD MOVWF datao CALL TX MOVLW B'00000000' ; MOVWF datao CALL TX ; Reg 0x05 MOVLW B'10001000' ; INT_MODE,RSVD,SEEKTH[3:0] MOVWF datao CALL TX MOVLW B'10001111' ; ,RSVD,VOLUME[3:0] MOVWF datao CALL TX ; CALL I2CSTOP ; RETURN ;--------------------------------------------------------------------- ; 文字列表示 ; 表示する文字列はLCDTEXTマクロで指定 ;--------------------------------------------------------------------- DSPTXT MOVLW D'16' MOVWF CNT CLRF TMP ; MOVLW H'80' + H'00' ; LCD1行目先頭へ CALL LCDCMD DSPTXTLP MOVF CNT,W SUBLW D'8' ; 9文字目以上は2行目に表示 BTFSS STATUS,Z GOTO DSPTXT1 MOVLW H'80' + H'40' ; LCD2行目先頭へ CALL LCDCMD DSPTXT1 MOVF INDF1,W CALL LCDDATA ; MOVWF INDF1 ADDFSR FSR1,1 INCF TMP,F DECFSZ CNT,F GOTO DSPTXTLP ; RETURN ;--------------------------------------------------------------------- ; LCD初期化(データシート通り) ;--------------------------------------------------------------------- LCDINIT CALL W20MS ; 電源が安定するまでの待ち時間 CALL W20MS ; MOVLW H'38' ; Function set CALL LCDCMD ; MOVLW H'39' ; Functino set CALL LCDCMD ; MOVLW H'14' ; Intrenal OSC frequency CALL LCDCMD ; ;; MOVF CNTRST,W ; コントラスト ;; ANDLW H'0F' ; 下位4ビット ;; IORLW H'70' ;; CALL LCDCMD ;; SWAPF CNTRST,W ;; ANDLW H'03' ; 上位2ビット ;; IORLW H'54' ;; CALL LCDCMD ; ; ; Contrast= B'10 1000' = D'40' MOVLW H'70'+H'08' ; Contrast set CALL LCDCMD ; MOVLW H'54'+H'02' ; Power/ICON/Contrast control CALL LCDCMD ; MOVLW H'6C' ; Follower control CALL LCDCMD CALL W200MS ; MOVLW H'38' ; Function set CALL LCDCMD ; MOVLW H'0C' + H'01' ; Display ON/OFF control CALL LCDCMD ; MOVLW H'01' ; Clear Display CALL LCDCMD ; RETURN ; ;--------------------------------------------------------------------- ; LCDコマンド (W:CMD) ;--------------------------------------------------------------------- LCDCMD MOVWF TMP ; 一時退避 ; MOVLW H'7C' ; I2Cアドレス CALL I2CWSTART MOVLW H'00' ; Command (RS=0) MOVWF datao CALL TX MOVF TMP,W MOVWF datao CALL TX CALL I2CSTOP ; MOVLW H'01' ; Clear Display SUBWF TMP,W BTFSC STATUS,Z GOTO LCDW1MS MOVLW H'02' ; Return Home SUBWF TMP,W BTFSC STATUS,Z GOTO LCDW1MS ; CALL W27US ; Normal command RETURN LCDW1MS CALL W1MS RETURN ; ;--------------------------------------------------------------------- ; LCD データ(Wレジ内容をLCDに書き込む) ;--------------------------------------------------------------------- LCDDATA MOVWF TMP ; 書き込みデータ一時退避 ; MOVLW H'7C' CALL I2CWSTART ; MOVLW H'40' ; Data (RS=1) MOVWF datao CALL TX ; MOVF TMP,W MOVWF datao CALL TX ; CALL I2CSTOP ; RETURN ; ;--------------------------------------------------------------------- ; ウェイト色々 ;--------------------------------------------------------------------- W27US MOVLW D'18' MOVWF WAIT1 W27USLP DECFSZ WAIT1,F GOTO W27USLP RETURN ; W1MS MOVLW D'221' MOVWF WAIT1 W1MSLP GOTO $+1 GOTO $+1 GOTO $+1 DECFSZ WAIT1,F GOTO W1MSLP GOTO $+1 GOTO $+1 GOTO $+1 RETURN ; W20MS MOVLW D'20' MOVWF WAIT2 W20MSLP CALL W1MS DECFSZ WAIT2,F GOTO W20MSLP RETURN ; W200MS MOVLW D'200' MOVWF WAIT2 W200MSLP CALL W1MS DECFSZ WAIT2,F GOTO W200MSLP RETURN ; W05S MOVLW D'100' MOVWF WAIT2 W05SLP CALL W1MS CALL W1MS CALL W1MS CALL W1MS CALL W1MS DECFSZ WAIT2,F GOTO W05SLP RETURN ; ;--------------------------------------------------------------------- ; I2Cアクセスルーチン ; 流用元:Microchip Applicatin Note : AN982 ; Interfacing I2C Serial EEPROMs to PIC10 and PIC12 Drivers ;--------------------------------------------------------------------- ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; ; Filename: i2c_routines.inc ; Date: March 21, 2005 ; File Version: 1.0 ; Assembled using: MPLAB IDE 7.00.00.0 ; ; Author: Chris Parris ; Company: Microchip Technology, Inc. ; ;*******************RAM register definitions********************** #define STARTRAM 0x40 ; Start RAM at address 0x40 cblock STARTRAM buffer ; Transfer/Receive bit buffer datai ; Data input byte buffer datao ; Data output byte buffer bitcount ; Bit loop counter bytecount ; Byte loop counter addressH ; Word address pointer addressL ; Word address pointer loops ; Delay loop counter loops2 ; Delay loop counter pollcnt ; Polling loop counter endc ;*******************Bit definitions******************************* SDA equ 4 ; I2C data pin, PORTA pin GP4 SCL equ 5 ; I2C clock pin, PORTA pin GP5 DO equ 0 ; TX/RX buffer output bit DI equ 1 ; TX/RX buffer input bit ACKB equ 2 ; ACK/NO ACK select bit ;*******************Delay Macros********************************** ; Each macro delay for 1 inst. cycle less than ; required, as the instruction immediately ; before the macro call provides 1 inst. cycle. ;***************************************************************** THIGH macro ; Clock high time delay (5 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) nop ; 0.5us endm THDSTA macro ; Start condition hold time delay (5 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) nop ; 0.5us endm TSUSTA macro ; Start condition setup time delay (5 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) nop ; 0.5us endm TSUSTO macro ; Stop condition setup time delay (5 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) nop ; 0.5us endm TAA macro ; Output valid from clock delay (4 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) goto $+1 ; 2-inst. cycle delay (1 us) nop ; 0.5us endm ;------------------------------------------------------------------- ; I2Cアクセス ;------------------------------------------------------------------- I2CWSTART MOVWF I2CADDR ; I2Cアドレス退避 movlw .8 movwf bytecount ; Initialize counter to 16 bytes txbyte call BSTART ; Generate start bit ; Now send the control byte ; for a write, to set address movf I2CADDR,W ; I2Cアドレス movwf datao ; Copy control byte to buffer call TX ; Output control byte to device ; Next, the address pointer RETURN I2CSTOP CALL NOACK call BSTOP ; Generate stop bit RETURN ; I2CRSTART IORLW H'01' MOVWF I2CADDR ; I2Cアドレス退避 movlw .8 movwf bytecount ; Initialize counter to 16 bytes rxbytec call BSTART ; Generate start bit ; Now send the control byte ; for a write, to set address movf I2CADDR,W movwf datao ; Copy control byte to buffer call TX ; Output control byte to device clrf datao ; 0x00アドレス call TX ; Output address to device call BSTART ; Generate another start bit ; to switch to read mode movf I2CADDR,W movwf datao ; Copy control byte to buffer call TX ; Output control byte to device ; Finally, read the data byte RETURN ;*******************Start bit subroutine************************** ; This routine generates a Start condition ; (high-to-low transition of SDA while SCL ; is still high. ;***************************************************************** BSTART bsf PORTA,SCL ; Make sure SCL is high TSUSTA ; Start condition setup time delay BANKSEL 1 BCF TRISA,SDA ; Configure SDA to be an output BANKSEL 0 bcf PORTA,SDA ; Pull SDA low to initiate ; Start condition THDSTA ; Start condition hold time delay bcf PORTA,SCL ; Bring SCL low in preparation ; for data transfer BANKSEL 1 BSF TRISA,SDA ; Configure SDA to be an input BANKSEL 0 retlw 0 ;*******************Stop bit subroutine*************************** ; This routine generates a Stop condition ; (low-to-high transition of SDA while SCL ; is still high. ;***************************************************************** BSTOP BANKSEL 1 BCF TRISA,SDA ; Configure SDA to be an output BANKSEL 0 bcf PORTA,SDA ; Pull SDA low bsf PORTA,SCL ; Make sure SCL is high TSUSTO ; Stop condition setup time delay BANKSEL 1 BSF TRISA,SDA ; Configure SDA to be an input BANKSEL 0 retlw 0 ;*******************Bit output subroutine************************* ; This routine outputs bit 'DO' in 'buffer' to ; the serial EEPROM device. ;***************************************************************** BITOUT bcf PORTA,SCL ; Make sure SCL is low btfss buffer,DO ; Check for state of bit to xmit goto bitlow ; If bit is low, pull SDA low clockout ; If bit is high, leave SDA high bsf PORTA,SCL ; Bring SCL high to begin transfer THIGH ; Clock high time delay bcf PORTA,SCL ; Bring SCL low again BANKSEL 1 BSF TRISA,SDA ; Configure SDA to be an input BANKSEL 0 retlw 0 bitlow BANKSEL 1 BCF TRISA,SDA ; Configure SDA to be an output BANKSEL 0 bcf PORTA,SDA ; Pull SDA low goto clockout ;*******************Bit input subroutine************************** ; This routine inputs a bit of data from the ; serial EEPROM device, and stores it in bit ; 'DO' of 'buffer'. ;***************************************************************** BITIN bcf PORTA,SCL ; Make sure SCL is low BANKSEL 1 BSF TRISA,SDA ; Configure SDA to be an input BANKSEL 0 bsf buffer,DI ; Assume input bit is high bsf PORTA,SCL ; Bring SCL high to begin transfer TAA ; Output valid from clock delay btfss PORTA,SDA ; Check for state of SDA bit bcf buffer,DI ; If SDA is low, set bit low bcf PORTA,SCL ; Bring SCL low again retlw 0 ;*******************Data transmit subroutine********************** ; This routine transmits the byte of data ; stored in 'datao' to the serial EEPROM ; device. Instructions are also in place ; to check for an ACK bit, if desired. ; Just replace the 'goto' instruction, ; or create an 'ackfailed' label, to provide ; the functionality. ;***************************************************************** TX movlw .8 movwf bitcount ; Initialize loop counter to 8 txlp bsf buffer,DO ; Assume output bit is high btfss datao,7 ; Check state of next output bit bcf buffer,DO ; If low, set buffer bit low call BITOUT ; Call routine to output bit rlf datao,F ; Rotate datao left for next bit decfsz bitcount,F ; Decrement counter, check if done goto txlp ; Keep looping ; call BITIN ; Call routine to read ACK bit CALL ACK retlw 0 ;*******************Data receive subroutine*********************** ; This routine reads in one byte of data from ; the serial EEPROM device, and stores it in ; 'datai'. It then responds with either an ; ACK or a NO ACK bit, depending on the value ; of 'ACKB' in 'buffer'. ;***************************************************************** RX clrf datai ; Clear input buffer movlw .8 movwf bitcount ; Initialize loop counter to 8 bcf STATUS,C ; make sure carry bit is low rxlp rlf datai,F ; Rotate datai 1 bit left call BITIN ; Read a bit btfsc buffer,DI bsf datai,0 ; Set bit 0 if necessary decfsz bitcount,F ; 8 bits done? goto rxlp ; If not, do another RETLW 0 ACK bcf buffer,DO ; If ACKB = 1, send ACK (DO = 0) call BITOUT ; Send bit retlw 0 NOACK bsf buffer,DO ; If ACKB = 1, send ACK (DO = 0) call BITOUT ; Send bit retlw 0 ; ;--------------------------------------------------------------------- ; flashメモリから読み出す ; W:アドレス ; 0:0x0380 Channel情報 → H'70' ;--------------------------------------------------------------------- READFLSH ; This code block will read 1 word of program ; memory at the memory address: PROG_ADDR_HI : PROG_ADDR_LO ; data will be returned in the variables;PROG_DATA_HI, PROG_DATA_LO BANKSEL PMADRL ; Select Bank for PMCON registers MOVLW H'03' ; 0x0380 から読み出す MOVWF PMADRH ; Store MSB of address MOVLW H'80' ; MOVWF PMADRL ; Store LSB of address BCF PMCON1,CFGS ; Do not select Configuration Space BSF PMCON1,RD ; Initiate read NOP ; Ignored (Figure 10-2) NOP ; Ignored (Figure 10-2) MOVF PMDATL,W ; Get LSB of word MOVWF CHANNEL ; Store in user location BANKSEL 0 RETURN ; ;--------------------------------------------------------------------- ; flashメモリ消去 ; 0x380H 〜 0x38FH (16バイト) ;--------------------------------------------------------------------- ERASFLSH ; This row erase routine assumes the following: ; 1. A valid address within the erase row is loaded in ADDRH:ADDRL ; 2. ADDRH and ADDRL are located in shared data memory 0x70 - 0x7F (common RAM) BCF INTCON,GIE ; Disable ints so required sequences will execute properly BANKSEL PMADRL MOVLW H'03' MOVWF PMADRH MOVLW H'80' MOVWF PMADRL BCF PMCON1,CFGS ; Not configuration space BSF PMCON1,FREE ; Specify an erase operation BSF PMCON1,WREN ; Enable writes MOVLW 55h ; Start of required sequence to initiate erase MOVWF PMCON2 ; Write 55h MOVLW 0AAh ; MOVWF PMCON2 ; Write AAh BSF PMCON1,WR ; Set WR bit to begin erase NOP ; NOP instructions are forced as processor starts NOP ; row erase of program memory. ; ; The processor stalls until the erase process is complete ; after erase processor continues with 3rd instruction BCF PMCON1,WREN ; Disable writes BSF INTCON,GIE ; Enable interrupts BANKSEL 0 RETURN ; ;--------------------------------------------------------------------- ; flashメモリ書き込み ; 0x70H〜0x7FH → 0x380H 〜 0x38FH (16ワード) ;--------------------------------------------------------------------- DATA_ADDR EQU H'70' WRITFLSH ; This write routine assumes the following: ; 1. 32 bytes of data are loaded, starting at the address in DATA_ADDR ; 2. Each word of data to be written is made up of two adjacent bytes in DATA_ADDR, ; stored in little endian format ; 3. A valid starting address (the least significant bits = 00000) is loaded in ADDRH:ADDRL ; 4. ADDRH and ADDRL are located in shared data memory 0x70 - 0x7F (common RAM) BCF INTCON,GIE ; Disable ints so required sequences will execute properly BANKSEL PMADRH ; Bank 3 MOVLW H'03' MOVWF PMADRH ; MOVLW H'80' MOVWF PMADRL ; MOVLW LOW DATA_ADDR ; Load initial data address MOVWF FSR0L ; MOVLW HIGH DATA_ADDR ; Load initial data address MOVWF FSR0H ; BCF PMCON1,CFGS ; Not configuration space BSF PMCON1,WREN ; Enable writes BSF PMCON1,LWLO ; Only Load Write Latches LOOP MOVIW FSR0++ ; Load first data byte into lower MOVWF PMDATL ; MOVIW FSR0++ ; Load second data byte into upper MOVWF PMDATH ; MOVF PMADRL,W ; Check if lower bits of address are '00000' XORLW 0x01 ANDLW 0x01 BTFSC STATUS,Z ; Exit if last of 16 words, GOTO START_WRITE ; MOVLW 55h ; Start of required write sequence: MOVWF PMCON2 ; Write 55h MOVLW 0AAh ; MOVWF PMCON2 ; Write AAh BSF PMCON1,WR ; Set WR bit to begin write NOP ; NOP instructions are forced as processor ; loads program memory write latches NOP ; INCF PMADRL,F ; Still loading latches Increment address GOTO LOOP ; Write next latches START_WRITE BCF PMCON1,LWLO ; No more loading latches - Actually start Flash program ; memory write MOVLW 55h ; Start of required write sequence: MOVWF PMCON2 ; Write 55h MOVLW 0AAh ; MOVWF PMCON2 ; Write AAh BSF PMCON1,WR ; Set WR bit to begin write NOP ; NOP instructions are forced as processor writes ; all the program memory write latches simultaneously NOP ; to program memory. ; After NOPs, the processor ; stalls until the self-write process in complete ; after write processor continues with 3rd instruction BCF PMCON1,WREN ; Disable writes BSF INTCON,GIE ; Enable interrupts BANKSEL 0 RETURN ; ;--------------------------------------------------------------------- END ;--------------------------------------------------------------------- ; 終わり ;---------------------------------------------------------------------