この広告は30日以上更新がないブログに表示されております。
新規記事の投稿を行うことで、非表示にすることが可能です。
広告
posted by fanblog
2018年12月18日
Visual Studio 2017 Communityで、書籍「Visual C++?@はじめてのWindowsプログラミング」のサンプルプログラムの動作を確認する 第3章
第3章は、サンプルが2つあります。2つとも無修正で動作しました。
注1:.NETのプラグラミングではありません。XXX.DLLが無いとかどうとか云うエラーに悩まされる方のプログラミングです。
注2:使用しているVSは、
Microsoft Visual Studio Community 2017
Version 15.9.3
VisualStudio.15.Release/15.9.3+28307.145
インストールされているバージョン:Community
Visual C++ 2017 00369-60000-00001-AA914
Microsoft Visual C++ 2017
注3:VC++、Windows 32 API用、空のプロジェクトの作成方法については、 https://fanblogs.jp/papas56/archive/53/0 を参考にしてください。
注4:VC++、Windows 32 API用、空のプロジェクトにソースファイルを追加する方法は、 https://fanblogs.jp/papas56/archive/54/0 を参考にしてください。
注1:.NETのプラグラミングではありません。XXX.DLLが無いとかどうとか云うエラーに悩まされる方のプログラミングです。
注2:使用しているVSは、
Microsoft Visual Studio Community 2017
Version 15.9.3
VisualStudio.15.Release/15.9.3+28307.145
インストールされているバージョン:Community
Visual C++ 2017 00369-60000-00001-AA914
Microsoft Visual C++ 2017
注3:VC++、Windows 32 API用、空のプロジェクトの作成方法については、 https://fanblogs.jp/papas56/archive/53/0 を参考にしてください。
注4:VC++、Windows 32 API用、空のプロジェクトにソースファイルを追加する方法は、 https://fanblogs.jp/papas56/archive/54/0 を参考にしてください。
2018年12月13日
Visual Studio 2017 Communityで、書籍「Visual C++?@はじめてのWindowsプログラミング」のサンプルプログラムの動作を確認する 第1章と第2章
(今更ですが)ここは書籍「Visual C++?@はじめてのWindowsプログラミング」(著者:山本信雄 出版:翔泳社)のサンプルプログラムについての動作確認記録です。この書籍は、開発環境として、Visual C++ 6.0 を使用して書かれていますが、2018年12月現在、Visual Studio 2017 Community VC++ でサンプルプログラムが動作するのかどうかを調べました。もし動作すれば、無料で高機能の開発環境を使用できるということになり、いい時代になったねというべきでしょうか。
結果:1章のサンプルプログラムと2章のサンプルプログラムは無修正で動作しました。(3章以降は適宜UPします。)
注1:.NETのプラグラミングではありません。XXX.DLLが無いとかどうとか云うエラーに悩まされる方のプログラミングです。
注2:使用しているVSは、
Microsoft Visual Studio Community 2017
Version 15.9.3
VisualStudio.15.Release/15.9.3+28307.145
インストールされているバージョン:Community
Visual C++ 2017 00369-60000-00001-AA914
Microsoft Visual C++ 2017
注3:VC++、Windows 32 API用、空のプロジェクトの作成方法については、 https://fanblogs.jp/papas56/archive/53/0 を参考にしてください。
注4:VC++、Windows 32 API用、空のプロジェクトにソースファイルを追加する方法は、 https://fanblogs.jp/papas56/archive/54/0 を参考にしてください。
結果:1章のサンプルプログラムと2章のサンプルプログラムは無修正で動作しました。(3章以降は適宜UPします。)
注1:.NETのプラグラミングではありません。XXX.DLLが無いとかどうとか云うエラーに悩まされる方のプログラミングです。
注2:使用しているVSは、
Microsoft Visual Studio Community 2017
Version 15.9.3
VisualStudio.15.Release/15.9.3+28307.145
インストールされているバージョン:Community
Visual C++ 2017 00369-60000-00001-AA914
Microsoft Visual C++ 2017
注3:VC++、Windows 32 API用、空のプロジェクトの作成方法については、 https://fanblogs.jp/papas56/archive/53/0 を参考にしてください。
注4:VC++、Windows 32 API用、空のプロジェクトにソースファイルを追加する方法は、 https://fanblogs.jp/papas56/archive/54/0 を参考にしてください。
2018年12月12日
Visual Studio 2017 Community で、VC++ Win32APIプログラミング 空のプロジェクトの作り方
Visual Studio 2017 Community のVC++を使って、Windows32 API プログラミングの勉強を始めたところです。参考書は、「プログラミング学習シリーズ Visual C++?@ はじめてのWindowsプログラミング」(絶版)です。古本で買いました。この本は、VC++ Ver.6.0をベースに記述されているので、現在の Visual Studio 2017 Community とはずいぶん操作方法が違いますが、プログラミングの基本は何も変化がなくソースプログラムは無修正で動作するようです。(まだ2章までしか確認しておりません。)VS2017を触るのもの初めて、C++も初めて、しかも本はVC++Ver.6.0(約20年前でしょうか)なので、空のプロジェクトの作成法を備忘録として記しておきます。
VC++ Windowsデスクトッププログラムを勉強するために、MFCは使わずWindows32 APIのみでアプリケーションを作成するときに、元になる空のプロジェクトが必要になります。(空のプロジェクトにソースファイルを追加する方法は、 https://fanblogs.jp/papas56/archive/54/0 を参考にしてください。)
1.Visual Studio 2017 Community(以後、VS2017と呼びます)をインストールしてください。
2.VS2017を立ち上げてください。
3.新規プロジェクトの作成をクリックしてください。
4.下記のダイアログボックスが出ます。
ここで、左側の「Visual C++」をクリックすると、「その他」が表示されます。「その他」をクリックすると、「空のプロジェクト」が表示されますので、「 空のプロジェクト」をクリックします。
プロジェクトに名前をつけます。名前はデフォルトでは「Project1」になっていますので、適当に変更してください。また、保存場所も自分の予定している場所に変更してください。以上の準備が出来ましたら。
右下の「OK」ボタンをクリックしてください。
【注意】
もし、「その他」のところに「空のプロジェクト」が表示されない場合はコンポーネントが不足しています。
青枠の中の、「Visual Studio インストーラーを開く」をクリックして足りないコンポーネントを追加してください。
VC++ Windowsデスクトッププログラムを勉強するために、MFCは使わずWindows32 APIのみでアプリケーションを作成するときに、元になる空のプロジェクトが必要になります。(空のプロジェクトにソースファイルを追加する方法は、 https://fanblogs.jp/papas56/archive/54/0 を参考にしてください。)
1.Visual Studio 2017 Community(以後、VS2017と呼びます)をインストールしてください。
2.VS2017を立ち上げてください。
3.新規プロジェクトの作成をクリックしてください。
4.下記のダイアログボックスが出ます。
ここで、左側の「Visual C++」をクリックすると、「その他」が表示されます。「その他」をクリックすると、「空のプロジェクト」が表示されますので、「 空のプロジェクト」をクリックします。
プロジェクトに名前をつけます。名前はデフォルトでは「Project1」になっていますので、適当に変更してください。また、保存場所も自分の予定している場所に変更してください。以上の準備が出来ましたら。
右下の「OK」ボタンをクリックしてください。
【注意】
もし、「その他」のところに「空のプロジェクト」が表示されない場合はコンポーネントが不足しています。
青枠の中の、「Visual Studio インストーラーを開く」をクリックして足りないコンポーネントを追加してください。
2016年06月19日
実践! ターゲットのソースにデバッグ関数を埋め込んでみたがRAM不足でコンパイルエラーとなった
実際にターゲットのソースファイルにデバッグ関数を埋め込んでみました。残念ながらRAM不足になりコンパイルできませんでした。デバッグ関数の呼び出し箇所をうんと減らす必要がありますね。残念。
Arduino:1.6.10 Hourly Build 2016/05/31 11:33 (Windows 10), ボード:"Arduino/Genuino Uno"
最大32,256バイトのフラッシュメモリのうち、スケッチが8,390バイト(26%)を使っています。
最大2,048バイトのRAMのうち、グローバル変数が2,473バイト(120%)を使っていて、ローカル変数で-425バイト使うことができます。
processing.app.debug.RunnerException: スケッチが使用するメモリが足りません。メモリを節約する方法については、以下のURLのページを参照してください。 http://www.arduino.cc/en/Guide/Troubleshooting#size
at cc.arduino.Compiler.size(Compiler.java:319)
at cc.arduino.Compiler.build(Compiler.java:156)
at processing.app.Sketch.build(Sketch.java:1111)
at processing.app.Sketch.build(Sketch.java:1081)
at processing.app.Editor$BuildHandler.run(Editor.java:1988)
at java.lang.Thread.run(Thread.java:745)
スケッチが使用するメモリが足りません。メモリを節約する方法については、以下のURLのページを参照してください。 http://www.arduino.cc/en/Guide/Troubleshooting#size
「ファイル」メニューの「環境設定」から
「より詳細な情報を表示する:コンパイル」を有効にすると
より詳しい情報が表示されます。
Arduino:1.6.10 Hourly Build 2016/05/31 11:33 (Windows 10), ボード:"Arduino/Genuino Uno"
最大32,256バイトのフラッシュメモリのうち、スケッチが8,390バイト(26%)を使っています。
最大2,048バイトのRAMのうち、グローバル変数が2,473バイト(120%)を使っていて、ローカル変数で-425バイト使うことができます。
processing.app.debug.RunnerException: スケッチが使用するメモリが足りません。メモリを節約する方法については、以下のURLのページを参照してください。 http://www.arduino.cc/en/Guide/Troubleshooting#size
at cc.arduino.Compiler.size(Compiler.java:319)
at cc.arduino.Compiler.build(Compiler.java:156)
at processing.app.Sketch.build(Sketch.java:1111)
at processing.app.Sketch.build(Sketch.java:1081)
at processing.app.Editor$BuildHandler.run(Editor.java:1988)
at java.lang.Thread.run(Thread.java:745)
スケッチが使用するメモリが足りません。メモリを節約する方法については、以下のURLのページを参照してください。 http://www.arduino.cc/en/Guide/Troubleshooting#size
「ファイル」メニューの「環境設定」から
「より詳細な情報を表示する:コンパイル」を有効にすると
より詳しい情報が表示されます。
2016年06月11日
Arduino IDE 環境にて、UncompatinoへI2C接続してデバッグする
UncompatinoにはUSB端子がありますが、これをデバッグ用にしてしまうと、USBを使うアプリはデバッグできません。そこで、デバッグの情報はI2Cでやり取りし、USBはアプリ側で使用できるようにしました。でも、無いよりはマシですが、物凄く便利というわけのものでもありません。その辺りをよく理解した上でもしご興味があればどうぞ試してみてください。
Arduino IDE を使用しますので、Uncompatinoともう一つのUNO互換機はPCとUSBで接続されます。Uncompatino側のUSBは、アプリが動き始めるとアプリが使用することになります。UNO互換機側のUSBは、I2C経由でUncompatinoから受け取ったデバッグ情報をPCに出力します。
デバッガー用にUNO互換機を買うつもりなら、Uncompatinoをお勧めします。Uncompatinoは、ISPライターの機能もあるので、これ1台でUncompatino上のATmega328Pにヒューズバイトとブートローダー、EEPROMを書くことができます。USB-シリアル変換ICのFTDI製FT232RLの機能です。写真の四角で囲ったISPのところがそうです。
I2Cの配線もA4、A5ピンをそれぞれ接続するだけです。ブレッドボードの一番右にはブレークポイントを抜けるためのstartButtonを配置しました。
You can write keywords is 234
TWBR is 0x48
TWSR is 0xF8
You can write keywords is 235
TWBR is 0x48
TWSR is 0xF8
You can write keywords is 236
TWBR is 0x48
TWSR is 0xF8
You can write keywords is 237
TWBR is 0x48
TWSR is 0xF8
私の環境では、ターゲット側のMaster-Writer2はCOM7をシリアルポートに指定しました。デバッガー側は、Arduino IDEをもう一つ起動して、COM8をシリアルポートに指定しました。くどいようですが、Arduino IDEを2つ起動するということは、Arduino IDEのスケッチを2つ開くということとは違います。お間違えのないようにご注意ください。Arduino IDEを2つ起動して初めて、別々のCOMをそれぞれ選べるようになります。Arduino IDEでソースコードを表示したら、COMポートを選択して、シリアルモニターを開いてください。ターゲット側とデバッガー側でそれぞれ別のCOMポートを選択できたかは、ウィンドウの下部にCOM番号が表示されますのでそれでも確認できます。
1.関数名などの文字列と、何番目のブレークポイントなのかを示す通し番号の2つを表示させる。
実装したものが下記となります。シリアル番号の表現としてint型で宣言して上位バイトと下位バイトに分離してバイト表現するやり方もあると思います。ここではbyte型のものを受信側(デバッガー側)でint型に合成することにしました。
Wire.beginTransmissionから始まってWire.write、Wire.endTransmissionで終わる一連の動作が一つのI2Cシーケンスとなります。
void debugPrint(char thisStr[]) { ← thisStr[]が任意の文字列となります。
Wire.beginTransmission(8); // transmit to device #8
Wire.write(thisStr); // sends charcters ← 文字列を送ります。
Wire.write(x[0]); // sends one byte ← シリアル番号の下位バイトを送ります。
Wire.write(x[1]); // sends one byte ← シリアル番号の上位バイトを送ります。
Wire.endTransmission(); // stop transmitting
if (x[0] == 255){
x[1]++; ← シリアル番号の更新です。
}
x[0]++; ← シリアル番号の更新です。
}
2.レジスター名とその内容(HEX形式)を表示させる。
実装したものが下記となります。
(レジスターによっては2バイト返すものがあるらしいのですが勉強不足で未対応です。そのうちに改良します。)
void debugRegPrint(char thisStr[], byte regValue) { ← レジスター名、その内容(1バイト)の順です。
Wire.beginTransmission(8); // transmit to device #8
Wire.write(thisStr); // sends charcters ← レジスター名の送信
Wire.write(regValue); // sends one byte ← レジスターの内容の送信 Arduino IDE では変数としてレジスタ名を書くだけでレジスタの内容が表示される仕様となっています。便利と言えばかなりお手軽な使い勝手です。これは、wire.hをインクルードしたので、幾重にもネストされたどこかのヘッダーファイルにマクロ定義がされているものと思います。そこまで調べて突き止める気力がありませんでした。
Wire.write(0); // dummy byte(debugPrintと揃える為) ← ダミーバイトの送信
Wire.endTransmission(); // stop transmitting
}
3.スタートボタンを押したらブレークポイントから抜けることができる。
実装したものが下記となります。
void breakPoint(void) { ← 引数も戻り値もありません。
while (1) { ← 無限ループです。
if (digitalRead(startButton) == LOW) { ← スタートボタンを押すとLOWになります。
delay(500);//wait a finger to take off ← 500ms待つのは、ボタンを押してから離すまでの時間です。ボタンを押してから離すまでは500ms以内に行わないと次のブレークポイントもすり抜けることになりますので注意してください。逆に長押しするということは、ブレークポイントを複数個所スルーできるので、適宜使い分けると便利かも。
break;//when the startButton got pushed ← 無限ループを抜けます。
}
}
}
4.上記1と2で送られたデータを解析して表示する。
実装したものが下記となります。
I2Cシーケンスが始まると割り込みが発生します。割り込みを処理する関数を割り込みハンドラーと呼びます。
void receiveEvent(int howMany) { ← 割り込みハンドラーです
while (2 < Wire.available()) { // loop through all but the last ← 受信したデータが最後の2バイトになるまでループします。
c = Wire.read(); // receive byte as a character ← 1バイトずつ文字として読みます。
if (c == '*'){ ← 読んだ文字が*なら、ここで打ち切りします。
break;
}
Serial.print(c); // print the character ← USB経由で1文字ずつPCに表示させます。
}
Serial.print(" is "); ← USB経由で文字列「 is 」をPCに表示させます。
if (c == '*'){ ← レジスターとしての処理を行います
//debugRegPrint
z = Wire.read(); // receive byte as a byte ← 1バイトをbyte型として読みます。
Serial.print("0x"); ← PCに「0x」を送ります。
Serial.println(z, HEX);// print the regValue as a hex ← 読んだデータをHEX形式でPCに送ります。
z = Wire.read(); // throw out a dummy byte ← ダミーバイトを読み捨てします。
} else { ← 任意の文字列の処理となります。
//debugPrint
x = Wire.read(); ← シリアル番号の下位バイトをint型として読みます。
y = Wire.read(); // receive byte as an integer ← シリアル番号の上位バイトをint型として読みます。
x = 256 * y + x; ← シリアル番号に戻しています。x += 256*y とも表現できますが分かり難いですよね。
Serial.println(x);// print the integer ← シリアル番号PCに送ります。
}
}
全体のサンプルコードは下記の通りです。Arduino IDE に付属していたコードを参考にさせていただきました。
(元ファイルは、Arduino IDEを立ち上げたら、メニューバーの「ファイル」−「スケッチの例」−「Wire」と開いて行くとあります)
loop()の中の、debugPrint、debugRegPrint、breakPointの3点で一組と考えていますが、debugPrint、breakPointの2点だけもありかなと思います。ここでは、レジスターTWBRとTWSRの値を読んでいますが、この2つのレジスターの値を読むとI2CのSCLの速度が計算できるからです。
最大の注意点なのですが、レジスタ名としてデバッガーに認識させるためには文字列の最後はアスタリスク(*)で終わってください。これが任意の文字列とレジスター名の文字列との識別子となります。
負の数字は扱わないのでx,yは、intではなくunsigned intとしました。そんな大きなプログラムは扱わないと思うのですが、気になったのでそうしておきました。
ATmega328Pの日本語データシートだとP136の「22.5.2.ビット速度発生器」のところに計算式があります。
SCL周波数=CPUクロック周波数/(16+2×(TWBR)×前置分周値)
前置分周値:P153の表22-7参照。→そのページに行くと、TWSRレジスターのbit1、bit0が、TWPS1、TWPS0とあり、表22-7から前置分周値が読み取れる。
今回の場合、TWBRが0x48で、TWSRが0xF8でした。0x48は10進で72、0xF8の下位2ビットは00なので分周値は1である。これを式に代入すると、SCL=16MHz/(16+2×72×1)=100kHz となりました。
後の問題は、ここで考えたブレークポイントを<どうやってターゲットのソースコードに埋め込むか>ですね。
まさか、関数ごとに手打ちで入れ込むなんて気が遠くなりそうだし間違えそう。なんとかしなくては。
接続図の説明
Arduino IDE を使用しますので、Uncompatinoともう一つのUNO互換機はPCとUSBで接続されます。Uncompatino側のUSBは、アプリが動き始めるとアプリが使用することになります。UNO互換機側のUSBは、I2C経由でUncompatinoから受け取ったデバッグ情報をPCに出力します。
実物写真
デバッガー用にUNO互換機を買うつもりなら、Uncompatinoをお勧めします。Uncompatinoは、ISPライターの機能もあるので、これ1台でUncompatino上のATmega328Pにヒューズバイトとブートローダー、EEPROMを書くことができます。USB-シリアル変換ICのFTDI製FT232RLの機能です。写真の四角で囲ったISPのところがそうです。
I2Cの配線もA4、A5ピンをそれぞれ接続するだけです。ブレッドボードの一番右にはブレークポイントを抜けるためのstartButtonを配置しました。
デバッガー側のシリアルポートの表示例
You can write keywords is 234
TWBR is 0x48
TWSR is 0xF8
You can write keywords is 235
TWBR is 0x48
TWSR is 0xF8
You can write keywords is 236
TWBR is 0x48
TWSR is 0xF8
You can write keywords is 237
TWBR is 0x48
TWSR is 0xF8
Arduino IDEの起動の仕方
私の環境では、ターゲット側のMaster-Writer2はCOM7をシリアルポートに指定しました。デバッガー側は、Arduino IDEをもう一つ起動して、COM8をシリアルポートに指定しました。くどいようですが、Arduino IDEを2つ起動するということは、Arduino IDEのスケッチを2つ開くということとは違います。お間違えのないようにご注意ください。Arduino IDEを2つ起動して初めて、別々のCOMをそれぞれ選べるようになります。Arduino IDEでソースコードを表示したら、COMポートを選択して、シリアルモニターを開いてください。ターゲット側とデバッガー側でそれぞれ別のCOMポートを選択できたかは、ウィンドウの下部にCOM番号が表示されますのでそれでも確認できます。
デバッグ仕様
1.関数名などの文字列と、何番目のブレークポイントなのかを示す通し番号の2つを表示させる。
実装したものが下記となります。シリアル番号の表現としてint型で宣言して上位バイトと下位バイトに分離してバイト表現するやり方もあると思います。ここではbyte型のものを受信側(デバッガー側)でint型に合成することにしました。
Wire.beginTransmissionから始まってWire.write、Wire.endTransmissionで終わる一連の動作が一つのI2Cシーケンスとなります。
void debugPrint(char thisStr[]) { ← thisStr[]が任意の文字列となります。
Wire.beginTransmission(8); // transmit to device #8
Wire.write(thisStr); // sends charcters ← 文字列を送ります。
Wire.write(x[0]); // sends one byte ← シリアル番号の下位バイトを送ります。
Wire.write(x[1]); // sends one byte ← シリアル番号の上位バイトを送ります。
Wire.endTransmission(); // stop transmitting
if (x[0] == 255){
x[1]++; ← シリアル番号の更新です。
}
x[0]++; ← シリアル番号の更新です。
}
2.レジスター名とその内容(HEX形式)を表示させる。
実装したものが下記となります。
(レジスターによっては2バイト返すものがあるらしいのですが勉強不足で未対応です。そのうちに改良します。)
void debugRegPrint(char thisStr[], byte regValue) { ← レジスター名、その内容(1バイト)の順です。
Wire.beginTransmission(8); // transmit to device #8
Wire.write(thisStr); // sends charcters ← レジスター名の送信
Wire.write(regValue); // sends one byte ← レジスターの内容の送信 Arduino IDE では変数としてレジスタ名を書くだけでレジスタの内容が表示される仕様となっています。便利と言えばかなりお手軽な使い勝手です。これは、wire.hをインクルードしたので、幾重にもネストされたどこかのヘッダーファイルにマクロ定義がされているものと思います。そこまで調べて突き止める気力がありませんでした。
Wire.write(0); // dummy byte(debugPrintと揃える為) ← ダミーバイトの送信
Wire.endTransmission(); // stop transmitting
}
3.スタートボタンを押したらブレークポイントから抜けることができる。
実装したものが下記となります。
void breakPoint(void) { ← 引数も戻り値もありません。
while (1) { ← 無限ループです。
if (digitalRead(startButton) == LOW) { ← スタートボタンを押すとLOWになります。
delay(500);//wait a finger to take off ← 500ms待つのは、ボタンを押してから離すまでの時間です。ボタンを押してから離すまでは500ms以内に行わないと次のブレークポイントもすり抜けることになりますので注意してください。逆に長押しするということは、ブレークポイントを複数個所スルーできるので、適宜使い分けると便利かも。
break;//when the startButton got pushed ← 無限ループを抜けます。
}
}
}
4.上記1と2で送られたデータを解析して表示する。
実装したものが下記となります。
I2Cシーケンスが始まると割り込みが発生します。割り込みを処理する関数を割り込みハンドラーと呼びます。
void receiveEvent(int howMany) { ← 割り込みハンドラーです
while (2 < Wire.available()) { // loop through all but the last ← 受信したデータが最後の2バイトになるまでループします。
c = Wire.read(); // receive byte as a character ← 1バイトずつ文字として読みます。
if (c == '*'){ ← 読んだ文字が*なら、ここで打ち切りします。
break;
}
Serial.print(c); // print the character ← USB経由で1文字ずつPCに表示させます。
}
Serial.print(" is "); ← USB経由で文字列「 is 」をPCに表示させます。
if (c == '*'){ ← レジスターとしての処理を行います
//debugRegPrint
z = Wire.read(); // receive byte as a byte ← 1バイトをbyte型として読みます。
Serial.print("0x"); ← PCに「0x」を送ります。
Serial.println(z, HEX);// print the regValue as a hex ← 読んだデータをHEX形式でPCに送ります。
z = Wire.read(); // throw out a dummy byte ← ダミーバイトを読み捨てします。
} else { ← 任意の文字列の処理となります。
//debugPrint
x = Wire.read(); ← シリアル番号の下位バイトをint型として読みます。
y = Wire.read(); // receive byte as an integer ← シリアル番号の上位バイトをint型として読みます。
x = 256 * y + x; ← シリアル番号に戻しています。x += 256*y とも表現できますが分かり難いですよね。
Serial.println(x);// print the integer ← シリアル番号PCに送ります。
}
}
全体のサンプルコードは下記の通りです。Arduino IDE に付属していたコードを参考にさせていただきました。
(元ファイルは、Arduino IDEを立ち上げたら、メニューバーの「ファイル」−「スケッチの例」−「Wire」と開いて行くとあります)
ターゲット側のソースコード(Master-Writer2)
loop()の中の、debugPrint、debugRegPrint、breakPointの3点で一組と考えていますが、debugPrint、breakPointの2点だけもありかなと思います。ここでは、レジスターTWBRとTWSRの値を読んでいますが、この2つのレジスターの値を読むとI2CのSCLの速度が計算できるからです。
最大の注意点なのですが、レジスタ名としてデバッガーに認識させるためには文字列の最後はアスタリスク(*)で終わってください。これが任意の文字列とレジスター名の文字列との識別子となります。
#include < Wire . h >
byte x [ 2 ] ; //as a serial number
const int startButton = 7 ;
void setup ( ) {
Wire . begin ( ) ; // join i2c bus (address optional for master)
pinMode ( startButton , INPUT ) ;
x [ 0 ] = 0 ;
x [ 1 ] = 0 ;
}
void debugPrint ( char thisStr [ ] ) {
Wire . beginTransmission ( 8 ) ; // transmit to device #8
Wire . write ( thisStr ) ; // sends charcters
Wire . write ( x [ 0 ] ) ; // sends one byte
Wire . write ( x [ 1 ] ) ; // sends one byte
Wire . endTransmission ( ) ; // stop transmitting
if ( x [ 0 ] == 255 ) {
x [ 1 ] ++ ;
}
x [ 0 ] ++ ;
}
void debugRegPrint ( char thisStr [ ] , byte regValue ) {
Wire . beginTransmission ( 8 ) ; // transmit to device #8
Wire . write ( thisStr ) ; // sends charcters
Wire . write ( regValue ) ; // sends one byte
Wire . write ( 0 ) ; // dummy byte(debugPrintと揃える為)
Wire . endTransmission ( ) ; // stop transmitting
}
void breakPoint ( void ) {
while ( 1 ) {
if ( digitalRead ( startButton ) == LOW ) {
delay ( 500 ) ; //wait a finger to take off
break ; //when the startButton got pushed
}
}
}
void loop ( ) {
debugPrint ( "You can write keywords" ) ; //ここは適当な文字列
debugRegPrint ( "TWBR*" , TWBR ) ; //read TWBR reg. レジスター名には*をつける
debugRegPrint ( "TWSR*" , TWSR ) ; //read TWSR reg.
breakPoint ( ) ;
}
デバッガー側のソースコード(Slave-Receiver2)
負の数字は扱わないのでx,yは、intではなくunsigned intとしました。そんな大きなプログラムは扱わないと思うのですが、気になったのでそうしておきました。
#include < Wire . h >
void setup ( ) {
Wire . begin ( 8 ) ; // join i2c bus with address #8
Wire . onReceive ( receiveEvent ) ; // register event
Serial . begin ( 230400 ) ; // start serial for output
}
void loop ( ) {
delay ( 100 ) ;
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
char c ;
unsigned int x , y ;
byte z ;
void receiveEvent ( int howMany ) {
while ( 2 < Wire . available ( ) ) { // loop through all but the last
c = Wire . read ( ) ; // receive byte as a character
if ( c == '*' ) {
break ;
}
Serial . print ( c ) ; // print the character
}
Serial . print ( " is " ) ;
if ( c == '*' ) {
//debugRegPrint
z = Wire . read ( ) ; // receive byte as a byte
Serial . print ( "0x" ) ;
Serial . println ( z , HEX ) ; // print the regValue as a hex
z = Wire . read ( ) ; // throw out a dummy byte
} else {
//debugPrint
x = Wire . read ( ) ;
y = Wire . read ( ) ; // receive byte as an integer
x = 256 * y + x ;
Serial . println ( x ) ; // print the integer
}
}
I2CのSCLの周波数計算
ATmega328Pの日本語データシートだとP136の「22.5.2.ビット速度発生器」のところに計算式があります。
SCL周波数=CPUクロック周波数/(16+2×(TWBR)×前置分周値)
前置分周値:P153の表22-7参照。→そのページに行くと、TWSRレジスターのbit1、bit0が、TWPS1、TWPS0とあり、表22-7から前置分周値が読み取れる。
今回の場合、TWBRが0x48で、TWSRが0xF8でした。0x48は10進で72、0xF8の下位2ビットは00なので分周値は1である。これを式に代入すると、SCL=16MHz/(16+2×72×1)=100kHz となりました。
一休み
後の問題は、ここで考えたブレークポイントを<どうやってターゲットのソースコードに埋め込むか>ですね。
まさか、関数ごとに手打ちで入れ込むなんて気が遠くなりそうだし間違えそう。なんとかしなくては。
2016年06月08日
Arduino IDE デバッグやり辛いですよね?
前提条件:Arduino UNO 互換機をターゲットとします。UNO互換機からUSBで大量のデータをPCに送るアプリのデバッグをしようとしています。
Arduino IDE って、デバッグのことは深く考えてないですよね。Visual Studioみたいにブレークポイントの設定ができるとよいのですが、そういうものは一切無いですよねえ。これって贅沢な意見なのでしょうか。残念ですね。
Arduino IDE for Visual Studio extention というものがあるらしいのですが、PCとターゲットボード間はシリアルポート(USB)で接続するみたいです。そうなると、ターゲットの機能でシリアルポート(USB)を使う仕様だった場合はどうなるのでしょうか? 複数のシリアルポート(USB)をターゲットボードが持っていないといけないですよね。う〜む。
Arduino IDE for Visual Studio extentionが、I2CかSPIでターゲットボードと通信する仕様なら実用性があると思うのですが、実際のところどうなのでしょう? シリアル接続じゃあ、シリアルポート使うアプリだとデバッグできないということでしょ? これは絶対に不便だと思うなあ。これって実際にデバッグ記事の投稿ありませんよね。
やはり現実的な方法としては、ターゲットボードのパラメーターを、別のArduino(互換機)とI2C通信で取得して、それを別のArduino(互換機)のシリアルポートからPCへ出力するのがベストですよね。
みなさんはどうされていますか。もしご存じでしたら教えていただけないでしょうか。
Arduino IDE って、デバッグのことは深く考えてないですよね。Visual Studioみたいにブレークポイントの設定ができるとよいのですが、そういうものは一切無いですよねえ。これって贅沢な意見なのでしょうか。残念ですね。
Arduino IDE for Visual Studio extention というものがあるらしいのですが、PCとターゲットボード間はシリアルポート(USB)で接続するみたいです。そうなると、ターゲットの機能でシリアルポート(USB)を使う仕様だった場合はどうなるのでしょうか? 複数のシリアルポート(USB)をターゲットボードが持っていないといけないですよね。う〜む。
Arduino IDE for Visual Studio extentionが、I2CかSPIでターゲットボードと通信する仕様なら実用性があると思うのですが、実際のところどうなのでしょう? シリアル接続じゃあ、シリアルポート使うアプリだとデバッグできないということでしょ? これは絶対に不便だと思うなあ。これって実際にデバッグ記事の投稿ありませんよね。
やはり現実的な方法としては、ターゲットボードのパラメーターを、別のArduino(互換機)とI2C通信で取得して、それを別のArduino(互換機)のシリアルポートからPCへ出力するのがベストですよね。
みなさんはどうされていますか。もしご存じでしたら教えていただけないでしょうか。
2016年06月06日
avrdudeを使ってATmega328Pにヒューズバイトとブートローダを書き込む
avrdudeのダウンロードとインストールは、「USB−シリアル変換IC FT232RLを使ったブートローダの書き込み」を参考にしてください。
URL・・・ https://fanblogs.jp/papas56/archive/6/0
ターゲットはUncompatinoとします。PCとUncompatinoをUSB接続します。UncompatinoのISPはジャンパー線で下記のようにショートしておきます。
CTS--MISO
DCD--MOSI
DSR--SCK
RI--RESET
最後にavrdudeを起動します。
?@avrdude.exeの場所を指定する。
?APrgrammerに、FT232R Synchronous BitBang(diecimila)を指定する。
?BUncompatinoのPort番号を指定する。デバイスマネージャーを起動しておき、UncompatinoをPCに接続すると新たにCOMが表示されるので、その番号を指定する。
?CDeviceに、ATmage328P(m328p)を指定する。
?DCommand line Optionに、-P ft0 B 115200 と指定する。
?EReadボタンをクリックしてまず値を読んでみる。書き込む値は下記を指定する。
hFuse・・・DA
lFuse・・・DF
eFuse・・・05
Writeボタンをクリックして書き込む。もう一度Readボタンをクリックして値を確認する。
?Fブートローダーを指定する。下記の値を使用する。
インストールしたフォルダ\arduino-nightly\hardware\arduino\avr\bootloaders\optiboot\optiboot_atmega328.hex
エラーが無ければ何事も表示されないので、あっけなく書き込みは完了する。エラーがあるとダイアログが開きエラー内容が表示される。
URL・・・ https://fanblogs.jp/papas56/archive/6/0
ターゲットはUncompatinoとします。PCとUncompatinoをUSB接続します。UncompatinoのISPはジャンパー線で下記のようにショートしておきます。
CTS--MISO
DCD--MOSI
DSR--SCK
RI--RESET
最後にavrdudeを起動します。
?@avrdude.exeの場所を指定する。
?APrgrammerに、FT232R Synchronous BitBang(diecimila)を指定する。
?BUncompatinoのPort番号を指定する。デバイスマネージャーを起動しておき、UncompatinoをPCに接続すると新たにCOMが表示されるので、その番号を指定する。
?CDeviceに、ATmage328P(m328p)を指定する。
?DCommand line Optionに、-P ft0 B 115200 と指定する。
?EReadボタンをクリックしてまず値を読んでみる。書き込む値は下記を指定する。
hFuse・・・DA
lFuse・・・DF
eFuse・・・05
Writeボタンをクリックして書き込む。もう一度Readボタンをクリックして値を確認する。
?Fブートローダーを指定する。下記の値を使用する。
インストールしたフォルダ\arduino-nightly\hardware\arduino\avr\bootloaders\optiboot\optiboot_atmega328.hex
エラーが無ければ何事も表示されないので、あっけなく書き込みは完了する。エラーがあるとダイアログが開きエラー内容が表示される。
2016年06月05日
USB−シリアル変換IC FT232RLを使ったブートローダの書き込み
Aruduino IDE(開発環境)を使用してもISPにてブートローダを書き込めるとのことですが、Aruduino(ハードウエア)をライターとして用意し、ライターソフトも書き込む必要があります。
avrdude(開発環境)は、ターゲット(例えばUncompatino)のATmega328Pに直接ヒューズビットやブートローダを書き込めるとのことです。これは、USB-シリアル変換ICのFT232RLのCTS、DSR、DCD、RIの4つの制御線を以下のようにATmega328Pに接続することによって、ヒューズビットとブートローダを書き込めるようになっているとのことです。
CTS--MISO
DCD--MOSI
DSR--SCK
RI--RESET
+5VとGNDはUSB経由でPCから供給されることが前提。
参考にしたサイトです。
http://engawa.kakaku.com/userbbs/1681/Page=2/SortType=ThreadID/#1681-6
avrdude(開発環境)は、ターゲット(例えばUncompatino)のATmega328Pに直接ヒューズビットやブートローダを書き込めるとのことです。これは、USB-シリアル変換ICのFT232RLのCTS、DSR、DCD、RIの4つの制御線を以下のようにATmega328Pに接続することによって、ヒューズビットとブートローダを書き込めるようになっているとのことです。
CTS--MISO
DCD--MOSI
DSR--SCK
RI--RESET
+5VとGNDはUSB経由でPCから供給されることが前提。
参考にしたサイトです。
http://engawa.kakaku.com/userbbs/1681/Page=2/SortType=ThreadID/#1681-6
タグ: avrdude