●LEDを点滅させる

PICマイコンが違うと同じプログラムでも動作しないので、色々な種類のPICでLEDの点滅をしてみたいと思います。
まずは、PIC16シリーズの18ピンタイプをテストするためPIC16F84のピン配置を基準として共通回路を制作しました。
必然的にPIC16F84基準となるので、発信器は外部発信器の10MHz固定となります。(内部発信器は使いません)


各々のプログラムを書き込んで実際に動作させると、このように1秒毎に点滅します。



■ PIC16F84 でのLED点滅
▼アセンブラ
	LIST      P=16F84
	#include <p16F84.inc>

	__CONFIG _CP_OFF & _HS_OSC & _PWRTE_ON & _WDT_OFF


;---------------------------------------------------------------
;汎用レジスタに名前を付ける
;0x0C〜0x4F 68バイト
;---------------------------------------------------------------
;ウェイト用メモリ
	CBLOCK	0Ch
	wait_val1
	wait_val2
	wait_val3
	ENDC
		org	0
		goto	start

start
;---------------------------------------------------------------
;ポートの設定
;---------------------------------------------------------------
		banksel	PORTA		;疑似命令でPORTAの有るバンクに切り替え
		clrf	PORTA
		clrf	PORTB
		banksel TRISA		;疑似命令でTRISAの有るバンクに切り替え
		movlw	b'00000000
		movwf	TRISA		;portAを1:入力、0:出力 全てを出力に設定
		movlw	b'00000000
		movwf	TRISB		;portBを1:入力、0:出力 全てを出力に設定
		banksel	PORTA		;疑似命令でPORTAの有るバンクに切り替え
;---------------------------------------------------------------
main

		MOVLW	b'11111111
		MOVWF	PORTA		;WレジスタからFレジスタに代入
		MOVLW	b'11111111
		MOVWF	PORTB		;WレジスタからFレジスタに代入
		call wait_loop
		MOVLW	b'00000000
		MOVWF	PORTA		;WレジスタからFレジスタに代入
		MOVLW	b'00000000
		MOVWF	PORTB		;WレジスタからFレジスタに代入
		call wait_loop

		goto main

;---------------------------------------------------------------
;ウエイト
;---------------------------------------------------------------
wait_loop
		MOVLW	0xB6
		MOVWF	wait_val1
		MOVLW	0xAF
		MOVWF	wait_val2
		MOVLW	0xD
		MOVWF	wait_val3
wait_loop_1
		decfsz	wait_val1,F
		goto	wait_loop_1
		decfsz	wait_val2,F
		goto	wait_loop_1
		decfsz	wait_val3,F
		goto	wait_loop_1
		return

		END


▼ PIC16F84 で同様の動きをするc言語版(xc)
#include <stdio.h>
#include <stdlib.h>

#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (Power-up Timer is enabled)
#pragma config CP = OFF         // Code Protection bit (Code protection disabled)

#include <xc.h>
#define _XTAL_FREQ 10000000 //クロック周波数 __delay_ms()に必要

int main(int argc, char** argv) {
    TRISA = 0b00000000; //portAを1:入力、0:出力 全てを出力に設定
    TRISB = 0b00000000; //portBを1:入力、0:出力 全てを出力に設定

    while (1) { // 無限ループ
        PORTA = 0b00000000; //portAに出力
        PORTB = 0b00000000;
        __delay_ms(1000); // 1秒ウエイト
        PORTA = 0b11111111;
        PORTB = 0b11111111;
        __delay_ms(1000);
    }
    return (EXIT_SUCCESS);
}


■ PIC16F648A でのLED点滅
▼アセンブラ
	LIST      P=16F648A
	#include <p16F648a.inc>

	__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _BOREN_ON & _LVP_OFF & _CPD_OFF & _CP_OFF

;---------------------------------------------------------------
;汎用レジスタに名前を付ける
;0x20〜0x6F 80バイト
;---------------------------------------------------------------
;ウェイト用メモリ
	CBLOCK	20h
	wait_val1
	wait_val2
	wait_val3
	ENDC
		org	0
		goto	start

start
;---------------------------------------------------------------
;ポートの設定
;---------------------------------------------------------------
		banksel	PORTA		;疑似命令でPORTAの有るバンクに切り替え
		clrf	PORTA
		clrf	PORTB
		banksel TRISA		;疑似命令でTRISAの有るバンクに切り替え
		movlw	b'00000000
		movwf	TRISA		;portAを1:入力、0:出力 全てを出力に設定
		movlw	b'00000000
		movwf	TRISB		;portBを1:入力、0:出力 全てを出力に設定
		banksel	PORTA		;疑似命令でPORTAの有るバンクに切り替え
;---------------------------------------------------------------
main

		MOVLW	b'11111111
		MOVWF	PORTA		;WレジスタからFレジスタに代入
		MOVLW	b'11111111
		MOVWF	PORTB		;WレジスタからFレジスタに代入
		call wait_loop
		MOVLW	b'00000000
		MOVWF	PORTA		;WレジスタからFレジスタに代入
		MOVLW	b'00000000
		MOVWF	PORTB		;WレジスタからFレジスタに代入
		call wait_loop

		goto main

;---------------------------------------------------------------
;ウエイト
;---------------------------------------------------------------
wait_loop
		MOVLW	0xB6
		MOVWF	wait_val1
		MOVLW	0xAF
		MOVWF	wait_val2
		MOVLW	0xD
		MOVWF	wait_val3
wait_loop_1
		decfsz	wait_val1,F
		goto	wait_loop_1
		decfsz	wait_val2,F
		goto	wait_loop_1
		decfsz	wait_val3,F
		goto	wait_loop_1
		return

		END


▼ PIC16F648A で同様の動きをするc言語版(xc)
#include <stdio.h>
#include <stdlib.h>
// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#include <xc.h>
#define _XTAL_FREQ 10000000 //クロック周波数 __delay_ms()に必要

int main(int argc, char** argv) {
    TRISA = 0b00000000; //portAを1:入力、0:出力 全てを出力に設定
    TRISB = 0b00000000; //portBを1:入力、0:出力 全てを出力に設定

    while (1) { // 無限ループ
        PORTA = 0b00000000; //portAに出力
        PORTB = 0b00000000;
        __delay_ms(1000); // 1秒ウエイト
        PORTA = 0b11111111;
        PORTB = 0b11111111;
        __delay_ms(1000);
    }
    return (EXIT_SUCCESS);
}


■ PIC16F1827 でのLED点滅
▼アセンブラ
	LIST      P=16F1827
	#include <p16F1827.inc>

	__CONFIG _CONFIG1,_FOSC_HS & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
	__CONFIG _CONFIG2,_WRT_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_HI & _LVP_OFF

;---------------------------------------------------------------
;汎用レジスタに名前を付ける
;0x20〜0x6F 80バイト
;---------------------------------------------------------------
;ウェイト用メモリ
	CBLOCK	20h
	wait_val1
	wait_val2
	wait_val3
	ENDC
		org	0
		goto	start

start
;---------------------------------------------------------------
;ポートの設定
;---------------------------------------------------------------
		banksel	PORTA		;疑似命令でPORTAの有るバンクに切り替え
		clrf	PORTA
		clrf	PORTB
		banksel TRISA		;疑似命令でTRISAの有るバンクに切り替え
		movlw	b'00000000
		movwf	TRISA		;portAを1:入力、0:出力 全てを出力に設定
		movlw	b'00000000
		movwf	TRISB		;portBを1:入力、0:出力 全てを出力に設定
		banksel	PORTA		;疑似命令でPORTAの有るバンクに切り替え
;---------------------------------------------------------------
main

		MOVLW	b'11111111
		MOVWF	PORTA		;WレジスタからFレジスタに代入
		MOVLW	b'11111111
		MOVWF	PORTB		;WレジスタからFレジスタに代入
		call wait_loop
		MOVLW	b'00000000
		MOVWF	PORTA		;WレジスタからFレジスタに代入
		MOVLW	b'00000000
		MOVWF	PORTB		;WレジスタからFレジスタに代入
		call wait_loop

		goto main

;---------------------------------------------------------------
;ウエイト
;---------------------------------------------------------------
wait_loop
		MOVLW	0xB6
		MOVWF	wait_val1
		MOVLW	0xAF
		MOVWF	wait_val2
		MOVLW	0xD
		MOVWF	wait_val3
wait_loop_1
		decfsz	wait_val1,F
		goto	wait_loop_1
		decfsz	wait_val2,F
		goto	wait_loop_1
		decfsz	wait_val3,F
		goto	wait_loop_1
		return

		END


▼ PIC16F1827 で同様の動きをするc言語版(xc)
#include <stdio.h>
#include <stdlib.h>
// CONFIG1
#pragma config FOSC = HS        // Oscillator Selection (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = HI        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), high trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

#include <xc.h>
#define _XTAL_FREQ 10000000 //クロック周波数 __delay_ms()に必要

int main(int argc, char** argv) {
    TRISA = 0b00000000; //portAを1:入力、0:出力 全てを出力に設定
    TRISB = 0b00000000; //portBを1:入力、0:出力 全てを出力に設定

    while (1) { // 無限ループ
        PORTA = 0b00000000; //portAに出力
        PORTB = 0b00000000;
        __delay_ms(1000); // 1秒ウエイト
        PORTA = 0b11111111;
        PORTB = 0b11111111;
        __delay_ms(1000);
    }
    return (EXIT_SUCCESS);
}



PIC16F84のコードと比較して違う所を赤文字にしました。
違うのはconfigの部分での使用する回路の構成の設定部分と、メモリのアドレスぐらいでしょうか。
C言語の場合にはconfig以外ほとんど隠蔽されていて違いがありません。
こうやって見ると、1990年代前半のPIC16C84のような昔の基本となるPICに様々な回路を追加して作られていることがわかります。
ということは、基本となる部分を押さえて理解すれば、必要な回路の含まれたPICを選択して、周辺機器や追加された回路について調べて プログラミングするだけで自分の好きな動きをさせる事ができるんじゃないかと思いました。

ちなみに、今回使ったフラッシュメモリ版のPIC16F84は1999年頃からの製品で、PIC16F1シリーズは2010年頃からの製品のようです。


■8ピンPIC

次に、8ピンPICでもLEDの点滅をしてみたいと思います。
そこで、次のような回路を考えました。


18ピンのソケットを流用し、差す場所によりPICを切り替える事にしました、 赤枠がPIC12F1822青枠がPIC10F222を想定しています。
各々のプログラムを書き込んで実際に動作させると、このように1秒毎に点滅します。



■ PIC12F1822 でのLED点滅


PIC12F1822のピンを簡易的に書くとこのようになり、回路の赤枠にPICをセットすれば電源が供給されて各出力ピンにLEDが接続されます。
以下のアセンブラをPICに書き込むとLEDが点滅します。

	LIST      P=12F1822
	#include <p12F1822.inc>

	__CONFIG _CONFIG1,_FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
	__CONFIG _CONFIG2,_WRT_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_HI & _LVP_OFF

;---------------------------------------------------------------
;汎用レジスタに名前を付ける
;0x20〜0x6F 80バイト
;---------------------------------------------------------------
;ウェイト用メモリ
	CBLOCK	20h
	wait_val1
	wait_val2
	wait_val3
	ENDC
		org	0
		goto	start

start
;---------------------------------------------------------------
;ポートの設定
;---------------------------------------------------------------
		banksel	OSCCON		;疑似命令でOSCCONの有るバンクに切り替え
					;内部オシレータを16MHzに設定
		movlw	b'01111010
		movwf	OSCCON
		banksel	ANSELA		;疑似命令でANSELAの有るバンクに切り替え
					;アナログ チャンネルをデジタル入力に切り替えるがデジタル出力機能には影響ない
		movlw	b'00000000
		movwf	ANSELA

		banksel	PORTA		;疑似命令でPORTAの有るバンクに切り替え
		clrf	PORTA

		banksel TRISA		;疑似命令でTRISAの有るバンクに切り替え
		movlw	b'00000000
		movwf	TRISA		;portAを1:入力、0:出力 全てを出力に設定

		banksel	PORTA		;疑似命令でPORTAの有るバンクに切り替え
;---------------------------------------------------------------
main

		MOVLW	b'11111111
		MOVWF	PORTA		;WレジスタからFレジスタに代入
		;WレジスタからFレジスタに代入
		call wait_loop
		MOVLW	b'00000000
		MOVWF	PORTA		;WレジスタからFレジスタに代入
		;WレジスタからFレジスタに代入
		call wait_loop

		goto main

;---------------------------------------------------------------
;ウエイト
;---------------------------------------------------------------
wait_loop
		MOVLW	0xB6
		MOVWF	wait_val1
		MOVLW	0xAF
		MOVWF	wait_val2
		MOVLW	0x15
		MOVWF	wait_val3
wait_loop_1
		decfsz	wait_val1,F
		goto	wait_loop_1
		decfsz	wait_val2,F
		goto	wait_loop_1
		decfsz	wait_val3,F
		goto	wait_loop_1
		return

		END


▼ PIC12F1822 で同様の動きをするc言語版(xc)
#include <stdio.h>
#include <stdlib.h>
// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = HI        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), high trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

#include <xc.h>
#define _XTAL_FREQ 16000000 //クロック周波数 __delay_ms()に必要

int main(int argc, char** argv) {
    OSCCON = 0b01111010;
    ANSELA = 0b00000000;
    PORTA = 0b00000000;
    TRISA = 0b00000000; //portAを1:入力、0:出力 全てを出力に設定

    while (1) { // 無限ループ
        PORTA = 0b00000000; //portAに出力
        __delay_ms(1000); // 1秒ウエイト
        PORTA = 0b00110111;
        __delay_ms(1000);
    }
    return (EXIT_SUCCESS);
}


■ PIC10F222 でのLED点滅


PIC10F222のピンを簡易的に書くとこのようになり、回路の青枠にPICをセットすれば電源が供給されて各出力ピンにLEDが接続されます。
しかし、GP3は入力のみのため、LEDを光らせる事はできません。 以下のプログラムをPICに書き込むと GP0 GP1 GP2に接続された3つのLEDが点滅します。
▼アセンブラ
	LIST      P=10F222
	#include <p10F222.inc>

	__CONFIG _IOSCFS_8MHZ & _MCPU_OFF & _WDT_OFF & _CP_OFF & _MCLRE_OFF

;---------------------------------------------------------------
;汎用レジスタに名前を付ける
;0x09〜0x1F 23バイト
;---------------------------------------------------------------
;ウェイト用メモリ
	CBLOCK	09h
	wait_val1
	wait_val2
	wait_val3
	ENDC
		org	0
		goto	start

start
;---------------------------------------------------------------
;ポートの設定
;---------------------------------------------------------------
		;GP2/T0CKIを使用、発信器校正を中心値に設定
		MOVLW	b'00000000
		MOVWF	OSCCAL
		;ウエイクアップOFF 弱プルアップOFF T0CKI無効
		MOVLW	B'11000000'
		OPTION
		;GP0 GP1をデジタルIOとする
		MOVLW	b'00001100'
		MOVWF	ADCON0
		;ピンを全て出力にする
		MOVLW	b'00000000
		TRIS	GPIO
;---------------------------------------------------------------
main
		MOVLW	b'00000111
		MOVWF	GPIO		;WレジスタからFレジスタに代入
		;WレジスタからFレジスタに代入
		call wait_loop
		MOVLW	b'00000000
		MOVWF	GPIO		;WレジスタからFレジスタに代入
		;WレジスタからFレジスタに代入
		call wait_loop

		goto main

;---------------------------------------------------------------
;ウエイト
;---------------------------------------------------------------
wait_loop
		MOVLW	0xB6
		MOVWF	wait_val1
		MOVLW	0xAF
		MOVWF	wait_val2
		MOVLW	0x0A
		MOVWF	wait_val3
wait_loop_1
		decfsz	wait_val1,F
		goto	wait_loop_1
		decfsz	wait_val2,F
		goto	wait_loop_1
		decfsz	wait_val3,F
		goto	wait_loop_1
		return

		END


▼ PIC10F222 で同様の動きをするc言語版(xc)
#include <stdio.h>
#include <stdlib.h>

#pragma config IOSCFS = 8MHZ    // Internal Oscillator Frequency Select bit (8 MHz)
#pragma config MCPU = OFF        // Master Clear Pull-up Enable bit (Pull-up enabled)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config CP = OFF         // Code protection bit (Code protection off)
#pragma config MCLRE = OFF      // GP3/MCLR Pin Function Select bit (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)

#include <xc.h>
#define _XTAL_FREQ 8000000 //クロック周波数 __delay_ms()に必要

int main(int argc, char** argv) {
    OSCCAL = 0b00000000;
    OPTION = 0B11000000;
    ADCON0 = 0B00001100;
    TRISGPIO = 0b00000000;
    while (1) {
        GPIO = 0b00000000; //GPIOに出力
        __delay_ms(1000); // 1秒ウエイト
       GPIO = 0b00000111;
        __delay_ms(1000);
    }
    return (EXIT_SUCCESS);
}



アセンブラでゴリゴリ書くよりも、C言語の力を使ったほうが圧倒的に楽でした。
やはり時代は抽象化レベルが高い言語に向かうのでしょうかね。


▲トップページ > マイコンなど