- ベストアンサー
H8/3052 クロスコンパイラ環境下でのsprintfの使用について
- H8を用いた測定システム開発において、文字コード変換を行うためにsprintfを使用しようとしているがうまくいかない。型のあわせ方が間違っている可能性がある。
- sprintfを使ってフーリエ展開した係数の値を文字列に変換し、シリアル通信で送信しようとしているが、正しく動作しない。
- sprintfの実装について詳しい情報が求められている。H8のsprintfの挙動について知っている方は回答をお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
RAM上デバッグの環境でライブラリをやたに組み込むのは難しい時が多々ありますね。 20k, 30k 簡単に増えちゃいますので。 それとサンプルを見て思ったのはbufスタックに乗せてないかな?と言う事でした。 組み込み系ではスタックの伸張が容易にトラブルを引き起こしますので サイズの大きい配列などは静的変数としてRAM上に確保したほうが安心できるかな。 一応、for(i=0;i<100;i++){も危なそうな、、、 SCI_OUT_dの実装が見えないので断言できませんが。 せめて for(i=0;buf[i]!='\0';++i){辺りの方がいいと思います。 char *p = buf; while( *p ){ SCI_OUT_d( *p++ ); } の方が私は頭使わず読めるので楽ですが、好みの問題になってしまいますね。 > 小数点4桁まで表示したいときに という縛りであれば、 unsigned long dw = (unsigned long)( ( b[d] + 0.5 ) * 1000 ); としてしまえば、後は整数のまま好きなように扱えばよいかと。 (簡易表記の為、正数のみ。) 極端な力技で可読性もひどいですが、ニュアンス的には以下のような扱いが目的です。 int i; for ( i = 3; i >= 0; --i ) { SCI_OUT_d( dw / ( i * 10 ) + '0' ); if ( i == 3 ) { SCI_OUT_d( '.' ); } } とりあえず、使い捨てのテストコードくらいでしか使えませんけど、ライブラリはなくてもなんとでもなる例として。 コントローラで浮動小数点を扱いたくないなぁってのが真っ先に出る本音だったりしますが。
その他の回答 (3)
- bug_bug
- ベストアンサー率78% (36/46)
unsigned long dw = (unsigned long)( ( b[d] + 0.5 ) * 1000 ); これもNGでした。 unsigned long dw = (unsigned long)( b[d] * 1000 + 0.5 ); 四捨五入になってませんでしたね、、、。 回答控えるべきですね。板汚しすいません。
- bug_bug
- ベストアンサー率78% (36/46)
あー スイマセン。寝る前でボケてました。 SCI_OUT_d( dw / ( i * 10 ) + '0' ); ( i * 10 )の所は 10のi乗と読み替えて下さい。 ソースで書くと肝心な説明以外のところのフォローの為グダグダになりそうなのでで避けときます。
- bug_bug
- ベストアンサー率78% (36/46)
300Hコアの環境が手元にないので未確認ですが、ライブラリの出力部に問題があるみたいですねぇ 参考サイト(適当に覗き見しただけなのでVer未確認) http://d.hatena.ne.jp/ntaka206/20070515/1179275185 http://watson8.com/initinit/ 代換の関数を自作するか、バイナリで吐き出すか、ソースはあるでしょうからライブラリを直しちゃうか。 とりあえず結果だけ取得したいなら、私ならCVS形式で吐き出してホスト側でエクセルでも使って目的のテーブルを取得すると思います。 符号ビット, バイアス付き指数, 仮数\n みたいな感じで。 ご参考までに。(あんまりアドバイスになってないような気も、、、) ちなみに下段のサンプルはfloatになってなさげですね。
お礼
本当に詳しいですね!! そのCVS形式を吐き出す方法もvfprintf関数などを使うんですよね? なんか今のところできない原因としては、sprintf関数を使用した場合に、容量が大きすぎて、3052の絶対アドレス16ビットというROMエリア(絶対アドレスを指定するときに使うのかな?よくわかりませんが)が 0x0000~0x7fffまでで、sprintfを使うと、sprintfはvfprintfなどほかの関数郡をやたらともってきてしまいますから、これをオーバーしてしまっています。 そのせいでうまくうごかないような。。。 実際、sprintfは使えるみたいなんですよ。 でも表示するときに小数点4桁まで表示したいときに、 b[0]=0.0000 b[1]=0.00 b[2]=0.0 見たいな感じになっています。なんか、小数点と0だけ表示できるみたいなんですよね。 GDBSTUBとかの関係でsprintfがあるとデバッグできないのでどうなっているのかよくわかりませんが。一応使わない方向で検討してみました。 方法としては、まず、整数部と小数点以下部分に分けてそれをひとつずつ表示させるみたいな。 if(b[d]<0){ b[d]=b[d]*-1.0; } Ib=(int)b[d]; Fb=b[d]-(double)Ib; こうしてあげれば、Iaが整数部で、Faが小数点以下部分に分かれると思うんですよね。 で、はじめに負数の場合は絶対値で計算をして-をあとでつけてあげればよいのではないかと? どうでしょうか?
お礼
いえいえ、とんでもない!とても参考になります! そうですね、スタック以上っていう問題は一回つまづいたことがあって、そのことに気づくのにすごく時間がかかりました。 今のところ、RAMの容量的には、外部の領域を使用しているので、測定ポイントの数がこれ以上増えない限り大丈夫だと思います。 bugbugさんのサンプルみたいな感じでやったらできましたね。ついに完成した感じです。(ただ四捨五入はしてませんが・・・)でも実務訓練もあと1ヶ月くらいのところでようやく目標に達成しました。bugbugさんのおかげと言っても過言ではありませんね(笑)