電子工作に役立つ情報公開サイト |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
avr(arduino) pic python java engineering work | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
avr(arduino) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
IDE(Integrated Development Environment)統合開発環境の準備 ・IDEはインストーラータイプとそうでないものがあり、
インストーラータイプでないものを利用すれば異なるバージョンを共存させられる。(インストーラータイプは旧バージョンのアンインストールを求められる。)ファイルはarduinoのサイトからダウンロードできるが、上位互換ということでもないので必ずしも最新版にする必要はない。 スケッチの書き方(基本) (前置き) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void setup( ) { // put your setup code here, to run once: } void loop( ) { // put your main code here, to run repeatedly: } void function( ) { // put your function code here: } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
緊急地震速報のサンプルスケッチ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const byte soundpin = 10; void setup( ) { pinMode(soundpin,OUTPUT); } void loop( ) { com = 70; tone(soundpin,392,com); delay(com + 1); tone(soundpin,523,com); delay(com + 1); tone(soundpin,659,com); delay(com + 1); tone(soundpin,932,com); delay(com + 1); tone(soundpin,1244,com); delay(com + 100); tone(soundpin,415,com); delay(com + 1); tone(soundpin,554,com); delay(com + 1); tone(soundpin,698,com); delay(com + 1); tone(soundpin,987,com); delay(com + 1); tone(soundpin,1318,com); delay(com + 600); } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
シリアルモニタの活用 arduinoのIDEにはシリアルモニタやシリアル通信に必要な関数が標準で用意されていて、PCとarduinoの間で直ぐにシリアル通信ができるようになっている。そのためとりわけ表示器を設けなくてもプログラムの実行結果をシリアルモニタで確認したり、外部入力を設けなくてもシリアルモニタからarduinoにデータを送って指示を与えるといったことが簡単にできるようになっている。シリアルモニタはIDEの右上にある虫眼鏡のようなマークを押せば開く。(一部のarduinoを除き、シリアルモニタを開く度にプログラムがリセットされる)使う時には予め用意されている定型の関数をスケッチにも記述しておく必要がある。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
構文(syntax)等について(備忘録) ・条件分岐にはif文とswitch文があり何れもお互いに書き換え可能だが、一般に多分岐の場合はswitch文の方が処理速度が速いとされている。switch文はcaseの定数式の値がコンパイル時に確定していないとエラーになるので変数(#define等で定義された定数は使用可)は使えない。caseの評価はbreakしなければ一通り行われる。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
外部ライブラリのインクルード ダウンロード等したライブラリはメニューのスケッチにあるInclude Libraryでzip形式のものもそのまま取り込むことができる。 手動で行う場合はarduinoホームのlibraryフォルダに追加したいライブラリのフォルダ(圧縮でないもので、その直ぐ下の階層にヘッダファイル等があるもの。)を置く。 但し、手動の場合はIDEの再起動が必要。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
マイライブラリを作ろう よく使う定数等はヘッダファイル(.h)に定義しておくと便利。 作り方(概要) ・IDEの右上にある▼から新規タブを選び任意の名前と属性(.h又は.cpp)を付ける。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
サンプルライブラリ(配列の要素をシャッフル) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//ヘッダファイル #ifndef Array_Shuffle_H//必須 #define Array_Shuffle_H//必須 class Array_Shuffle{//クラス定義(オブジェクト定義)、クラス名=ライブラリ名 public: Array_Shuffle(void);//コンストラクタ定義、コンストラクタ=クラス名 void Act(uint8_t *Ary, uint8_t Elements, uint8_t Times, uint8_t UnusePin); //関数名定義 private: uint8_t i, y, j, t;//ソースファイルで使用するグローバル変数を定義(この場合はグローバルでなくてもよい) }; #endif//必須 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//ソースファイル #include "arduino.h"//標準関数等用 #include "Array_Shuffle.h" Array_Shuffle::Array_Shuffle(void) {//クラス名とコンストラクタ }//ヘッダファイルで定義した変数の初期化等は必要に応じてここで行う void Array_Shuffle::Act(uint8_t *Ary, uint8_t Elements, uint8_t Times, uint8_t UnusePin) {//関数の具体的な実行内容 randomSeed((analogRead(UnusePin) + analogRead(UnusePin)) / 2); //randomSeedの引数はunsigned int for ( y = 0; y < Times; y++) { for ( i = 0; i < Elements; i++) {//fisher yates shuffle algorism j = random(Elements); t = Ary[i]; Ary[i] = Ary[j]; Ary[j] = t; } } } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//使用例 Array_Shuffle AS; byte list[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; AS.Act(list, sizeof(list), 10, A5); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
上のソースファイルをヘッダファイルにまとめて書く場合 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//ヘッダファイル #ifndef Array_Shuffle_H//必須 #define Array_Shuffle_H//必須 class Array_Shuffle{//クラス定義(オブジェクト定義)、クラス名=ライブラリ名 public: Array_Shuffle(void){//コンストラクタ定義、コンストラクタ=クラス名 };//定義した変数の初期化等は必要に応じてここで行う void Act(uint8_t *Ary, uint8_t Elements, uint8_t Times, uint8_t UnusePin){ //関数名と実行内容定義 randomSeed((analogRead(UnusePin) + analogRead(UnusePin)) / 2); //randomSeedの引数はunsigned int for ( y = 0; y < Times; y++) { for ( i = 0; i < Elements; i++) {//fisher yates shuffle algorism j = random(Elements); t = Ary[i]; Ary[i] = Ary[j]; Ary[j] = t; } }; private: uint8_t i, y, j, t;//クラス内で使用するグローバル変数を定義 }; #endif//必須 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
※カッコ内の v o i d は省略可 ※スケッチはコピペすると全角スペースが入っているためエラーになる | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
定数等定義用サンプルヘッダファイル(.h) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#ifndef private_define_H
#define private_define_H typedef unsigned char uchar;//0~255 = byte = uint8_t typedef unsigned int uint;//0~65,535 = uint16_t typedef unsigned long ulong;//0~4,294,967,295 = uint32_t #define High (1) #define Low (0) #define Inv (2)//Invert #define On (1) #define Off (0) #define F5v10b (4.8875855)//float 5v/1023(10bit) #define F3v10b (3.2258064)//float 3.3v/1023(10bit) #define Pi (3.1415926)//float f(PI) = 3.14 #endif | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
サンプルキーワードファイル(keywords.txt) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private_define <Tab> KEYWORD1 Pi <Tab> KEYWORD2 00000000 <Tab> LITERAL1 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
IDEをカスタマイズしよう libフォルダにあるpreference.txtの各項目を編集することで、IDEの環境設定をより細かく設定できる。
例えば、起動時のエディタサイズ等を指定。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
カスタマイズしたIDE(起動時の初期画面) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
プリプロセッサ(コンパイラに対する命令)を使おう プリプロセッサにデバイス指定しておくとエラー防止になる。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
arduino uno 等のATmega328Pのチップを搭載の場合 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#ifndef __AVR_ATmega328P__//Preprocessor #error "Device Error"//エラーメッセージ #endif | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
デジタルポート(Read,Write)の高速化※アナログポートもデジタルポートとして使用可 プログラム内計測で標準関数を使用した場合が8uSの時、ポートレジスタを操作すると0uS。 これを関数化しても同等のパフォーマンスを得られる(0uS)が、ライブラリ化すると4uSに下がる。 但し、ヘッダファイルにまとめて書いた場合のライブラリ化は関数化と同等だと思われる。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
digitalWriteのFunction関数化サンプルスケッチ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//ATmega328~pinMode(#, OUTPUT) //digitalWrite(0 to 19) void port(byte p_num, byte sw) { if (p_num < 8){ if (sw == 1) {PORTD |= _BV(p_num);} if (sw == 0) {PORTD &= ~_BV(p_num);} }else if (p_num < 14){ if (sw == 1) {PORTB |= _BV(p_num - 8);} if (sw == 0) {PORTB &= ~_BV(p_num - 8);} }else if (p_num < 20){ if (sw == 1) {PORTC |= _BV(p_num - 14);} if (sw == 0) {PORTC &= ~_BV(p_num - 14);} }else{ return; } } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ポートレジスタ単位での一括操作のFunction関数化サンプルスケッチ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void multi_port(byte p_reg, byte sw, byte bin){ if (p_reg == 0){ if (sw == 1) {PORTD |= bin;}//sw(1)=on(only '1' bit turn on) if (sw == 0) {PORTD &= bin;}//sw(0)=off(exept '1(&1)' bit turn off) if (sw == 2) {PORTD ^= bin;}//sw(2)=invert(only '1' bit invert) }else if (p_reg == 1){ if (sw == 1) {PORTB |= bin;} if (sw == 0) {PORTB &= bin;} if (sw == 2) {PORTB ^= bin;} }else if (p_reg == 2){ if (sw == 1) {PORTC |= bin;} if (sw == 0) {PORTC &= bin;} if (sw == 2) {PORTC ^= bin;} }else{ return; } } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
digitalReadのFunction関数化サンプルスケッチ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//ATmega328~pinMode(#, INPUT) //digitalRead(0 to 19) byte d_read(byte p_num){ boolean state; if (p_num < 8){ state = PIND & _BV(p_num); }else if (p_num < 14){ state = PINB & _BV(p_num - 8); }else if (p_num < 20){ state = PINC & _BV(p_num - 14); }else{ return 0; } return state; } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//使用例 #include <private_define.h> multi_port(2, Inv, B00100000);//A5, HIGH multi_port(2, Inv, B00100000);//A5, LOW | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
外部割込みを使ってみよう arduinoには標準関数から利用できるINTピンとPCINTピンの2種類の外部割込みが設定されていて、ATmega328チップ等の場合は前者が2ピンで後者が23ピン(前者の2ピンはPCINTピンとしても機能)用意されている。INTピンは割り込みベクタ(要因番号)がそれぞれ独立していて、割り込みを生じさせるタイミングもそれぞれ4種類設定できるようになっている。PCINTピンは全てのI/Oピンと数は多いが割り込みベクタがI/Oポート単位になっていてタイミングもロジックレベルの変化時に限られている。割り込みハンドラーは割り込みベクタ単位での実行となる。 使用することはそうそう滅多にあるものではないが、PCINTを用いる場合で同一I/Oポートで複数ピンの割り込みを設定した時の判定方法のスケッチの一例 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include <avr/io.h>//IOライブラリのインクルード volatile byte PCI0FR = 0;//PCI1FR, PCI2FR | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void setup( ) { PCICR = (1 << PCIE0); PCMSK0 = 0x03;//PCINT0, PCINT1 sei( ); } ISR(PCINT0_vect){//PCINT1_vect, PCINT2_vect cli( ); PCI0FR = PCMSK0 & PINB;//Low to High PCI0FR = (PCMSK0 ^ PINB) & PCMSK0;//High to Low //Some Description sei( ); } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
これは単にフラグを立てるだけの記述なのでハンドラーのISR(InterruptServiceRoutine)内で処理を済ませる場合は処理方法は様々。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ソフトウェアでリセットが必要な場合(本来の使い方以外で)はwdtを利用しよう 例えば、wdtを条件分岐で真の時に有効、偽の時に無効にすれば任意のタイミングでリセットできる。※スリープ状態からの復帰にも利用可能。 ウォッチドッグタイマーに必要な記述 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include <avr/wdt.h>//ウォッチドッグタイマー用インクルード wdt_enable(WDTO_15MS);//有効 //WDTO_=15MS,30MS,60MS,120MS,250MS,500MS,1S,2S,4S,8S wdt_reset();//リセット wdt_disable();//無効 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PWM(Pulse Width Modulation)を使ってみよう arduinoで簡単にPWMを使うには | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
analogWrite(pin, value);//OFF:value = 0 又は digitalWrite(pin, LOW); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
という関数を利用する(利用できるIOピンがATmega328であれば3,5,6,9,10,11ピンと決まっている)方法がある。この関数は使い勝手はよいが周波数が固定(490Hz,一部のIOピンで980Hz)されているのでLEDの明るさを変えるといったデューティー比(0-255)を変化させるだけでよい場合に使える。この関数だけを使う場合はピンモードの初期設定は不要。反対にデューティーが50%の固定で周波数を自由に変えるには | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tone(pin, frequency, duration);//OFF:noTone(pin); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
という関数を利用するとよい。(こちらはピンモードの設定が必要)何れも変えたいという場合はレジスタを直接操作する必要がある。PWMのモードは4つあり、そのうちのPWM Phase and Frequency Correct Mode((Mode8 or Mode9)9pin,10pin)を使えば任意の周波数とデューティー比のPWM出力を得られる。PWMはモード等を設定すると、指定したピンから常時出力されているので、ON/OFFはデューティーの設定を変えることで行える。(指定ピンをPWMモード以外で使用する場合はTCCR1A = 0にしてPWMモードを解除する)周波数の計算は | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include<avr/io.h> void setup( ) { pinMode(pin, OUTPUT);//pinは 9 又は 10 TCCR1B = B00010010;//prescale * 8 ICR1 = 1912;//523Hz OCR1B = 956;//Duty50% TCCR1A = B00100000;//PFCPWM Non-Inverted } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PWMは設定と同時に出力されるので実際は関数化して必要な時に呼び出すなどした方が実用的。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tone関数とPWM Phase and Frequency Correct Mode(Mode8)を併用した和音の演奏 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PROGMEMを使ってみよう arduinoはATmega328であればデータメモリ用のRAMの容量が2Kバイトとそれ程大きくないなので、少し大きめの定数データ等を扱う場合はPROGMEMを使えばプログラムエリアに格納しておくことが可能で必要に応じてRAMに展開できる。データが文字列の場合は文字列を使用する際にF( )マクロを利用すれば簡単に同じ効果が得られる。PROGMEMの場合はライブラリー<avr/pgmspace.h>のインクルードが必要で、扱えるデータの型や読み込み方法が決まっているのでそれらに従って行う。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
EEPROMを使ってみよう arduinoにはプログラムを書き込むためのFlashROMとEEPROMという設定やデータを保存するための電源を切っても消えない不揮発性のROM(Read Only Memory)、データメモリ用の揮発性のRAM(Random Access Memory)が入っている。EEPROMを使うために標準で予め用意されている関数は | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
EEPROM.read(address); EEPROM.write(address, value); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
で、初期化メソッドはない。ROMのデータ保持期間は常温で100年、消去、書き込みの耐久性はFlashが1万回でEEPROMが10万回となっている。EEPROMへの書き込みは耐久性を考えると利用する場合は工夫した方がよい。決まった設定やデータ等はスケッチを変更したりプログラムが実行される度に書き込む必要はないので、EEPROMを書き込むためだけのスケッチを用意したり利用するプログラムを工夫しなければならない。EEPROMを初めて使う場合の簡単な工夫の例は | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if(EEPROM.read(0) == 0xFF){ EEPROM.write(address, value);//address(0 to 1023),value(0 to 255) 又は for(int i = 0; i < sizeof(value); i++){//Array EEPROM.write(i, value[i]); } } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
等。EEPROMの容量はATmega328であれば1kバイトなので、初期値はその全てに「1」が書き込まれていて、1バイト(8ビット)毎の仕切りなのでどのアドレスのデータも「FF」となっている。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
内蔵基準電圧を利用してみよう arduinoは電圧を計測するための標準電池のような参照用の基準電圧を内部に持っていて、analogRead関数を実行するとその基準電圧と比較した結果がデジタル値として得られるようになっている。基準電圧の参照はDEFAULTで電源電圧(AVCC(5V))となっているが、電源電圧は不安定なのでより高い精度で微小な電圧変化を計測するには信頼性のある外部電源を用意するか内蔵の基準電圧(ATmega328等は1.1V)を用いる。ADC(Analog-to-Digital Converter)の精度は10ビット(1024段階)で±2 LSB(最下位ビット)となっているので、基準となる電圧さえ安定した信頼できるものであれば高精度であることがわかる。基準電圧の選択は | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
analogReference(DEFAULT); analogReference(INTERNAL); analogReference(EXTERNAL); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
で行え、プログラム中で切り替えて使うこともできる。外部の基準電圧を参照するにはAREFに基準となる電圧を入力するようになっているが、ADCの入力範囲がVCCまでとなっているので超高精度の電源を利用するにしてもADCの温度補正のことも考慮すれば通常の使用に於いてはEXTERNALを利用するメリットは今のところあまり感じられない。analogReadで読み取った電圧値は | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
内蔵温度センサーを利用してみよう arduino(ATmega328)には実は温度センサーが内蔵されているのだが、普通の使い方では利用できない。チップの仕様書を見ると温度センサーはADCの温度補正のために内蔵されているようなのだがそれもどうやらそのままでは眠ったままのようだ。ADCはDIPタイプで6チャンネル、FPタイプで8チャンネル利用できることになっているが、実は9チャンネル目があって、それが温度センサー専用となっている。DIPタイプも温度センサーの値を読み取るのに9チャンネルにアクセスするということは7、8チャンネルも内部的には存在しているものと思われる。
9チャンネルにアクセスして温度センサーの値を読み取るには0x7C番地にあるADMUXと0x7A番地にあるADCSRAという2つのレジスタの操作が必要で、これはanalogRead()という標準関数を利用した時にも同じように操作されているらしいのだが、この関数では何故か扱えない仕様になっている。ADMUXのレジスタは参照する基準電圧と読み取るチャンネル指定の設定、ADCSRAのレジスタは読み取り変換開始の設定となっている。温度センサーは内蔵の1.1Vを基準電圧として計測され10ビットのデジタル値に変換される。仕様書には温度と温度センサーから出力される電圧の代表的な相関関係表があるがより精度を求めるならEEPROMなどに書き込まれているチップ毎のキャリブレーションをいじらなければならないようなのであまり参考にはならない。
1mV/℃という相関は概ね正しい。温度の計算は仕様書には | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ADMUX = 0xC8;//(REFS1,REFS0,MUX3 set) ADCSRA |= 0x40;//(ADSC set) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
と設定すれば、ADCHとADCLのレジスタに10bitのデジタル値が格納される。但し、内蔵温度センサーの測定範囲が判らないので、仕様書の相関関係表にある最低温度と最高温度を採用することにして、チップ毎に誤差があるにしてもその範囲のデジタル値はADCLの値だけで事足りるが、仕様書によれば、ADCLを読んだ場合は、ADCHが読まれるまでADCLが更新されないと書かれているので、ADCHも事務的に読む必要があり読む順序も自ずと決まってくる。ADCSRAレジスタのADSCビットは変換が完了すると自動でクリアされるので読み出したい時にセットすれば良い。温度の計算はチップ毎にオフセット等が異なるので参考までに示せば | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
byte Lbyte = ADCL; byte Hbyte = ADCH; T = map(Lbyte, 16, 146, -45, 85);//-45℃~85℃ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
で行える。但し、実装する場合は、初めて変換が行われる際にADCの初期化のために誤差がでるので数回ダミー計測するなどの工夫が必要なのと、計測にはそれなりに時間がかかることに注意。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ADCの9チャンネルにもアクセスできるanalogReadのFunction関数化サンプルスケッチ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//ATmega328 //analogRead(0 to 8) //ref(0=EXTERNAL, 1=DEFAULT, 3=INTERNAL) word a_read(byte p_num, byte ref){ byte state; if (p_num >= 0 && p_num < 9 && ref < 4 && ref != 2){ ADMUX = ((ref << 6) | p_num); ADCSRA |= 0x40; while (bit_is_set(ADCSRA, ADSC)); byte Lbyte = ADCL; byte Hbyte = ADCH; }else{ return (Hbyte << 8 | Lbyte); } return 0; } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
arduinoのライターシールドを作ろう arduinoのIDEにはATmega328P等の外部白チップにブートローダー等を書き込む機能がある。 配線数は多くないのでブレッドボード等を使っても良いが、繰り返し使いたい場合は専用シールドとして 製作しておいた方が良い。作り方を公開しているサイトもあるので製作手順はそちらを参照。 ゼロプレッシャーICソケットとフラットパッケージ用ソケット(TQFP32 to 28)を組み合わせればフラット パッケージチップへの書き込みもDIPタイプと同じようにできる。参考までに、クリスタルはクロック周波数を変えられるように、見づらいが画像にあるようにピンフレームなどを用いて固定しないように設計した方がよい。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
アセンブリ言語を使ってみよう 真に高速化が必要な場合はマシン語の一歩手前のアセンブリ言語をインラインで用いると良い。アセンブリはCPUの一挙手一投足の動作を記述しなければならないのでいわゆるarduino言語と比較すれば記述が非常に長くなり見た目では高速化を実感できないが、Arduinoなどのavrマイコンの場合は一つの命令を実行するのに必要なサイクル(1フェッチ)の殆どが1クロックとなっていてる(CPI=1と表す、picマイコンはCPI=4)ので相当な高速化が見込める。
アセンブリはマシン語を人間がより分かり易いようにニーモニックという命令を表す記号とその対象となるオペランドという被演算子(レジスタや即値等)を記述することになっている。また、インラインで記述する場合(arduinoIDEの場合はインラインのみ)は、経験的に、一関数内での記述に行数制限があるようだ。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
付録 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
モールス信号生成スケッチ(要圧電ブザー) コードの表示 Cdsセルを使ったLEDの自動調光スケッチ コードの表示 ① ② 回路図 ステッピングモーターのテスト調整用スケッチ コードの表示 ユニポーラ 和音スケッチ コードの表示 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
▲ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
※当サイトは手書きです。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||