#include <xc.h> #define _XTAL_FREQ 8000000 // 使用するPIC等により動作周波数値を設定する main (void) { __delay_us(100) ; // 100us遅延する __delay_ms(500) ; // 500ms遅延する }こんな感じです。
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0))) #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))__delay(x)はインライン関数です、数値(x)の指定は定数で変数指定は出来ません、
なので、システム周波数を8MHz(1サイクル=500ns)とした場合は、 __delay_ms(100) ; __delay_us(100000) ; _delay(200000) ; // (100)*(8000000/4000) 又は (100000)*(8000000/4000000) これはすべて同じ長さ100ms(200000*500ns)待ちます。__delay( )はインライン関数なのでコンパイラ(XC8)が、サイクル数に見合った長さだけの命令コード数を
例えばこんな感じです、1命令辺り1〜3サイクル消費します。 ;test.c: 88: _delay((unsigned long)((500)*(8000000/4000.0))) ; opt asmopt_off movlw 6 movlb 0 ; select bank0 movwf ((??_main+0)+0+2),f movlw 19 movwf ((??_main+0)+0+1),f movlw 177 movwf ((??_main+0)+0),f u1517: decfsz ((??_main+0)+0),f goto u1517 decfsz ((??_main+0)+0+1),f goto u1517 decfsz ((??_main+0)+0+2),f goto u1517 nop2 opt asmopt_onですので、Delayは正確に動作しますが、指定は定数のみ変数不可と言う事です。
4MHz | 8MHz | 16MHz | 32MHz | 64MHz | |
__delay_us | 50462464 | 25231232 | 12615616 | 6307808 | 3153904 |
__delay_ms | 50462 | 25231 | 12615 | 6307 | 3153 |
_delay | 50462464 | 50462464 | 50462464 | 50462464 | 50462464 |
4MHz | 8MHz | 16MHz | 32MHz | 48MHz | 64MHz | |
__delay_us | 197120 | 98560 | 49280 | 24640 | 16426 | 12320 |
__delay_ms | 197 | 98 | 49 | 24 | 16 | 12 |
_delay | 197120 | 197120 | 197120 | 197120 | 197120 | 197120 |
// 指定した時間(num x 10ms)だけウエイトを行う処理関数 *1) void Wait(int num) { // numで指定した回数だけ繰り返す do { __delay_ms(10) ; // 10msプログラムの一時停止 } while(--num > 0); }って感じでループさせれば良いのですがぁ、__delay_ms(10)は時間は正確です、
こんな感じで作成されています。 ; Delay = 1 seconds ; Clock frequency = 8 MHz ; Actual delay = 1 seconds = 2000000 cycles ; Error = 0 % cblock d1 d2 d3 endc Delay ;1999996 cycles movlw 0x11 movwf d1 movlw 0x5D movwf d2 movlw 0x05 movwf d3 Delay_0 decfsz d1, f goto $+2 decfsz d2, f goto $+2 decfsz d3, f goto Delay_0 ;4 cycles (including call) return ; Generated by http://www.piclist.com/cgi-bin/delay.exe (December 7, 2005 version) ; Wed Feb 11 09:33:48 2015 GMT ; See also various delay routines at http://www.piclist.com/techref/microchip/delays.htmこのルーチンは関数になっているので、CALL/RETURN命令で4サイクル消費するから
#include <xc.h> volatile persistent char d1,d2,d3 ; // 変数名は変えてもOK void Delay1s(void) { #asm ;1999996 cycles movlw 0x11 movwf _d1 movlw 0x5D movwf _d2 movlw 0x05 movwf _d3 Delay_0: decfsz _d1, f goto $+2 decfsz _d2, f goto $+2 decfsz _d3, f goto Delay_0 ;4 cycles (including call) #endasm } main() { while(1) { RA0 = 1 ; Delay1s() ; RA0 = 0 ; Delay1s() ; } }こんな感じです、アセンブラ内で変数名を書く場合は変数の前に_(アンダーバー)を付けます。
; Delay = 0.5 seconds ; Clock frequency = 8 MHz ; Actual delay = 0.5 seconds = 1000000 cycles ; Error = 0 % cblock d1 d2 d3 endc Delay ;999990 cycles movlw 0x07 movwf d1 movlw 0x2F movwf d2 movlw 0x03 movwf d3 Delay_0 decfsz d1, f goto $+2 decfsz d2, f goto $+2 decfsz d3, f goto Delay_0 ;6 cycles goto $+1 goto $+1 goto $+1 ;4 cycles (including call) returnこれをインラインアセンブラ用に書き換えます。
void Delay500ms() { #asm ;999990 cycles movlw 0x07 movwf _d1,0 movlw 0x2F movwf _d2,0 movlw 0x03 movwf _d3,0 Delay_0: decfsz _d1,1 goto $+6 decfsz _d2,1 goto $+6 decfsz _d3,1 goto Delay_0 ;6 cycles goto $+4 goto $+4 goto $+4 ;4 cycles (including call) #endasm }PIC18系で動作させるには赤文字の様に書き換えます、goto命令は2ワードなので飛び先も変更です。
プログラム記述変更(*1) 2015/03/08
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2015 Shigehiro Kimura All Rights Reserved.