
PIC18F14K50のマイコンでPCとUARTで通信するように、ソフトを作成中ですが、なぜか、送信のためにマイコンの変数P[1]-[24]にある1バイトの数値を16進数文字列に変換し始めると、変数に入っている数値が0になってしまいます。
原因のわかる方、0にならない対処法を教えて下さい。
開発環境はMPLABX XC8で行っています。
以下に送信部分のソースを示します。
if(PP){ // PPが1で変換、送信
Txdata[0] = '\0'; //送信文字列クリア
strcat(Txdata,"Z");// 文字列先頭に"Z"を挿入
if(P[1]<16){strcat(Txdata,"0");}
sprintf(str, "%x",P[1]);//P[1]を16進に変換
strcat(Txdata,str);//Pa\r\nを付け加える
if(P[2]<16){strcat(Txdata,"0");}
sprintf(str, "%x",P[2]);strcat(Txdata,str);
if(P[3]<16){strcat(Txdata,"0");}
sprintf(str, "%x",P[3]);strcat(Txdata,str);
--- 中 略 ----------
if(P[23]<16){strcat(Txdata,"0");}
sprintf(str, "%x",P[23]);strcat(Txdata,str);
if(P[24]<16){strcat(Txdata,"0");}
sprintf(str, "%x",P[24]);strcat(Txdata,str);
strcat(Txdata,"\r\n");
strOut(Txdata);//送信
Txdata[0]='\0'; PP=0;END=0;}
//**** 文字列送信関数 ****************************
void strOut(char *str){
while(*str){
while (!PIR1bits.TXIF); //送信終了待ち
TXREG = *str++; } } //文字出力しポインタ+1
A 回答 (7件)
- 最新から表示
- 回答順に表示
No.7
- 回答日時:
%x は「unsigned int 型の引数を 16進で出力する」書式指定だから, 対応する引数はせめて unsigned char であってほしい. つまり P を
char P[なんとか];
のように定義しているなら「char が符号なしである」ことを確認しなきゃいけない (plain char が符号付きか符号なしかは処理系定義).
unsigned char 型の引数に対応するなら書式は %02xhhx とするのが今の ISO C としては正しいのだが, 処理系が対応してるかなぁ.
あぁ, %02x だと
・最低 2桁
・不足分は 0 付加
なので, 「絶対に 2桁になる」という保証はないっす.
回答ありがとうございます。記入していませんでしたが、P[]は0-255に制限しておりますがそれでも2桁以上になりますか?また、それにより、0に変化しますか?P[]に値が代入されるときに、設定がおかしくて0になるのであれば、わかりますが今回0に変化するのはP[]からほかの変数に代入するときに発生しています。P[],str,Txdataの変数の設定がまずいとして、P[]からほかの変数に代入した場合でも、P[]は変化するのでしょうか?
No.6
- 回答日時:
あと…
>if(P[1]<16){strcat(Txdata,"0");}
>sprintf(str, "%x",P[1]);//P[1]を16進に変換
>strcat(Txdata,str);//Pa\r\nを付け加える
としなくても、
sprintf(str, "%02x",P[1]);
でP[1]が5だったら"05"になるかと思われますよ。
ライブラリの実装にもよりますけど。
# そういう指定もできないヘタレ実装ならunsigned charから16進数文字列2桁に変換する処理を自前で作るべきかと。
了解です。ところで今回の私の質問はそこを改善すれば、解決するということですか?
行ってみましたが、かわりませんでした。なぜですか?
No.5
- 回答日時:
>strとかTxdata等にサイズが小さい場合、P[]が0になってしまう可能性がありますかね?
バッファオーバーフロー/バッファオーバーランとなれば破壊する可能性はあるでしょう。
>ご指摘の記述でも送信バイト数はふえないのでしょうか?
意図しないサイズで出力される。
というのを防げます。
コンパイラに依存しますがint型が16bitだった場合、かつ明示しない場合にsigned intとして扱われる。という状況だったときに
P[1]に255が入っている場合に
sprintf(str, "%x",P[1]);
でstrに"ffff"が入るかも知れません。
P[1]の11111111bが符号拡張で1111111111111111bに。
16進数文字列への変換が指定されているのでffffに。
# 当然文字列なので、char str[4]には収まりませんのでめでたくバッファオーバーラン成立となります。
>変化するのはP[ ]のマイコン内の変数で
ちなみにP[]はどのような?
P[0]が出てこないのは何か理由あるんでしょうか?
>送信側にデータを吐き出す変数が0になっています。
で、「if(P[24]==0){LED=1;}で調べました」なんですか???
No.4
- 回答日時:
変数 P の定義は char型でしょうか?
サイン型の変数を sprintf の引数を指定し、その値がマイナスの数値である場合 "%x" での変換結果の桁数が 8桁になります。 (char型=1byteの変数であっても)
よって、char str[4] (4byte)、char Txdata[60] (60byte)でも十分なサイズではありません。
少なくとも str は 8+1=9byte 必要で、Txdata は (1+8) x 24+1=217byte 必要です。
("%x"を"%02x"などとすれば、必ず2桁分しか生成されないと言う方もいますが、これは間違いです)
回答ありがとうございます。
P変数は unsigned char P[30] =0; で宣言しています。
因みにP[]もstrも0-255の1byteで制限をかけて、使用するようにしているつもりです。PC側から送信するデータへも制限をかけています。このデータは制御に使用するので、EEPROMに書き込んで使用するため、1変数1アドレスに書き込めるように扱っているつもりです。
No.3
- 回答日時:
もう少し全容がわかるソースコードが必要ですが、そのような現象の一般的な問題はバッファーオーバーフローが原因であることが多いです。
変数 Txdataとstrはどのように定義していますか? これらの変数のサイズが小さいことによる問題の可能性を疑います。
回答ありがとうございます。今回の問題は送信側なのですが、バッファーオーバーフローが発生するのでしょうか?
また、char str[4]; 4byte char Txdata[60]; 60byte 取っています。 strは2byte,Txdataは50byte程度と思いますが?
そして、変化するのはP[ ]のマイコン内の変数で、ソース内を検索しても、書き換える部分が存在しないタイミングで変わっているので理解できません????書き換わるタイミングをif(P[24]==0){LED=1;}で調べましたが、アップしているソース部分でした。xc8のバグ?
No.1
- 回答日時:
>sprintf(str, "%x",P[1]);//P[1]を16進に変換
>strcat(Txdata,str);//Pa\r\nを付け加える
とりあえず、2つめのコメントに書かれている挙動にはならないかと思われますがその辺りはどうなんでしょう?
あと、strとやらには十分なサイズの領域確保されてます?
# char str[2];だと不足しますけど。
>変数に入っている数値が0になってしまいます。
というのは「どの変数」のことですかね?
回答ありがとうございます。char str[4]; 4byte char Txdata[60]; 60byte 取っています。
今回問題となっている変数はP[24]で入力される変数ではなく、送信側にデータを吐き出す変数が0になっています。
strとかTxdata等にサイズが小さい場合、P[]が0になってしまう可能性がありますかね?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- C言語・C++・C# C# 浮動小数の数値文字列化 1 2022/04/18 15:15
- Visual Basic(VBA) VBA ユーザーフォームからSubプロージャ―に値を引き渡す方法 3 2023/04/09 01:54
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
勝手に無変換になる
-
エクセル関数/10進法から60進法...
-
スマホ(iPhone)で写真を絵に...
-
緯度・経度の値をエクセルで変...
-
青の吹き出しの何をどう考えれ...
-
アリーナ型議会と変換型議会の...
-
シガーソケットのL型変換ができ...
-
つらそう…を丁寧に言うなら、お...
-
無料でも使えるSSDを、MBRからG...
-
レーザーをマイクロ波に変換す...
-
フォルダ、ファイル名の一括変...
-
●Illustrator CMYKをRGB変換し...
-
名前を数字にしたい。
-
セガサターンを高画質でPCに出...
-
カーナビにスマホ画面を表示さ...
-
CDの音源をMP3に変換してメール...
-
廃仏毀釈の「毀釈」ってどうい...
-
cdiをisoに変換したいのですが
-
NTSC と PAL の確認...
-
拡張子omaをm4a又はmp4に直接変...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
緯度・経度の値をエクセルで変...
-
エクセル関数/10進法から60進法...
-
勝手に無変換になる
-
意外に?以外に??どちらが正...
-
無料でも使えるSSDを、MBRからG...
-
つらそう…を丁寧に言うなら、お...
-
●Illustrator CMYKをRGB変換し...
-
Wordに囲い文字というのがない...
-
VB.NETで小数点以下の桁数を取...
-
カーナビにスマホ画面を表示さ...
-
フォルダ、ファイル名の一括変...
-
スクリーンショット:文字がぼ...
-
MP3を楽譜に変換するサイト、ア...
-
pdfの色データをCMYK→K+Cの2色...
-
土日祝 の正しい読みは
-
CADソフトの拡張子変換
-
エクセル DEC2BIN 範囲外数値の...
-
単位の リューベ って
-
Windows Media PlayerからMP3に...
-
Google 日本語入力の調子がおか...
おすすめ情報
P変数は unsigned char P[30] =0; で宣言しています。
因みにPCから送信される0-255の値を代入して、P[]の値をEEPROMの各アドレスの1byteに書き混んでいますが、正常に書き込まれています。
文字変数を扱うのは難しいですね ><
「if(P[24]==0){LED=1;}で調べました」は言葉足らずですいません。この判定分をP[]が使用される場所(PCからデータを受信してP[]に代入した後、P[]をEEPROMに書き込んだ後、P[]を文字変換して送信する箇所)にいれて、LEDが点灯する箇所==P[]が0に変化する箇所と考えてサーチしました。
結果として、今回アップしたP[]を変換、送信のソース部分で変化しています。
また、変化はif(PP){if(P[24]==0){LED=1; でLEDが点灯しています。
因みにP[1] P[2]より、最後のP[24]のほうが0に変化する頻度が高いです。また、入っている数字が
255が0になりやすいです。