/***************************************************************** UltraSonic US-015 By JA3OOK 中村 利和 v1.0 2017/9 正式版      ------------------------------------------------------------------ 開発環境 MPLAB X IDE MPLAB XC8 C Compiler Free mode ******************************************************************/ // refer \c:Program Files(x86)\Microchip\xc8\v1.40\docs\chips\16f1619.html #pragma config BOREN =OFF //Brown-out Reset enable #pragma config WRT =OFF //Write protection off #pragma config FOSC =INTOSC //INTOSC oscillator: I/O function on CLKIN pin #pragma config PLLEN =OFF //4x PLL is enabled when software sets the SPLLEN bit #pragma config MCLRE =OFF //MCLR disabled #pragma config WDTE =OFF //WDT disabled #pragma config CP =ON //Code protection on #pragma config LVP =OFF //RB3 is digital I/O, HV on MCLR must be used for programming #pragma config PWRTE =OFF //Power-up Timer Enable #pragma config IESO =OFF //Internal External Switchover mode disabled #pragma config FCMEN =OFF //Fail-Safe Clock Monitor disabled #include "pic16f1619.h" #include #include "lcd_v2.h" #define MHz 000000 //#define _XTAL_FREQ 8MHz //PIC_OSC_FREQ #define _XTAL_FREQ 1MHz //PIC_OSC_FREQ // Version and author #define ver " v1.0 " #define author "JA3OOK " //入力ポートは Rxx を記述 出力ポートは LATxx を記述 #define lcd_vdd LATC0 // VDD of LCD #define RA3 RA3 // Dummy #define trigger LATA5 // Trigger #define echo RA4 // Echo SMT1SIG unsigned int t1count ; // タイマー設定値 unsigned int count_for_trig ; // triggerタイミングのために割込み発生回数をカウントする変数 unsigned int echo_w ; // パルス幅 //unsigned short long echo_w ; // パルス幅 bit trigger_flag; // trigger timing flag bit measure; // 計測中 unsigned int timer; //temporaryタイマー用(符号無し16ビット長) unsigned char str[21]; //temporary work void interrupt InterTimer( void ){ // タイマー割込み if(TMR1IF == 1) { // タイマー1の割込み発生か? TMR1H = (t1count >> 8); // タイマーの初期化 TMR1L = (t1count & 0x00FF) ; // タイマーの初期化 TMR1IF = 0 ; // タイマー割込フラグをリセット // count_for_trig++ ; // 割込み発生回数をカウント // if(count_for_trig >= 2){ //割り込み2回で1秒 trigger_flag = 1; //測定指示 // count_for_trig = 0; // } } } void Analize_distance(void){ //SMT1(SIGNAL MEASUREMENT TIMER 1)を設定 SMT1CON0 = 0b10000000; //SMT1有効 プリスケーラー1:1 SMT1CON1 = 0b00000010; //まだ開始しない 1回のみ計測 SMTの動作モードは周期とduty計測 SMT1STAT = 0b00000000; SMT1CLK = 0b00000001; //クロック単位は Fosc/4 SMT1WIN = 0b00000000; SMT1SIG = 0b00000000; //信号入力はSMT1SIGピン //初期値設定 測定はまだだよ count_for_trig = 0; trigger_flag = 0; measure = 0; while(1){ //無限loop if(trigger_flag){ //測定指示あり trigger_flag = 0; trigger = 1; __delay_us(15); // 10us以上 trigger = 0; SMT1GO = 1; //測定開始せよ(echo信号ONの幅をもとにカウント数を求める) measure = 1; } if(measure && !SMT1GO){ //測定中で、SMT1GOが0か? measure = 0; // SMT1CPWU 今回のセンサーの場合は使わなくて(値をzeroとみなして)大丈夫 echo_w = (SMT1CPWH << 8); //echo_w = SMT1CPWH * 256; と同じ意味 echo_w = echo_w + SMT1CPWL; //カウント数が求まった // Lcd_goto(0x07); //LCDの表示位置を指定 // Bin2str(echo_w, str, 5);//2進数を10進数へ変換 // Lcd_puts(str); // カウント数を表示 //距離の計算条件 音速=346m(温度24度) CPUクロックが1MHz、その1/4毎にカウントアップ // 音速は温度が低いほど遅くなる (338m 温度10度) //計算 対象物までの距離1cm、往復2cmに要する音速での時間は 2/(346*100)=57.8us //   1カウントの時間は 1/(1000000/4)=4us //  従って往復2cm(対象物までの距離1cm)の場合のカウント数は 57.8us/4us=14.45カウント 14.5カウントと約す //   カウント数から距離を求める次の計算は整数型で行っているので、小数点以下の誤差をなくす目的で10倍して計算している if(echo_w < 6550){ echo_w = (echo_w * 10 / 145); // 対象物までの距離をcmへ換算  Lcd_goto(0x00); //LCDの表示位置を指定 Bin2strB(echo_w, str, 3);//2進数を10進数へ変換(ゼロサプレス) Lcd_puts(str); // 距離を表示 Lcd_puts("cm"); }else{ Lcd_goto(0x00); //LCDの表示位置を指定 Lcd_puts("over "); } } } } void main(void){ // see Data sheet PIC16F1619 //OSCCON = 0b01110010 ;//internal OSC 8Mz OSCCON = 0b01011000; //internal OSC 1Mz OPTION_REG = 0b10001000; //All weak pull-ups are disabled (except MCLR, if it is enabled) //Prescaler is not assigned to the Timer0 module // LCDのVDDをONする前は、LCDへのすべてのポートはlowであること。 ANSELA= 0b00000000; //All デジタル(既定値:アナログ) TRISA = 0b00011000; //RA4:Echo=SMT1SIG RA3:input(dummy) PORTA = 0b00000000; // WPUA = 0b00000000; // ANSELB= 0b00000000; //All デジタル(既定値:アナログ) TRISB = 0b00000000; // PORTB = 0b00000000; //初期化 ANSELC= 0b00000000; //All デジタル(既定値:アナログ) TRISC = 0b00000000; // PORTC = 0b00000000; // WPUC = 0b00000000; // // PPS(PERIPHERAL PIN SELECT MODULE)を設定 // SMT1SIG の既定ピンは RA4 (see Data sheet P182,P180) // SMT1SIGPPS = 0b00000100; //SMT1計測シグナルの入力ポート:RA4 (see Data sheet P182,P180) T1CON = 0b00110001; // instruction clock (FOSC/4)でTIMER1を使用、プリスケーラカウント値 1:8 T1GCON= 0b00000000; t1count = -15625; // タイマー1用カウントの初期値(15625カウントでオーバー) //t1count:15625の場合 割込間隔0.500sec = (1/1000000μs*4*8*15625) // (Fosc=1MHz Prescale=8 において) TMR1H = (t1count >> 8); // タイマーの初期化 TMR1L = (t1count & 0x00FF) ; // タイマーの初期化 TMR1IF = 0 ; // タイマー0割込フラグを0 count_for_trig = 0 ; // 割込み発生の回数カウンターを0 //LCD initialize and cleare // LCDのVDDをONする前は、LCDへのすべてのポートはlowであること。 lcd_vdd = 1; __delay_ms(30); //長めを設定 Lcd_init(); Lcd_clear(); Lcd_write(0b00001100); //Display on, no cursor, no blinking Lcd_goto(0x00); //LCDの表示位置を一行目左端 Lcd_puts("Ultra-sonic"); Lcd_goto(0x40); //LCDの表示位置を二行目左端 Lcd_puts(ver); //LCDにメッセージを表示 Lcd_puts(author); //LCDにメッセージを表示 timer = 3; while(timer--){__delay_ms(1000);}; //Wait Lcd_clear(); TMR1IE = 1 ; // タイマー1割込をマスクしない PEIE = 1 ; // 周辺割込みをマスクしない GIE = 1 ; // 全割込み処理をマスクしない Analize_distance(); }