« オリンパス OM-D E-M1mk2の充電器の充電表示ランプを判別その2 | トップページ | Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMを使おう »

2020年8月11日 (火)

14pinのAVRマイコン、ATtiny24が動かん!

しょうもないミスをしてしまって、解決まで悩みまくった・・・

試作回路のテスト用ジグの製作。
周波数1kHzで、デューティ0%~99%のパルス波が欲しい
という要求仕様。
設定はロータリーDIP SWが2桁。
使ったのは14ピンのATtiny24で、こんな回路に。

11_20200811093001
6.4MHzの水晶をクロックを1/64して100kHzを得、
これを1/100して1kHz。
AVRマイコンのタイマー0をFAST PWMモードにして
DSWでの設定00で全区間L~99%のH/L波形を出します。

※ISPのライン、PA4、5、6に入れてある抵抗は
 DSWオン時(GNDにつながる)でもISPできるように。

こんな基板に。
とりあえず、プラケースに入るようにして行方不明に
なりにくく。
この手のテストジグ、裸の基板だと消息不明が多発・・・

12_20200811093001

ところがです。
・・・プログラムが動いてくれない。
イニシャルはしてくれるのですが、main()の
永久ループに入らない。 なぜ?

AVRマイコン、「C」で書く時はこんなスタイルです。
  ※Arduinoならsetup()とloop()に分かれますが。

// 初期化ルーチン
void ioinit(void)
{
  あれこれ
}

// main処理
int main(void)
{
 ioinit();  // 初期化処理を呼び出して
 while(1){    // 永久ループ
   あれこれ  // メインでの処理★
 }
}

初期化処理までは動くんだけど、★のメイン処理が
動かないという現象が起こったんです。

さらに・・・
テストルーチンをioinit()内に入れこんで、ioinit()
から抜け出ないようにしたら、ちゃんと動くんです。
なぜにwhile(1)で永久ループしない?

この追求に手間取りました。
でも、原因は単純な話。

通常、AVRマイコンの「C」の処理は、
・ステータスレジスタのクリアとスタックポインタの初期化
・内部データの生成
・BSSエリアのクリア
これを自動(ユーザーは意識しなくて良い)で行った後、
main()をサブルーチンコールします。

そして↑の私の書き方だと、main()の中から
ioinit()をサブルーチンコールして、その後に
while(1)の永久ループが回ります。

さて、トラブった原因・・・

この時、コンパイルはATtiny44を想定して行っていました。
ところが・・・
ターゲットの回路に入っていた実際のチップはATtiny24

同じ14ピンなもんで、チップのマークをちゃんと読まないと
判断できません。

そして、I/Oレジスタまわりの構成は同じです。
だからioinit()は動いて、それなりの動作をし始めた
のです。 (だからややこしかった)

何が問題になったのか・・・
RAMのサイズでした。

小さいプログラムですんで、ROMは小さくても大丈夫。
RAMもほとんど使っていないんで余裕のはずなんですが、
Cコンパイラが設定するスタックポインタがtiny24と
tiny44では異なります。
  (RAMの最終アドレスを設定する)

コンパイラがtiny44のつもりで設定した場所、tiny24の
ここにはRAMがありません。
だもんで、ioinit()を呼んだ戻り先が喪失してしまい、
プログラムが暴走。
いつまで経ってもwhile(1)のループにたどりつけません。

こんなスカタンな話、生半可にI/O回りが動き始めてたんで、
解決に手間取りました。


※豆知識
AVRマイコンのデータシートを見てもらえれば、ステータスレジスタと
スタックポインタへの処理が、Cコンパイラの「大きなお世話」で
あることが分かるかと。

AVRマイコン、リセット起動で
 ・ステータスレジスタはゼロに初期化。
 ・スタックポインタはRAMENDに初期化。
されます。

それをCコンパイラで書かれたプログラムがなぞるわけです。
スタックポインタはチップに乗ったRAMサイズに合わせて
自動的にセットされるので、チップのRAMサイズが変わっ
ても(小さくなるチップを使っても)今回のようなサブルーチンの
リターンアドレスが喪失するような事態は発生しません。

アセンブラでプログラムを書くなら、この初期化処理はしません。
リセットによる初期化を信じます。


※制御プログラム:ダウンロード - 1khz_duty.zip

 

|

« オリンパス OM-D E-M1mk2の充電器の充電表示ランプを判別その2 | トップページ | Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMを使おう »

トラブル遭遇」カテゴリの記事

電子工作」カテゴリの記事

ツール」カテゴリの記事

コメント

68marukuです.ご無沙汰しております.
店主様でもこのような事が有るのですね.
私も最近ハマった事があるので書き込みさせていただきました.
以前店主様と柴田様の取りまとめにより頂いた部品で,コンパクトなトラッキングレギュレータ(±18V,200mA)が完成しました.
本当に有難う御座いました.写真でお見せできないのが残念です(自画自賛).
uA723は正側の制御に,ハンパな(もとい,スペシャルな)値の抵抗は分圧などに,MSM561は7seg 9桁のセグメントドライブに使用しました.
ここでAD及び表示制御用に愛用の\100MCU R8C/M12Aを使用してトラブルに遭遇.
まったく動作せず.
pin数の関係でreset用pinをI/Oとして使用したのはいいのですが,使い方に問題が....
マニュアルを熟読すると
「内部resetが終了した時点で本pinがLだとresetは継続します。Hが供給されるまで解除されません。」
今回はOutPut設定しデジトラを接続していたので完全にNGでした.pinを入れ替えてやっとOK.
不注意だった私の責任ですがハマった人も多いのではないでしょうか.pin説明のtopに書いておいてくれよ~
長文失礼しました.


投稿: 68maruku | 2020年8月11日 (火) 16時26分

R8Cのリセット、そんな仕掛けがあるとは知りませんでした。
ということは、
・起動時にH/Lが不定な入力ポートとは共存できない。
・プルダウンされた抵抗がつながる出力ポート(NPNデジトラ)もダメ。
・プルアップされた出力ポート(PNPデジトラでLアクティブ制御)ならOK。
ということになるのでしょうか。

昔々・・・8pinのPIC16F675を使ったメッセージキーヤーで、スイッチ入力を増やすのにRESET(PICなんでMCLR)を使いましたなぁ。

投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年8月12日 (水) 07時45分

68marukuです.
最初にこの仕様を見たときはトンデモ仕様と思いましたが,よく考えると
Fuseを持つAVRと違って,R8Cはプログラムが走って機能が決定するまでは
RST端子はデフォルトのままなのは当然なわけで,うっかりした私の凡ミス
でした....

投稿: 68maruku | 2020年8月16日 (日) 22時29分

コメントを書く



(ウェブ上には掲載しません)




« オリンパス OM-D E-M1mk2の充電器の充電表示ランプを判別その2 | トップページ | Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMを使おう »