目次
コメントはありません。 Comments/tomise
前回のitos()は0だと表示されないので一行追加。
桁数以下の幅を指定したらまずいのは同様。
void itos(char *s, int i, int width) { s[width] = '\0'; s[width - 1] = '0'; for (; i; i /= 10) s[--width] = i % 10 + '0'; while (width) s[--width] = ' '; }
割込ルーチンでどのピンの割込なのかを確かめてからカウント。
#pragma interrupt_handler INT_GPIO void INT_GPIO(void) { if ((PRT0DR & (0x01 << 7)) == 0) ++wheel; }
他も適当に組んで、赤外線LEDを動かすとカウントされるのを確認した。
カウントはcounterモジュールをつかっても良さそうだけど、これぐらいなら使わなくても良さそう。
起動時の動作チェックアニメーションを何パターンか作成した。
液晶に全て0xff(黒塗り)を表示させる。
sprintf()の代りにcsprintf()があったが、桁オプションが使えなくて結局使えなかった。
仕方ないので、文字幅を指定してintを文字列にする関数を作った。
/* * sに整数iをwidth幅で文字列化して格納する * widthが文字列幅以下にならないように注意 * itos(s, 16, 3); // " 16" * itos(s, 8, 5); // " 8" */ void itos(char *s, int i, int width) { s[width] = '\0'; for (; i; i /= 10) s[--width] = i % 10 + '0'; while (width) s[--width] = ' '; }
単位表示で3文字も幅を取るのが勿体ないのでCGRAMに単位文字を定義しようと思ったが、5x7ドットではさすがに難しい。
素直に3文字分(km/h, kph, rpm)使っておくのが無難か?
点火と回転は割込でcountしようと思ったが、割込は同じ関数が呼び出される。
関数内でポートの状態を見て、どのピンからの割込かを調べてcount?
表示更新は割込関数内ではせずにmain()か定期的なタイマー割込でした方が良さそう。
磁気抵抗素子の値の変化が小さすぎてテスタでもわからないので、赤外線LEDと受光素子に方向転換。
エミッタ接地回路でコレクタに100Ωを繋げると5.0 <-> 4.5V
10kΩに変更して4 <-> 0V
これならデジタル入力に使えそう。
磁気抵抗素子DM-106Bの配置と測定。
配線ミスやら、入力ピンに制限があることに気付かず、無駄に時間を取られた。
SAR6で値を取ってみると、磁石を殆ど接触させた状態で1, それ以外は0という値。
ADCの使い方が間違っている?
PGA経由でGainを色々変えてみても大して変わらない。
スイッチ割込でカウント、タイマー割込で定期的に表示更新まで。
mainのループは空にできた。
PSoCGPIOINT.asmはこんな感じに。
;@PSoC_UserCode_BODY@ (Do not change this line.) ;--------------------------------------------------- ; Insert your custom code below this banner ;--------------------------------------------------- ljmp _INT_GPIO ;--------------------------------------------------- ; Insert your custom code above this banner ;--------------------------------------------------- ;@PSoC_UserCode_END@ (Do not change this line.)
main.cはこんな感じに。先程のPSoCGPIOINT.asmに書いた関数名の先頭から'_'を除いた名前で宣言。
#pragma interrupt_handler INT_GPIO void INT_GPIO(void) { // ... }
調べていて見つけた情報。割込に使ったポートと同じポートに出力するとはまる可能性。
sprintf()が使えないので、itoa()で。
#include <stdlib.h>
char line[17] = {'\0'}; itoa(line, 12345, 10);
でもこれだと桁揃えがしにくい。
それを改善したマクロが見つかるが、if分岐で何とかしても良さそう?
if (count < 10) ; else if (count < 100) ; else if (count < 1000) ; else if (count < 10000) ; else ;
前回の配線図通りに配線。初めにピンを間違えて大幅な時間ロスをした。
コントラスト調整用に10kΩの可変抵抗をつけるべき所に普通の抵抗をつけてしまって、かなり見にくい状態だったのでとりあえずGND直結で動作確認。
文字列の表示はこんな感じ。
LCD_1_Start(); LCD_1_Position(0, 0); // 行, 列 LCD_1_PrCString("LCD Test");
datasheetを見ていると、棒グラフを表示させるなんていう面白いAPIを発見。
ドット単位のパターンを用意して実現している様子。
デバッグやらにも便利に使えそう。
SC1602は1文字を5 * 7ドットで表現しているので、横棒グラフなら5 * 16 = 80ドット、縦棒グラフなら7 * 2 = 14ドット。
使い方はこんな感じ。
LCD_1_InitBG(LCD_1_SOLID_BG); LCD_1_DrawBG(0, 0, 16, 72); // 行, 開始列, 終了行, グラフの長さ
DrawBG()の引数がちょっとわかりにくいけど、次のような感じ。
LCD_1_DrawBG(0, 0, 16, 50); // 0行目の0〜16文字を使って50ドットの長さ LCD_1_DrawBG(0, 1, 5, 60); // 0行目の1〜5文字を使って60ドット(5 * 5 = 25を超えるけど超えた分は表示されないから25ドットになる)
良く考えたら16文字だからDrawBG(0, 0, 15, ...)が正しい気がする。
データシートと睨めっこした結果、こんな感じになった。
配線距離が長いが、ユニバーサル基板に液晶を取り付けたときのバランスを考えると、どうしても隅っこになってしまう。
何を作りたいかの発表と、その中からどれを実際に作っていくか、大体の方針の決定。
皆実装に縛られない自由な案を出していて、実装前提で考えている自分は何だか縛られている感じがした。
次回までにキャラクタ液晶の配線を考えておく。
FIRST TOUCHでCapSenseを試した後、ユニバーサル基板にICソケット、LED、抵抗、スイッチを配置して半田付けの作業。
PSoCの開発環境を整え、FIRST TOUCHを使ってLEDを光らせる所まで。
PSoC入門:PSoC First Touch編に従って、プロジェクトの作成、モジュールの配置、配線、設定の一通りの流れを実施。
プログラムを書く前の設定作業が多いなあと思ったが、それだけ自由度が高いということか。
バージョンが更新されたようでPSoC入門:PSoC First Touch編とは異なる箇所がいくつかあった。