こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

H8/3052 クロスコンパイラ環境下でのsprintfの使用について

実務訓練でH8を用いて測定システムを開発しています。
今、H8に接続したセンサの値を測定しA/D変換した値を、フーリエ変換し、その結果をシリアル通信のソフト(ハイパーターミナル)などで表示できるようするために、その値を文字コードに変換して送るようにしているところです。
その変換した値がどのくらいなのかわからないので、場合わけ等が必要なのかと思っていましたら、会社の方にsprintfを使えばいいと言われました。
それは気づかなかったと思って、使ってみたら動きませんでした(^^;
型のあわせ方とかが間違っているのかな?

char buf[100];
sprintf(buf,"%f",a[k]); //a[k]はフーリエ展開した係数の値(double)
for(i=0;i<100;i++){
SCI_OUT_d(buf[i]); //SCI_OUT_dはシリアル送信関数
}
なにかおかしいところありますか?
ためしに
char buf[100];
float DFTa;
DFTa=(float)a[k];
sprintf(buf,"%f",a[k]); //a[k]はフーリエ転換した係数の値(double)
for(i=0;i<100;i++){
SCI_OUT_d(buf[i]); //SCI_OUT_dはシリアル送信関数
}
でfloat型にしてみてもそこでとまってしまいました。

何かH8のsprintfの実装についてわかることがある人がいましたら回答お願いします。

投稿日時 - 2008-01-29 10:28:42

QNo.3723999

すぐに回答ほしいです

質問者が選んだベストアンサー

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( '.' );
}
}

とりあえず、使い捨てのテストコードくらいでしか使えませんけど、ライブラリはなくてもなんとでもなる例として。
コントローラで浮動小数点を扱いたくないなぁってのが真っ先に出る本音だったりしますが。

投稿日時 - 2008-01-31 02:18:17

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

unsigned long dw = (unsigned long)( ( b[d] + 0.5 ) * 1000 );
これもNGでした。

unsigned long dw = (unsigned long)( b[d] * 1000 + 0.5 );
四捨五入になってませんでしたね、、、。

回答控えるべきですね。板汚しすいません。

投稿日時 - 2008-01-31 02:41:11

お礼

いえいえ、とんでもない!とても参考になります!

そうですね、スタック以上っていう問題は一回つまづいたことがあって、そのことに気づくのにすごく時間がかかりました。
今のところ、RAMの容量的には、外部の領域を使用しているので、測定ポイントの数がこれ以上増えない限り大丈夫だと思います。
bugbugさんのサンプルみたいな感じでやったらできましたね。ついに完成した感じです。(ただ四捨五入はしてませんが・・・)でも実務訓練もあと1ヶ月くらいのところでようやく目標に達成しました。bugbugさんのおかげと言っても過言ではありませんね(笑)

投稿日時 - 2008-01-31 15:32:41

ANo.3

あー スイマセン。寝る前でボケてました。
SCI_OUT_d( dw / ( i * 10 ) + '0' );

( i * 10 )の所は 10のi乗と読み替えて下さい。

ソースで書くと肝心な説明以外のところのフォローの為グダグダになりそうなのでで避けときます。

投稿日時 - 2008-01-31 02:30:34

ANo.1

300Hコアの環境が手元にないので未確認ですが、ライブラリの出力部に問題があるみたいですねぇ
参考サイト(適当に覗き見しただけなのでVer未確認)
http://d.hatena.ne.jp/ntaka206/20070515/1179275185
http://watson8.com/initinit/

代換の関数を自作するか、バイナリで吐き出すか、ソースはあるでしょうからライブラリを直しちゃうか。
とりあえず結果だけ取得したいなら、私ならCVS形式で吐き出してホスト側でエクセルでも使って目的のテーブルを取得すると思います。

符号ビット, バイアス付き指数, 仮数\n
みたいな感じで。

ご参考までに。(あんまりアドバイスになってないような気も、、、)

ちなみに下段のサンプルはfloatになってなさげですね。

投稿日時 - 2008-01-29 23:57:59

お礼

本当に詳しいですね!!
その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が小数点以下部分に分かれると思うんですよね。
で、はじめに負数の場合は絶対値で計算をして-をあとでつけてあげればよいのではないかと?
どうでしょうか?

投稿日時 - 2008-01-30 11:20:15

あなたにオススメの質問