ぷらこのきろく

メモとかテストとか備忘録とか

ASOOVU USBで遊んでみる(2-1)

その2-1:割り込みを使おうとして失敗する

タイマ機能というものがあるらしい。時間をカウントして一定時間経ったら教えてくれたり時間を計ったりできるらしい。
その機能で、時間がたったら割り込みがかかって教えてくれるものがあるっぽい。
というわけで、割り込みを使おうと思いたった。

XC8のマニュアルを読むと、

void interrupt hoge(void)

と書くと、hoge()は割り込み関数として登録されるらしい。
ASOOVU USBで使われるPIC18F2550は、割り込み関数が二つ(優先度高と優先度低)使えて、それぞれ

void interrupt low_priority hoge(void)
void interrupt high_priority heke(void)

で、優先度低と高が使えるらしい。と、PIC18F2550のデータシートとXC8のマニュアルに書いてあった。

というわけで、何もしない(単にreturnを返す)だけの割り込み関数だけ作って、動かそうとしてみた。
・・・動かない。今まで動いていたmain()の中身が実行されない。
いろいろ試してみた。3日ぐらいかけて。関数の中身を変えてみたり、割り込み許可をしないようにしてみたり、コンフィギュレーションビットを確認してみたり。
で、確認できたのは、割り込み関数を定義すると動かなくなって、定義をコメントアウトすると動くようになる。

なんでだろう・・・と、ASOOVU USBの販売元のサイトからサンプルプログラムをダウンロードして確認してみた。bootload.hに

#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS	0x1008
...
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
void Remapped_High_ISR (void)

とかかいてある。書いてあることは半分くらいしかよくわからないが、優先度高の割り込み関数が置いてあるアドレスが0x1008に再設定された、ということなのではないか。

mapファイル(プロジェクトのhexファイルが置いてあるディレクトリと同じ場所に、~.mapと書いてあるファイルがある)を確認する。
ちょっとしか意味はわからないが、このファイルには関数やグローバル変数などがどのアドレスに割り付けてあるかが書いてある。

サンプルプログラムのmapファイルの優先度高割り込み関数(だと思われるもの)は、確かに0x1008に割り付けられてる。
そして、自分が書いたプログラムのmapファイルを見ると、0x0008に割り付けられている。

ここで、データシートを見る。figure5-1にメモリのマップがある。やっぱり0x0008だよなぁ。。
でも、やってみるしかない。割り込み関数の割り付けを変えてみよう。。

MPLAB X IDEのプロジェクトを右クリックして、Propertiesを選択。
XC8 LinkerのカテゴリからAdditional optionsを選択。Extra Linker Optionsに

-L-preset_vec=1000h,intcode=1008h,intcodelo=1018h,powerup,init

と記述。
f:id:prizeout:20171225223504p:plain
あ、なんかmain()が動きだした。割り込み関数を使ってみよう、と、適当にタイマ0で割り込みを起こしてみたら、
ちゃんと割り込み関数を通った。
しかしなんで割り付けをデフォルトから変えないといけないのだろう。どこにその説明が書いてあるのだろう。
まあともかく、これで次はやっとタイマをまともに使える。
続く。

ASOOVU USBで遊んでみる(4)

その(4) :コード書いてコンパイル・書き込み・実行

コード確認

コードはこれだけ
f:id:prizeout:20171217162443p:plain
とりあえずメモ

9行目

ヘッダファイルインクルード。こないだの日記でコンフィグレーションビットの設定を出力したコピーペースト。中でxc.hをインクルードしている。

14~15行目

PORTBとLATBを0クリア。
前の日記の初期化例で調べたのをそのまま。

16行目

TRISBを0に設定。つまり、RB0~RB7を全部出力に設定。

18行目

while(1)で回す。組込み関係ではプログラムは終了しないのが常道らしい。つまりmain()関数のreturnはしない。

19行目

500ms待つ。これはXC(コンパイラ)が提供するマクロみたい。
xc.hから読み込まれるpic.hに*1

// NOTE: To use the macros below, YOU must have previously defined _XTAL_FREQ
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

って書いてある。
で、10行目で_XTAL_FREQを設定。設定する数は、マイコンの周波数。ASOOVU USBのマニュアルに製品仕様が書いてあって
内部動作周波数:48MHzと書いてある。ということで48000000を設定。
・・・あ、#defineの値を括弧でくくるの忘れてた。

20~25行目

LATB4をON/OFFする。僕はif~elseで書くけど多分別に~のビット反転使ってもいいと思う。たぶん。
LATBbits構造体や、先ほどでてきたPORTBやLATB、TRISBのレジスタなどはpic18f2550.hで定義されてる。

コンパイル

で、コンパイル
MPLAB X IDEのプロジェクト名を右クリックして、Buildを選択。
コンパイル結果はOutput欄に出力。
f:id:prizeout:20171217170238p:plain
BUILD SUCCESSFULLでビルド成功を確認。
次に、hexファイル(デバイスに書き込むためのファイル)の場所を確認。

書き込み

HIDBootLoader.exeを起動。「Hexファイル読み込み」で、先ほどできたhexファイルを読み込む。
ASOOVU USBのマニュアルに従って、デバイスのジャンパーピンをBOOT側に設定し、USBケーブルでPCにつなぐ。うまくいくとLEDが赤青にちかちかする。
そして「Hexファイル書き込み」。うまくいけば書き込み成功のメッセージが出る。

実行

バイスをPCから外し、ジャンパーピンをBOOT側からもう一方へ設定する。もう一度USBケーブルに接続する。
実行結果の動画(youtube)
めでたしめでたし

*1:XCのヘッダファイル群はインストールされたディレクトリ、デフォルトでは"C:\Program Files (x86)\Microchip\xc8\v1.44\include"にある

ASOOVU USBで遊んでみる(3)

その(3):データシートを見る

とりあえず今回は、LEDを光らせたり消したりすることを考える。

ポートの確認

ASOOVU USBのマニュアルの裏側に回路図が書いてある。(サイトからダウンロードもできる)
で、LEDの部分を見てみる。
f:id:prizeout:20171217121741p:plain
LED(青)は25番ポートとつながっているらしい。

データシートの確認

公式サイトからデータシートをダウンロードしてくる。
http://ww1.microchip.com/downloads/en/DeviceDoc/39632e.pdf
英語とか、426ページとか、中学以降英語は落ちこぼれで文章読んだりするのも苦手な僕は結構うんざりなんだけど*1
がんばって手抜き読みをしてみる。きっと図表が書いてあるにちがいない。。
可能な限り図表だけで読んでみよう。。

ピン配置図

pdfの4ページにピン配置図があった。
f:id:prizeout:20171217130346p:plain
25番ピンはRB4というらしい。

ブロック図

12ページにブロック図があった。
f:id:prizeout:20171217130942p:plain
RB4はPORTBにつながっているらしい。

ポート回路図

というわけで10章。IO Portの章。回路図を見る。
f:id:prizeout:20171217150310p:plain
三角形は3ステートバッファというものだと思う。論理回路:3ステートバッファ(1) | 東芝 半導体&ストレージ製品
制御信号に○がついてるからきっとNOTで、TRISラッチが0のときにDATAラッチからIOピンに出力があるらしい。
(ラッチはなんか値を保存しておくものだった気がする。なんか値を書き込んだらそのまま保持されるんだろう。)
ということでTABLE 10-3を見ると
f:id:prizeout:20171217152722p:plain
RB4はLATB4から読み込めるらしい。

初期化例

PORTBの初期化例が書いてあった。アセンブラなんか読めないが、この程度ならなんとなく理解。
f:id:prizeout:20171217153053p:plain
とりあえず理解に必要なのは上下の赤枠の中。真ん中のはコンフィグレーションビットの設定でしてあるからいらない。と判断。
上の部分はPORTBとLATBの0クリア。下の部分はTRISBに0xCFを代入。0xCFは2進法で書くと11001111だから、一番右を0番目、一番左を7番目として、4,5番目が0となっている。
コメントに、「RB4とRB5を出力に」とあるので、TRISBの該当ビットを0にすると出力なんだろう。

というわけで、やっとコードが書ける。
続く。

*1:だったら日本語訳見ろっていうんだけど、それはそれで敗北感が・・・

ASOOVU USBで遊んでみる(2)

その(2) :Configuration bitの設定

よくわからないけど、機械の設定っぽいことをするらしい。
本当はデータシートとか見ないといけないけど、そのうち詳しくなってみたい。

とりあえず今回は、マニュアルのサイト、あるいは書き込みソフトをダウンロードしたサイトから
適当なスケルトンソフトを落とし、中のヘッダファイルを見て真似してみた。

Production→Set Configration Bitsを選ぶ。
いろいろとあるので、とりあえず真似して設定。
f:id:prizeout:20171214010833p:plain
Generate Source Code to Outputボタンを押すと、アウトプットのコードができる。
これをコピーペーストでソースコードに貼りつけるみたい。

main.cにぺたぺた貼りつけるのもあるんだろうけど、僕はヘッダファイルを作ってそこに貼りつけた。

続く。

ASOOVU USBで遊んでみる(1)

その(1) :MPLAB X IDE プロジェクト作成

MPLAB X IDEを起動する。
File→New Project
Microchip EmbeddedからStandalone Projectを選択してNext
f:id:prizeout:20171214002435p:plain

今回使うICはPIC18F2550というものらしい。(マニュアルに書いてある)
というわけで、Advanced 8-bit MXUs (PIC18)からPIC18F2550を選択してNext
f:id:prizeout:20171214002432p:plain

Toolsのところはよくわからないけど、ネットで見た感じPICのときはPICkit3を選ぶらしい。
というわけでそうする。
f:id:prizeout:20171214002427p:plain

コンパイラはXC8
f:id:prizeout:20171214002424p:plain

最後にプロジェクト名を適当に決める。
encodingのところはWindowsはShift-JISなんかなということでそうした。今ならutf-8とかその辺なんだろうか。わかんないけど。
で、Finish
f:id:prizeout:20171214002420p:plain

これでプロジェクトは作成完了。
main.cがなければいかんだろうから、
Source Fileのところを右クリックして、New→main.c
f:id:prizeout:20171214002420p:plain

続く。

ASOOVU USBで遊んでみる(0)

その(0) :準備編

数か月前に買ったASOOVU USBというものをせっかくだからちょっとだけ起動してみようかと思ってやってみた。
ASOOVUシリーズ | Bit Trade One, LTD

まず、マニュアルに書いてあるサイトから書き込みソフトをダウンロードした・・・
のだが、僕のマシンのノートン先生がウィルスと判断し削除されてしまった。
どうしようかと思ったが、上にあげた販売元のリンクのサポートから書き込みソフトがダウンロードでき、そちらはウィルスでなかったらしく事なきを得た。
次に、
MPLAB- X IDE | Microchip Technology Inc.
ここからMPLAB X IDEとXC8をインストール。(以前インストールしてたが、最新版に更新した。)
また、今回遊ぶマイコンは16ビットマイコンだからXC16もインストール。
↑まちがい。PIC18F2550は8ビットらしい。でもなんかXC16を入れたらその後の設定がうまく通った気がする。

続く。

算数の問題

ちゃんと書ける日記がここしかないのでここで。
せっかくだからてふとか使ってみよう。

ツイッターみてたらこんな問題が流れてきた。
https://twitter.com/nekonyannyan821/status/915572712596168704

で、仕事帰りの電車の中で解こうとがんばってた。。

すべてのi (1 \leq i \leq n) で i番目のカードの数字がi \\
つまり 1,2,...n とカードの数字が並んだ場合は条件を満たす。これを基準に考える。\\
んで、nのカードのどこかのカードを入れ替えたn-1通りは、条件を満たす。\\
1からn-1までのカードで、任意の2枚を入れ替えた場合、\\
小さい数字のカードは条件を満たさなくなるが、\\
そのカードとnのカードを入れ替えたらまた条件を満たす。\\
というわけで_n C _2 = \frac{n(n-1)}2\\
任意の3枚以上を入れ替えたらきっと条件を満たすのは無理っぽいから\\
全部足して\frac{n(n+1)}2\\
が答えなんじゃなかろうか。

てなことを考えてたんだけど、
問題流した人がヒントというか答え出してて
1が入るのは2通り、そのいずれにも2が入るのが2とおり、・・・
って言ってた。
なんでだーって悩んでたら
3枚以上の入れ替えでも
1,2,3,4→2,3,1,4と1つずつくるっとずらすように入れ替えて、最後に一番小さな1と4を入れ替えたら
条件満たすやん、と、家かえってお風呂に入ってから思い立ったしまった。
もちろん3以上でも成り立つ。
で、条件満たすために入れ替えるのが「1つずつくるっとずらす」だけだとしたら
 1 + (n-1) + _n C _2 + _n C _3 + ... _n C _{n-1} \\
2項定理とかで 2^{n-1}通りじゃないか。
これはヒントと合致する。
ただ、入れ替えの条件が他ではダメだということを証明してないからなんか気持ち悪い。


で、なんかくやしい。もっと方法ないか。

 n = 2のとき 2通り\\
n = k のときa _k通りと仮定したとき、n = k+1のとき増える場合は\\
  1,2,...nの順に並ぶ場合の最後に{n+1}のカードを加えた場合の1通り\\
  上の場合に、{n+1}のカードと任意のカード1枚を入れ替えた場合、n通り\\
  1,2,...nの順に並んでいないカードの最後に{n+1}のカードを加え、 \\
  n番目のカードと{n+1}番目のカードを入れ替える場合、a _k - 1通り\\
だから・・・いやちょっとまて

1~nを並べたときに、条件に合わないiが一つだけある場合
をカウントせんといかんのじゃないか。

あまりに力押しで疲れてきた。うーんやっぱりあの2通りが何個分のがいちばんスマートだよなぁ。。
とりあえず今日は疲れたので寝る。