08/07/24 15:00:41 KSyZ4cHL
PIC CでPIC16系用の割り込みルーチン書いてるんだが、変数、volatileつけようが
atomicじゃないんだな。これ、ひどいな。
実験はしていないが、割り込みルーチンでvolatile int型の変数を0x7fffからインクリメントしたら、
割り込みルーチンの外でその変数を読み出すと0x7fff→0x7f00→0x8000ってなるんだろうな。
atomicにアクセスしたいなら一時的に割り込み禁止にするべきなのか?
di()にしておいて、ei()に戻したときに、この割り込み禁止時間内に来たUSARTのデータなんかは、
ei()にした瞬間割り込みがかかって、(1バイトだけなら)取りこぼさないと理解していいのか?
555:774ワット発電中さん
08/07/24 18:33:57 1aQDkzlx
はい露光失敗したー
いつになったらライタ完成すんね!!!
556:774ワット発電中さん
08/07/24 18:59:31 KSyZ4cHL
俺、554だがdi()で割り込み禁止にすると普通にUSARTの文字とりこぼすな。
タイマー割り込みだけ禁止か、タイマー一時停止させてもいいが、そうすると
その期間タイマーがわずかにずれていくんだよな…。
idle中に頻繁にtimerの値を取得して、タイミングを調整するようなプログラムなので、
これもまずい…。
そうなると割り込み中でincrementするtimerを8bitにするとか(実用性に乏しい)、
割り込みの外からtimerの値を参照するときは2回アクセスして正しそうな値のほうを採用するとか。
何にしても割り込み中でインクリメントしているint型の変数の値を割り込みの外の関数から
取り出すだけで一苦労だな、これ。
557:485
08/07/24 19:00:42 ZlAQhDcI
>>554
PIC Cは触ってないので、的外れかもしれないけど、intって1バイトじゃないの?CCS Cだと1バイト。
558:774ワット発電中さん
08/07/24 19:22:45 U2Iff1oI
>>554
まてまて何か話が妙じゃないか?
メインでインクリメント途中に割り込み入る場合のことか?
あと一時割り込み禁止の場合も短時間ならOKだろ。
USARTもダブルバッファだし 1byte分程度ならなんとか・・・
まぁ no waitで連続受信だと、そうも言ってられないが。
559:774ワット発電中さん
08/07/24 19:29:07 U2Iff1oI
あ、スマソ
メイン側の参照途中に割り込み側で変数変化の場合だな。
まぁ一時禁止はやむを得ないだろ。
割り込み処理は極力短くすりゃ問題なさそうだが。
560:774ワット発電中さん
08/07/24 19:35:11 KSyZ4cHL
>>557
PIC Cはintは2バイトなのです。
>>558
> メインでインクリメント途中に割り込み入る場合のことか?
逆です。1msのone shot timerで割り込みをかけて、割り込み処理中にインクリメントするのです。
ところがこの変数が2バイトなので、atomic性がないのです。
具体的に書けば、割り込みの外の関数内で
my_timer = timer;
のような代入文があるとして、timer = 0x00ffのとき、この代入の下位バイトが代入された瞬間に
タイマ割り込みがかかり、timerのインクリメントが行なわれた場合、timer = 0x0100になりますが、
その割り込みハンドラから抜けて、上位バイトをmy_timerに代入することになるので、
my_timerの値は0x01ffになります。
> あと一時割り込み禁止の場合も短時間ならOKだろ。
それがdi()~ei()する実装だと、文字をぼろぼろ読みこぼしました。
原因はよくわかりません。タイマを一時的に停止させる実装なら読みこぼす問題はないのですが
Idle中につねにtimerの値を監視したいため、頻繁にtimerの値を参照しなければならないので
5%ぐらい進みが遅くなってタイマとしての使い物にならなくなってくるのです。
561:774ワット発電中さん
08/07/24 19:44:33 KmG60qpi
>>560
2回連続で読みだして、同じだったら正しいってことにしといたら?
同じじゃなければ、次の読みだした値を正しいものとする。
562:774ワット発電中さん
08/07/24 19:44:51 KSyZ4cHL
>>559
レスが入れ違いになりました。すみません。
> まぁ一時禁止はやむを得ないだろ。
なのですが、>560で書かせてもらったように、タイマとしての精度に問題が出てくるので
割り込み禁止は今回の場合、使えないのです。
そこで、次のように解決しました。
割り込みルーチンのなかではtimerはインクリメントしかしないので
割り込み外ではこの値を連続で2度読みして、
1) 2つの値が同じ→問題なし
2) 2つの値が1違い→大きいほうの値が新しい値なので大きいほうを採用。
ただし0xffffと0x0000なら0x0000のほうを採用。
3) 2つの値の差が0xffなら、上位バイトは大きいほう(ただし0xffよりは0x00が
大きいと扱う)を採用し、下位バイトは0とする。
ただ、実は、この変数はintではなく、unsigned longでして、4バイトなので
上のアルゴリズムの4バイト版を作らなければならず、結構面倒なのです。
レジスタが8bitなのが本当に恨めしい…。
563:774ワット発電中さん
08/07/24 19:45:50 KSyZ4cHL
>>561
なるほど!!! >562 を書いた自分が馬鹿みたいです…。
564:774ワット発電中さん
08/07/24 20:01:06 QGZsu7Rh
無事に解決したようでなりよりです。
volatile は最適化抑止のための指定なので、atomicかどうかとは関係ないですよ。
565:774ワット発電中さん
08/07/24 20:14:44 xNPNFghc
インクリメントで問題が発生するのは桁上げが発生するときで、
最下位がFFHから00Hになったときだから、最下位がFFHの時には
二度読みするなんていう実装したりしてな。
>それがdi()~ei()する実装だと、文字をぼろぼろ読みこぼしました。
>原因はよくわかりません。
こういうのを放置して、とりあえず動いたからいいや・・なんてやってると
後で痛い目をみたりするんだよな。
遊びでやってるだけならどうでもいいけど。仕事だったら許されないな。
566:774ワット発電中さん
08/07/24 20:19:15 U2Iff1oI
全体がいまいち掴めないので単なるアドバイスとして聞いてくれ。
タイマー精度の件だが・・・
割り込みでTimer値の再set時に += で補正する手もある。
但し受信も割り込み処理なら高頻度で割り込み入ると影響大きそう。
ともかくCCP使えるようなら Timerオーバーフロー割り込みの代わりに
Special Event Trigger使ってみたらどう?
Timer値の範囲が違ってくるので要注意だが、
たぶんオーバーフローより扱いやすいと思う。
567:774ワット発電中さん
08/07/24 20:29:11 KSyZ4cHL
>>565
> 最下位がFFHの時には二度読みするなんていう実装したりしてな。
なるほど!!
> 遊びでやってるだけならどうでもいいけど。仕事だったら許されないな。
もちろん、そうです。私のほうはまだざっくりとしか調べてない状態です。あとで詳しく調べ直します。
>>566
Special Event Triggerというのを初めて知りました。面白そうな仕組みですね。
568:774ワット発電中さん
08/07/24 21:04:01 pZ/KKwSE
>>565
> インクリメントで問題が発生するのは桁上げが発生するときで、
> 最下位がFFHから00Hになったときだから、最下位がFFHの時には
> 二度読みするなんていう実装したりしてな。
そう言う実装にすると、平均的には下位バイトのチェックだけで
済むから効率的だけど、最悪時は 下位バイトのチェック +
前回との比較 + 再読み込み となってしまう。
組み込み用途だと最悪の状態でも正しく動作することを求められ
ることが多いから、そう言う実装はあまり勧められない。
逆に人間相手のソフトなら、たまにちょっと遅くなっても平均的
に早いほうがいいのでそう言う実装もありだ。
569:774ワット発電中さん
08/07/25 00:17:26 a59gaSgu
>>554
変数へのアクセスがatomicにならないのはPIC Cに限定された話じゃないよ。
atomicなアクセスはC言語の仕様に含まれていないから、C言語の標準の範囲内で
プログラムを書く限り、どのCコンパイラを使ってもatomicアクセスの保障はない。
atomicアクセスが必要なら、割り込みを禁止するか、atomicであることが
保障されているアクセス手段でセマフォを作ってアクセスバリアを作るしか
ない。
>>565
「最下位が特定の値のときに二度読み」だと>>568が指摘するような
レイテンシ差が発生する可能性があるので、必ず二度読みするのがお勧め。
これだとレイテンシ差が発生しないようにコードを書くのが容易。
570:774ワット発電中さん
08/07/25 00:29:25 YPd9qSBD
PICで複数(20個とか)のLEDをそれぞれ違う輝度でPWM駆動することは可能でしょうか?
どう考えてよいのかわかりません。
571:774ワット発電中さん
08/07/25 00:37:11 a59gaSgu
>>570
条件次第だが、可能。
20個でどう考えていいのか分からんのなら、まず1個で考えろ。その次は2個だ。
どこまでなら分かるんだ?
もしかして スレリンク(denki板:420番)
の続きか?
572:774ワット発電中さん
08/07/25 01:08:45 Y5E1/Skm
ハードでのPWMは1個しかないけど、ソフトでやればOK
ループでもタイマ割り込みでもいいけど一定間隔で
{
カウンタを+1する(カウンタが上限いったら0にする)
LEDの輝度を先ほどのカウンタと比較して
大きければ点灯、小さければ消灯する(必要なLED数だけ行う)
}
例えばカウンタが上限255なら、輝度128なら Duty50%で点灯する
64ならDuty25%で点灯する。
問題は周期がハードに比べて遅くなる。
573:774ワット発電中さん
08/07/25 01:47:13 JeP47Zwo
>>569
PIC用のコンパイラで使えるかは知らないけど
一応、Cの仕様にはsig_atomic_tという型があって、
・最低8ビットで
・volatile付きで宣言されているとき、代入がatomicである
ことになっているよ。
574:569
08/07/25 04:20:46 a59gaSgu
>>573
あーすまん、確かにそのとおりだ。>>569は言葉足らずだった。
言わんとしていたことは「型によらずatomicであること」の保障はない、だ。
>>569は「変数へのアクセス」を「任意の変数へのアクセス」とでも
読み替えてくれ。
575:774ワット発電中さん
08/07/25 04:36:36 cia2XHWk
知ったか乙
576:774ワット発電中さん
08/07/25 07:36:47 uD0mpU5s
PICKit2 Starter Kitについてるデモボードではあらかじめくっついてるマイコンにしか書き込みできないのでしょうか?
577:774ワット発電中さん
08/07/25 08:41:36 a59gaSgu
PICkit 2 Starter Kitに付属のデモボードの名称は
PICkit 2 Low Pin Count Demo Board
そのマニュアルが
Low Pin Count Demo Board User's Guide
URLリンク(ww1.microchip.com)
その中の「1.3 Devices Supported by the LPC Demo Board」に
対応チップの一覧がある。記載されているのは
PIC12F508 PIC12F629 PIC12F635
PIC12F509 PIC12F675 PIC12F683
PIC12F510
PIC16F505 PIC16F630 PIC16F684
PIC16F506 PIC16F676 PIC16F688
PIC16F685 PIC16F689 PIC16F785
PIC16F687 PIC16F690
マニュアルの改訂のペースは遅いので、対応チップはもっと多い可能性もある。
578:774ワット発電中さん
08/07/25 11:03:22 yzuFq62G
PICKit2なんですが、100ピンのやつも配線がわかれば書き込めますか?あったら教えて
579:774ワット発電中さん
08/07/25 12:11:53 3r9w7ge7
配線が分かって、なおかつ正しく配線すれば書き込める。
580:774ワット発電中さん
08/07/25 12:34:21 ILMNW3aV
質問
16F877Aを使用しての質問なんですが
パルスの周期(パルス間の時間計測)をキャプチャ機能
で測定しようと思ってます
(設定は立上エッジで割込み)。
PICの動作としては割込が発生した時点でキャプチャ
レジスタを読めばエッジ間の時間計測結果が分かるという
ことで良いのでしょうか?
581:774ワット発電中さん
08/07/25 12:41:32 D8jwVZuH
>580
そうだよ。差をとるんだけどね。
582:774ワット発電中さん
08/07/25 14:03:04 a59gaSgu
>>580
「割り込み発生時点でキャプチャ」じゃなくて「キャプチャ時点で
(割り込み許可になっていれば)割り込み発生」ね。
割り込みが発生するか否かによらず、キャプチャは行われる。
583:774ワット発電中さん
08/07/25 14:38:35 D8jwVZuH
「割込が発生した時点でキャプチャ レジスタを読めば」
584:774ワット発電中さん
08/07/25 15:08:08 a59gaSgu
ぐはっ・・・なんという早とちり・・・
585:774ワット発電中さん
08/07/25 16:07:14 YVnMtuoI
どんまいw
586:774ワット発電中さん
08/07/25 17:25:07 yzuFq62G
PICKit2ProgrammerでdsPICのHEX読み込むと
Warning:Some configuration words not in hex file.
Ensure default values above right are acceptable.
書き込もうとすると
Programing failed at Program Memory address 0x000000
って出る、たすけて!
#include "p30f4012.h" //4012のヘッダファイルの読み込み
_FOSC(CSW_FSCM_OFF & EC_PLL8); //EC PLLx8=80MHz, Failsafe off
_FWDT(WDT_OFF); //WDT(ウォッチドッグタイマ)オフ
_FBORPOR(PBOR_ON & MCLR_EN);
_FGS(CODE_PROT_OFF); //コードプロテクトオフ
#define CLOCK 80
int main(void){
TRISC=0x8000;
while(1){
LATBbits.LATB0 = 1;
asm("NOP");
LATBbits.LATB0 = 0;
asm("NOP");
}
}
587:774ワット発電中さん
08/07/25 17:28:21 HC8aQdZT
エンコーダやD/A変換のように値が上下するものは
・変換中フラグON
・データ取り込み
・変換中フラグOFF
として、データ参照側は変換中フラグONなら読まない。
>>569
これがセマフォというやつでいいですか?
588:774ワット発電中さん
08/07/25 18:50:55 mz9d4CFu
値を読み込むシステムコールを用意して、ソフトウェア割り込みの中で読む
589:774ワット発電中さん
08/07/25 21:00:38 uD0mpU5s
>>577
ありがとうございます。
恥を忍んで聞きますが、別のチップに書き込むにはデモボードにあらかじめついてるやつを一旦取り外すんですよね?
なんか外れそうな気がしないのですが。
590:774ワット発電中さん
08/07/25 21:20:44 yzuFq62G
もしかして
URLリンク(www.geocities.jp)
ってdsPIC無理なの?8000円・・・・・・・
591:587
08/07/25 21:24:48 Lj4POHjO
>>588
ありがとうです。リアルタイムOSの技術なんですね。
>>589
Starter KitはICソケットなので簡単に外れるよ。
PICKit2と基板を離して、6ピンのコネクタに別の基板orPICをつなぐ方法もある。
592:774ワット発電中さん
08/07/25 21:38:53 D8jwVZuH
>>590
dsPIC用はピンアサインが違う。
593:774ワット発電中さん
08/07/25 21:46:21 yzuFq62G
まじかよ!やっと基盤焼けたのに・・・もう今日はダメだ・・・・・