・プログラムを組む前に
・Let's プログラム
C言語で開発するので、当然C言語を知らなきゃ開発できませぬ。一度に説明するのは面倒なので、必要に応じて説明していきます。
基本の形
#include <P16F873.h> #include <Datalib.h> #include <Delays.h> void main (void) { } |
取りあえずこの形を作ってください。
#include〜となっているのは、おまじないみたいなもんで必須。良く使う機能(ヘッダーファイルにて記述)を読み込む為のものです。特に<P16F873.h>ってやつは、使うPICの仕様書みたいなもんです。当然、使うPICによってこの部分は変えなきゃいけないですが、良く使う873で話を進めていきます。
肝心のプログラムは、
void main (void) { } |
の{ }内に書いてください。
さて、書いてくださいと言われて当然書けるわけも無く、そもそもPICっちゃ何?って感じです。PICとは000回で説明したマイコンの1種であり、用途によって様々な種類があります。今回使用するPic16F873もその中の一つです。そして、その16F873の構造は以下のようになっています。
PIC16F873 | ||||||
MCLR/Vpp/THV | -| | 1 | ∪ | 28 | |- | RB7/PGD |
RA0/AN0 | -| | 2 | 27 | |- | RB6/PGC | |
RA1/AN1 | -| | 3 | 26 | |- | RB5 | |
RA2/AN2/Vref- | -| | 4 | 25 | |- | RB4 | |
RA3/AN3/Vref+ | -| | 5 | 24 | |- | RB3/PGM | |
RA4/T0CKI | -| | 6 | 23 | |- | RB2 | |
RA5/AN4/SS | -| | 7 | 22 | |- | RB1 | |
Vss | -| | 8 | 21 | |- | RB0/INT | |
OSC1/CLKIN | -| | 9 | 20 | |- | Vdd | |
OSC2/CLKOUT | -| | 10 | 19 | |- | Vss | |
RC0/T1OSO/T1CKI | -| | 11 | 18 | |- | RC7/RX/DT | |
RC1/T1OSI/CCP2 | -| | 12 | 17 | |- | RC6/TX/CK | |
RC2/CCP1 | -| | 13 | 16 | |- | RC5/SDO | |
RC3/SCK/SCL | -| | 14 | 15 | |- | RC4/SDI/SDA | |
まぁ、いきなりこんなのを見せられても何?って感じですね。
まず、必要な部分から見てみましょう。
-基本設定-
1、20番ピン(Vpp、Vdd):電源(5V)と繋ぐ
8、19番ピン(Vss):アースへ繋ぐ
9、10番ピン(CLKIN、CLKOUT):発振子と繋ぐ
取りあえず以上が、PICを動かすのに必要最低限な装備です。ブレッドボード上で配線してみましょう。
さて、PICを動かすにあたって、取りあえず何らかの信号(出力)を出したい。そんな時に使用するのがI/Oポートである。
873においてRA0〜RA5(2〜7番ピン)、RB0〜RB7(21〜28番ピン)、RC0〜RC7(11〜18番ピン)が入出力に使用できる。ぶっちゃけ、さっき使った基本設定以外の部分は全て入出力ポートとして使うことが出来ます。ただし、2番ピンのように「RA0/AN0」と/で分けられているものは、複数の機能を持っており、どの機能を使うかはまた別途設定します。
見て分かるように、RA、RCポートは他の機能を持っているのが多いので、基本的にRBポートから使っていきます。
・取りあえず設定を
そういや、どんなプログラムにするか決めてなかったな(ヲイ
一番最初って事で、取りあえずLEDを光らせてみよう。使うポートは、RB5(26番ピン)にでもしておこうか。
そこでまず必要になるのが、ポートの設定と呼ばれる作業。各ポートは入力、出力どちらにでも使用できるため、どっちで使用するかということを決めてやらなくてはいけない。よって、以下のように記述する。
void main (void) { PORTB=0xFF; //PORTBを使用するという宣言 TRISB=0x00; //PORTBを出力端子として使用するという宣言 PORTB=0x00; //PORTBの初期出力が0であるという宣言 } |
さて、ここでまた意味不明の記述である。
〜1行目〜
PORTB=0xFF;
順を追って説明するならまずは=について。
通常数学の数式において=とは左右が等しいということを表すのだが、C言語の「=」は=の右側の値を左側へ与えるといった意味を持つ。(因みに「==」という表記で数学上の「=」と等価な意味を持つ)つまり、PORTBの状態を0xFFにするという命令が一番最初の行に書かれている。それでは0xFFとは何だろうか?
0xと頭に付ける事によって、16進数表記で表すことを意味して、FFを2進数で表すと「1111
1111」となる。
10進 | 16進 | 2進 | 10進 | 16進 | 2進 | 10進 | 16進 | 2進 | 10進 | 16進 | 2進 | |||
0 | 0 | 0000 | 4 | 4 | 0100 | 8 | 8 | 1000 | 12 | C | 1100 | |||
1 | 1 | 0001 | 5 | 5 | 0101 | 9 | 9 | 1001 | 13 | D | 1101 | |||
2 | 2 | 0010 | 6 | 6 | 0110 | 10 | A | 1010 | 14 | E | 1110 | |||
3 | 3 | 0011 | 7 | 7 | 0111 | 11 | B | 1011 | 15 | F | 1111 |
まぁ、上の表のようになっている訳である。
一体全体これが何を意味するのか?先ほども書いたように「FF」(16)=「1111 1111」(2)であり、8桁である。因みにPORTBはRB0〜RB7までの8ヶである。こじ付け感があるが、2進数時の1ビットそれぞれがRB0〜7に対応している。言葉で言っても分かりにくいので、図で見てみる。
PORTB=0xA9 | |||||||
A | 9 | ||||||
1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 |
とまぁ、こんな感じになる。1が使用する、0が使用しないという命令であり
この場合、RB7、5、3、1番ピンを使用するという命令になる。
プログラムの0xFFだと全て1となるので、PORTB全てを使用するって意味である。
〜2行目〜
TRISB=0x00
これはPORTBを入力にするか出力にするかを決める命令である。先ほどと同様に、2進数時の1ビットそれぞれがRB0〜7に対応している。
そして、この設定において0だと出力を意味し、1だと入力を意味する。
〜3行目〜
PORTB=0x00;
まぁ、ぶっちゃけ無くてもOK
出力に指定したPORTBの初期出力が0って言うことを表してる。
設定しない場合、0が出力される筈なので問題無いのだが、気分の問題である。
・出力させるべし!!
まぁ、ここまでやれば後は簡単♪あと1行足すだけで終わる。
void main (void) { PORTB=0xFF; //PORTBを使用するという宣言 TRISB=0x00; //PORTBを出力端子として使用するという宣言 PORTB=0x00; //PORTBの初期出力が0であるという宣言 PORTB|=0x20; //RB5から出力 } |
以上である。
と、今度は「|=」とかいうまたしても分からない記号が出てきた。今度はこれについて説明する。
まぁ、正直に言うならわざわざ「|=」と書かなくても「=」で事足りる。けれども、後々の事を考え、「|=」に慣れておくべきである。
「|=」とは、ディジタルでいうところのORにあたる。さて、ORとは何ぞや?
口で説明するのも面倒なので、表にて表す。因みに、式で書くと「OR」=「+」である
A | B | A+B |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
X | 0 | X |
X | 1 | 1 |
(Xは未知数)
と、こんな感じの演算である。(説明するまでもないかな〜
よって、「PORTB|=0x20」という操作は以下の通りである。
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 | ||
足す値 PORTB|=0x20 |
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 | ||
最終値 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 |
となる。因みに初期値が0x00の場合「PORTB=0x20」とやっても同じ結果となる。
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 | ||
足す値 PORTB=0x20 |
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 | ||
最終値 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 |
この二つの操作の違いを表すとしたら
初期値 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 | ||
最終値 PORTB|=0x20ver. |
1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 | ||
最終値 PORTB=0x20 ver. |
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | |
RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 |
であり、一目瞭然である。「|=」は初期値に値を加える操作であり、「=」は新しい値を代入するのである。
・まとめ
ちょっと道が逸れてしまったけれど、最終的には以下のようなプログラムを組めばOKである。
#include <P16F873.h> #include <Datalib.h> #include <Delays.h> void main (void) { PORTB=0xFF; //PORTBを使用するという宣言 TRISB=0x00; //PORTBを出力端子として使用するという宣言 PORTB=0x00; //PORTBの初期出力が0であるという宣言 PORTB|=0x20; //RB5から出力 } |
取り合えず、基礎中の基礎のプログラムはこんな感じ。次はこれをコンパイルしよう!
[戻る]