新規記事の投稿を行うことで、非表示にすることが可能です。
2018年12月10日
Visual Studio 2017 Community VC++ にソースファイルを追加する方法
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年前でしょうか)なので、最初に、ソースプログラムを追加するところまでは、備忘録としてやり方を記録しておくことにしました。
空のプロジェクトにソースプログラム(XXXX.cpp)を追加する手順を説明しておきます。(空のプロジェクトについては、https://fanblogs.jp/papas56/archive/53/0を参考にしてください。)
1.Visual Studio 2017 Communityを立ち上げる。
2.プロジェクトを開く。(ここでは、ModelAppというプロジェクトを立ち上げています。)
画面の右側のソリューションエクスプローラーを使います。「ソースファイル」を右クリック、「追加」をクリック、「既存の項目」をクリックします。
そうすると、「既存の項目の追加」ダイアログボックスが開きますので、追加したいファイルを選択します。
3.ModelMain.cppというファイルをプロジェクトに追加したところです。
エディターエリアにソースコードを表示したいときは、右側のソリューションんエクスプローラー内の追加したソースファイルをダブルクリックします。下記のように表示されます。
空のプロジェクトにソースプログラム(XXXX.cpp)を追加する手順を説明しておきます。(空のプロジェクトについては、https://fanblogs.jp/papas56/archive/53/0を参考にしてください。)
1.Visual Studio 2017 Communityを立ち上げる。
2.プロジェクトを開く。(ここでは、ModelAppというプロジェクトを立ち上げています。)
画面の右側のソリューションエクスプローラーを使います。「ソースファイル」を右クリック、「追加」をクリック、「既存の項目」をクリックします。
そうすると、「既存の項目の追加」ダイアログボックスが開きますので、追加したいファイルを選択します。
3.ModelMain.cppというファイルをプロジェクトに追加したところです。
エディターエリアにソースコードを表示したいときは、右側のソリューションんエクスプローラー内の追加したソースファイルをダブルクリックします。下記のように表示されます。
【このカテゴリーの最新記事】
2018年07月09日
[ Python IDE ] Spyder にて、コマンドライン引数を渡してデバッグする方法
書籍「退屈なことはPythonにやらせよう」を読みながら、Pythonの勉強をしているところです。私は Pythonのディストリビューションの1つ Anaconda をインストールしました。すると、デバッグ環境として IDLE と Spyder の両方がインストールされることになります。
書籍「退屈なことはPythonにやらせよう」は分かりやすくてなかなかよいと思います。本文を読み進めて行くと、コマンドライン引数を渡す例題にぶち当たります。本文(P143 コラム「IDLEの外でPythonスクリプトを実行する」、または8.7 プロジェクト:マルチクリップボードなど)には デバッグ環境がIDLEなので、コマンドライン引数(sys.argvに値を代入したいということ)に値を渡せませんので、IDLE の外側から、つまりコマンドプロンプトから実行しろと書いてあるではありませんか。初心者だからデバッガー使いたいのに...
この記事では、せっかく Spyder もインストールされているので、Spyder でコマンドライン引数を渡してデバッグする方法をここに書いておきます。
Spyderを起動します。ソースコードを書きます。私の場合は同書籍本文 8.7のソースコードになります。
上記の画像は小さくて見えにくいのでクリックして拡大にしてください。コマンドライン引数を渡すには、「設定の実行(Ctrl+F6)」をクリックします。もちろんショートカットキーでもOKです。すると下記の子画面が出ます。コマンドラインオプションにチェックを入れて、渡したい引数を書きます。私の場合は、save と abc を入れました。OKをクリックして子画面を閉じます。あとは普通にデバッグするだけです。
以上です。
書籍「退屈なことはPythonにやらせよう」は分かりやすくてなかなかよいと思います。本文を読み進めて行くと、コマンドライン引数を渡す例題にぶち当たります。本文(P143 コラム「IDLEの外でPythonスクリプトを実行する」、または8.7 プロジェクト:マルチクリップボードなど)には デバッグ環境がIDLEなので、コマンドライン引数(sys.argvに値を代入したいということ)に値を渡せませんので、IDLE の外側から、つまりコマンドプロンプトから実行しろと書いてあるではありませんか。初心者だからデバッガー使いたいのに...
この記事では、せっかく Spyder もインストールされているので、Spyder でコマンドライン引数を渡してデバッグする方法をここに書いておきます。
Spyderを起動します。ソースコードを書きます。私の場合は同書籍本文 8.7のソースコードになります。
上記の画像は小さくて見えにくいのでクリックして拡大にしてください。コマンドライン引数を渡すには、「設定の実行(Ctrl+F6)」をクリックします。もちろんショートカットキーでもOKです。すると下記の子画面が出ます。コマンドラインオプションにチェックを入れて、渡したい引数を書きます。私の場合は、save と abc を入れました。OKをクリックして子画面を閉じます。あとは普通にデバッグするだけです。
以上です。
2017年12月18日
modeequiv() について調べたこと(備忘録)
ソースコードは下記の通り。
void
modeequiv()
{
static const struct eqdic_s {
byte tkn;
byte tdif;
int rnum;
word wu;
} eqdic[] = {
{20, 2, 52, 4000},
{10, 4, 104, 4000},
{ 4, 10, 260, 10000},
{ 2, 20, 520, 20000},
};
const struct eqdic_s *eq;
int realnum, i;
byte at, crcnt, tokadif, toka, tokanum;
byte ch, chnum, vh, adch, adchT;
word ui1, waituntil, sinterval;
rminit(false);
eq = &eqdic[oscspeed & 3];
tokanum = eq->tkn;
waituntil = eq->wu;
realnum = eq->rnum;
tokadif = eq->tdif;
sinterval = 40; // 20us
uartjob();
// ADMUX reg values
switch(oscinput) {
default:
case 0x00: adch = 0x61; chnum = 1; break;
case 0x01: adch = 0x62; chnum = 1; break;
case 0x02: adch = 0x61; chnum = 2;
tokanum >>= 1;
tokadif <<= 1;
break;
}
adchT = 0x61 + (osctrig & 7);
header(2, 0);
// This data packet contines to MARC-A
sinterval--;
crcnt = 0;
at = 0;
for(toka = 0; toka < tokanum; toka++) {
for(ch = 0; ch < chnum; ch++) {
// reset and initialize timer1
TCCR1B = 0x00; // stop, set normal mode
TCCR1A = 0x00;
TIMSK1 = 0x00; // no irq
ICR1 = 0x0000;
TCNT1 = 0x0000;
TIFR1 = 0x27; // clear flags;
// analog comparator setting
// The D6 pin is the positive input.
// The negative input is A1, A2, A3, or A4 pin.
ACSR = 0x94; // analog comparator off
DIDR1 = 0x03; // disable the digital input func of D6 and D7.
ADMUX = adchT; // select the negative input
ADCSRA = 0x04;
ADCSRB = 0x40;
// start time1 with pre=1/8 (2MHz)
// input capture noise canceler ON
TCCR1B = (osctrig & 0x10) ? 0xc2 : 0x82; // edge selection
ACSR = 0x14; // capture-on, aco to caputure timer1
TIFR1 = 0x27; // clear flags again
ui1 = (tokadif * toka) + (osctdly << 1);
// falling edge detection(rising edge for ICES1)
// doesn't stabilize without a 20usec wait below.
while(TCNT1 < 40)
;
TIFR1 = 0x27;
// wait until a trigger event happens
while(true) {
if (TIFR1 & 0x20) {
// trigger event has happened.
ui1 += ICR1;
at = 0; // a trigger event has happened.
break;
}
if (TCNT1 > waituntil) {
ui1 += TCNT1;
at = 1; // trigger failed.
break;
}
uartjob();
}
// at:0 -> trigger event has happened, 1 -> not happened
ACSR = 0x94; // disable analog comparator
ADCSRB = 0x00;
ADCSRA = 0x84; // adc enable
TCCR1B = 0x1a; // timer1 CTC-ICR1 mode pre1/8
TCCR1A = 0x00; // CTC mode;
ICR1 = ui1;
TIFR1 = 0x27; // clear flags
ADMUX = 0x60; // adc target is A0 pin to get trigger value;
ADCSRB = 0x07; // timer1 capture event;
ADCSRA = 0xf4; // adc auto trigger, force 1st conversion
// wait until the 1st conversion finishes.
while((ADCSRA & 0x10) == 0x00)
uartjob();
vh = ADCH; // trigger level
osctvolt = vh;
ADMUX = adch + ch;
ADCSRA = 0xb4; // clear flag, 1MHz, adate on
if (toka == 0 && ch == 0) { // needed only for the 1st loop
// MARC-A continued
txput1(at);
txput1(vh);
txputcrc(false);
txgo(); // start to trasmit a packet
if (at)
goto ex; // send header only when trigger failed
}
for(i = 0; i < realnum; i++) {
while(true) {
if (TIFR1 & 0x20) {
ICR1 = sinterval;
TIFR1 = 0x27; // clear timer1 flags;
}
if ((ADCSRA & 0x10) != 0x00)
break;
uartjob();
}
vh = ADCH;
ADCSRA = 0xb4; // clear flag, 1MHz, adate on
txput1(vh);
if (++crcnt >= 200) {
crcnt = 0;
// cause crc error on purpose if trigger failed(at > 0).
txputcrc((at > 0) ? true : false);
}
}
}
}
//if (crcnt > 0)
// sysdown(800);
if (crcnt == 40) {
txputcrc((at > 0) ? true : false);
}
else
sysdown(800);
ex:
txfinish(true, true);
}
2017年12月17日
txputには、txput0(byte ch), txput1(byte ch), txputcrc(boolean force_error) がある
ソースコードは下記の通り。
void
txput0(byte ch)
{
// to reduce the cpu consumption,
// venture to omit txn overflow check.
// if programmed properly, such an overflow never occurs.
// rxn(appears later) check is omitted as well.
txbuf[txn++] = ch;
txcrc = 0;
}
void
txput1(byte ch)
{
txbuf[txn++] = ch;
txcrc = crctbl[txcrc ^ ch];
}
void
txputcrc(boolean force_error)
{
txput0((force_error) ? ++txcrc : txcrc);
}
uartjob() について調べたこと(備忘録)
ソースコードは下記になります。
rollmodeだとrmbuf[]にADCH(ADCの上位8bit)を書き込む。
そうじゃないと、UDR0にtxbuf[]を書き込む。
rollmodeだとrmbuf[]にADCH(ADCの上位8bit)を書き込む。
そうじゃないと、UDR0にtxbuf[]を書き込む。
void
uartjob()
{
byte sts;//sts は、status のことらしい
sts = UCSR0A;//UCSRnA - USARTn制御/状態レジスタA (USART Control and Status Register n A)
if ((char)sts < 0) //UCSR0Aの第7bitが1、つまり受信バッファに未読データありということ
rxbuf[rxn++] = UDR0;//UDRn - USARTnデータ レジスタ (USART I/O Data Register n)
//受信バッファにデータがあるのでrxbuf[]に取り込んだ
// in case rxbuf[] overflow, no fatal situation happens.
// because rxn is an 8 bit variable and rxbuf[] size is 256.
if (rmon) {//rmonって何? rmってroll memoryのことらしい
//rmonは、onがtrueの時に1としているみたい、falseなら0
//ここは殆ど通らないところ?
if (TIFR1 & 0x20)//TIFR1 - タイマ/カウンタ1割り込み要求フラグ レジスタ (Timer/Counter 1 Interrupt Flag Register)
//カウンタ1がTOP値になった
TIFR1 = 0x27; // clear timer1 flags; タイマ/カウンタ1割り込み要求フラグを全部クリアしている
if (ADCSRA & 0x10) {//ADCSRA - A/D制御/状態レジスタA (ADC Control and Status Register A)
if (rmon == 1) {
ICR1 = 100 - 1; // 50us
//ICR1は16bitレジスタ カウンタに設定する値
//0.5usを100倍すると50us
ADMUX = 0x62;//ADMUX - A/D多重器選択レジスタ (ADC Multiplexer Select Register)
//0x62 基準電圧はAVCCでアナログ入力はADC2 PC2 下記のコメントと矛盾
rmon = 2;
rmbuf[rmw++] = ADCH; // CH1(A1pin) value
//ADCの値は、8bit精度ならADCHを読むだけで事足りる(ADCLは読まない)
}
else if (rmon == 2) {
ICR1 = 400 - 1; // 200us
//0.5usを400倍すると200us
ADMUX = 0x60;//0x60 基準電圧はAVCCでアナログ入力はADC0 PC0 下記のコメントと矛盾
rmbuf[rmw++] = ADCH; // CH2(A2pin) value
rmon = 3;
}
else {
ICR1 = 500 - 1; // 250us
//0.5usを500倍すると250us
ADMUX = 0x61;//0x61 基準電圧はAVCCでアナログ入力はADC1 PC1 下記のコメントと矛盾
rmon = 1;
osctvolt = ADCH; // trigger level
}
ADCSRA = 0xb4; // clear flags, 1MHz, adate on
//ADCSRA - A/D制御/状態レジスタA (ADC Control and Status Register A)
//システムクロック16分周
return; //in order to release cpu quickly
}
}
if (txr < txn && (sts & 0x20)) {
UCSR0A = (sts & 0xe3) | 0x40;
UDR0 = txbuf[txr++];//UDRn - USARTnデータ レジスタ (USART I/O Data Register n)
//UDR0は送受信バッファ、バッファに送信データを書き込む
}
}
sysdown(int dly) について調べたこと(備忘録)
ソースコードは下記の通り。
レジスターに値を代入し、D13のLEDを点滅させる内容。
レジスターに値を代入し、D13のLEDを点滅させる内容。
void
sysdown(int dly) // dly .. in msec
{
int i;
byte s;
SPCR = 0x00; // disable SPI
TCCR0B = 0x00; // stop timer0
TCCR0A = 0x02; // ctc mode
TIMSK0 = 0x00; // Disable all timer0 irqs
TIFR0 = 0x07; // clear flags
TCNT0 = 0x00;
OCR0A = 250 - 1;
TCCR0B = 0x03; // start timer0 pre = 1/64 i.e 250kHz
s = 0;
while(true) {
if (++s & 1)
PORTB |= 0x20; // D13 == HIGH (LED on)
else
PORTB &= 0xdf; // D13 == LOW (LED off)
for(i = 0; i < dly; i++) {
while((TIFR0 & 2) == 0)
;
TIFR0 = 0x07; // clear flags
}
}
}
2017年12月15日
txinit()について調べたこと(備忘録)
ソースコードは下記の通り。
void
txinit(void)
{
if (txn >= TXBSZ) // TXBSZは1100のこと、ソースコードの冒頭に定義してありました!
sysdown(200); // tx buffer overflow has been detected.
txn = 0;
txr = TXBSZ;
}
header(byte typ, byte reqid)について調べた(備忘録)
ソースコードは下記の通り。ヘッダーのデータを作成しているらしい。
詳細は現時点では不明。
@Arduino_UNOに送るためのオシロスコープの設定を作っているらしい。
Atxbuf[]に書き込む回数と読みだす回数が一致していない理由が不明。
詳細は現時点では不明。
@Arduino_UNOに送るためのオシロスコープの設定を作っているらしい。
Atxbuf[]に書き込む回数と読みだす回数が一致していない理由が不明。
void
header(byte typ, byte reqid)
{
static byte seq;//staticだから前の値を保持している
txinit();
uartjob();
// prologue
//序章?
txput0(0xaa);//txbuf[]に書き込み
txput0(0x55);//txbuf[]に書き込み
txput0(0xa5);//txbuf[]に書き込み
txput0(0x5a);//txbuf[]に書き込み
uartjob();//ここまでtxbuf[]に4回書き込んだが、txbuf[]から読みだしたのはこの1回、
txput1(typ);
if (typ == 3)//3だとrollmodeなの?
txput1(seq++); // rollmode
else
txput1(reqid);
txput1(oscspeed);
txput1(oscinput);
uartjob();//txbuf[]に書き込む回数と読みだす回数が一致しないのは?
txput1(osctrig);
txput1(osccupgain);
txput1(osctdly >> 8);
txput1(osctdly);
uartjob();
txput1(oscofreq >> 16);
txput1(oscofreq >> 8);
txput1(oscofreq);
txput1(oscoduty);
uartjob();
}
moderoll()について調べたこと(備忘録)
moderoll()は、kit_scope.ino 中の loop() の中にある関数です。
詳細はまだ不明。
@rmon==0の時(プログラム開始直後の時か?)
各種レジスターに値を代入
Aheader(3, 0)を実行
txput1(0)
txput1(osctvolt)
txputcrc(false)
上記は何かしらデータを送信している
Btxgo()を実行 パケットを送信開始
Cfor文を実行 この中でおそらく初めにヘッダーデータを、次に波形データを送信しているらしい
Dtxputcrc(false)
txfinish(true, true) を実行し、一連のデータ送信が完了ということらしい
ソースコードは下記の通り。
詳細はまだ不明。
@rmon==0の時(プログラム開始直後の時か?)
各種レジスターに値を代入
Aheader(3, 0)を実行
txput1(0)
txput1(osctvolt)
txputcrc(false)
上記は何かしらデータを送信している
Btxgo()を実行 パケットを送信開始
Cfor文を実行 この中でおそらく初めにヘッダーデータを、次に波形データを送信しているらしい
Dtxputcrc(false)
txfinish(true, true) を実行し、一連のデータ送信が完了ということらしい
ソースコードは下記の通り。
void
moderoll()
{
byte i;
if (rmon == 0) { // start rollmode
// reset and initialize timer1
TCCR1B = 0x00; // stop
TCCR1A = 0x00;
TIMSK1 = 0x00; // no irq
TCNT1 = 0x0000;
ICR1 = 200; // 100 usec
TIFR1 = 0x27; // clear flags;
ACSR = 0x94; // disable analog comparator
ADCSRB = 0x00;
ADCSRA = 0x84; // adc enable
ADMUX = 0x60; // adc target is A0 pin to get trigger value;
ADCSRB = 0x07; // timer1 capture event;
ADCSRA = 0xf4; // adc auto trigger, force start 1st conversion
TCCR1B = 0x1a; // timer1 CTC-ICR1 mode pre1/8
TCCR1A = 0x00; // CTC mode;
// wait until the 1st conversion finishes.
while((ADCSRA & 0x10) == 0x00)
uartjob();
osctvolt = ADCH; // trigger level
ADMUX = 0x61;
ADCSRA = 0xb4; // clear flag, 1MHz, adate on
rminit(true);
}
header(3, 0);
txput1(0);
txput1(osctvolt);
txputcrc(false);
txgo(); // start to trasmit a packet
for(i = 0; i < 200; i++) {
while(rmw == rmr)
uartjob();
txput1(rmbuf[rmr++]);
}
txputcrc(false);
txfinish(true, true);
}
kit_scope.ino について調べたこと(備忘録)
kit_scope.inoは、Arduino開発環境のソースコードです。v0.72 Mar 20, 2016版を使用しています。
ATmega328Pのデータシートは支障がない限り、下記(日本語)を参照します。
https://avr.jp/user/DS/PDF/mega328P.pdf
Arduino開発環境については支障がない限り、下記(日本語)を参照します。
http://www.musashinodenpa.com/arduino/ref/
この部分で行っているのは、入力信号のAD変換とUARTでPCへの送信、UARTでPCからのコマンドの受信となります。
Arduino のソースコードの形式はC言語に従いますが、setup()に初期設定を書き、loop()に通常処理を書きます。setup()は文字通り1回だけ実行されます。loop()も文字通りで、これは無限ループになります。setup()とloop()を置く順番は、特に無いようです。大文字で記載されている変数は、CPU(AtMega)のレジスターとなります。レジスターはAtMegaの仕様書に記載されている名称そのままで、変数宣言しないで使用します。cli()の関数もArdino環境固有のもので、全ての割り込みを禁止にする関数です。
ATmega328Pのデータシートは支障がない限り、下記(日本語)を参照します。
https://avr.jp/user/DS/PDF/mega328P.pdf
Arduino開発環境については支障がない限り、下記(日本語)を参照します。
http://www.musashinodenpa.com/arduino/ref/
この部分で行っているのは、入力信号のAD変換とUARTでPCへの送信、UARTでPCからのコマンドの受信となります。
Arduino のソースコードの形式はC言語に従いますが、setup()に初期設定を書き、loop()に通常処理を書きます。setup()は文字通り1回だけ実行されます。loop()も文字通りで、これは無限ループになります。setup()とloop()を置く順番は、特に無いようです。大文字で記載されている変数は、CPU(AtMega)のレジスターとなります。レジスターはAtMegaの仕様書に記載されている名称そのままで、変数宣言しないで使用します。cli()の関数もArdino環境固有のもので、全ての割り込みを禁止にする関数です。