「みんな教えて! 選手権!!」開催のお知らせ

現在PICマイコンでPCからGPSの座標データを取得し,そのデータ列から必要な部分だけ抜き出す処理をくんでいるんですがうまくいきません。

pcとマイコンの接続はrs23-2c
コンパイラはccsc
pic:16f877


GPSデータ↓
@051125012151N3529558E13638533G009+00021E0000N0000D0003
このデータのN以降の「3529558」とE以降の「13638533」の文字列を数値にしたい。


delay_ms(300);
output_b(0b00000001);//デバック用LED点灯
delay_ms(300);
gets(mes);    //ここでGPSデータをmesに代入する
output_b(0b00000011);


len_N=0;
for(i=0;i<58;i++){
 if(mes[i]=='N'){
  len_N=i;
  break;
 }
}
printf("\r\n");

n=atoi(mes[len_N+1]); //ここで試しに一文字分だけ数値にする処理を行ったが処理が停止する。
printf("n:%ld",n);


アドバイスお願いします

A 回答 (6件)

以下のようにすると切り出しぐらいはできるようです。


ただRAM384バイトしかないので変数領域に気をつけてください。
一応コンパイルは通るようです。実際の挙動がそのようになるかは確認していません。
また、よく考えるとatoi()ではだめですよね。
CCS-Cのlong型は16ビットですからunsigned指定をしても65535までしかカウントできません。
サンプルにある13638533なんて演算できませんもんね。
ここを数値化する方法は別に考えないといけませんね。

#include <TEST.H>

char mes[60] = "@051125012151N3529558E13638533G009+00021E0000N0000D0003";

void main() {
int numN=0 ;
int Nflag=0;
int numE=0;
int Eflag = 0;
int i;
char mesN[10] = {0,0,0,0,0,0,0,0,0,0};
char mesE[10] = {0,0,0,0,0,0,0,0,0,0};
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_port_a(NO_ANALOGS);
setup_adc(ADC_CLOCK_INTERNAL);

while(1){
printf("Input> ");printf(mes); printf("\r\n");

for(i=0;i<58;i++){
if ( mes[i]=='N' ){ Nflag = 1; Eflag = 0; }
if ( mes[i]=='E' ){ Nflag = 0; Eflag = 1; }
if ( mes[i]=='G' ){ Nflag = 0; Eflag = 0; }
if ( Nflag ) {
mesN[numN] = mes[i];
numN++;
}
if ( Eflag ) {
mesE[numE] = mes[i];
numE++;
}
}

printf( mesN ); printf("\r\n");
printf( mesE ); printf("\r\n");

}
}
    • good
    • 0
この回答へのお礼

ありがとうございます、参考にします

お礼日時:2005/12/28 22:55

>ポインタ操作ができないようです



ということであれば、
文字列の処理をどうするのか補足してください。
文字列を数字にするのは変数演算でできると思うのですが、できませんか?

この回答への補足

回答者の方々のおっしゃるとおり、
longでもビット数が足りないことが分かりました。
いままで授業ではPC上のソフトしか組んだことがないので
まったくの無知でした。

どっちみち、うまく取り出したとしても変数に
格納できないし、unsignedではなんか反則技みたいで

最終的には
dig(int) min(int) sec(float) と三つに分けるつもりなので
ばらばらで処理していきたいと思います

ちなみに
16F877に書き込んだところ
すでにRAMがいっぱいです。

cssのマニュアルには
なるべくローカル変数をへらせ
としかかいてありません
数回しか行かない関数はメイン文に入れろ
と先生はいうので
そのとおりにしてもぜんぜん足らないので
PICを変えるべきなのか迷っています。

補足日時:2005/12/28 22:58
    • good
    • 0

そういえばこれGPSですよね。

ということはわたってくる数値は固定小数点だったはず。

であれば、

float n, e, pow;

n = 0;
pow = 10;
for(i = 1; mes[len_N + i] >= '0' && mes[len_N + i] <= '9'; i++)
{
 n += (mes[len_N + i] - '0') * pow;
 pow /= 10;
}

e = 0;
pow=100;
for(i = 1; mes[len_E + i] >= '0' && mes[len_E + i] <= '9'; i++)
{
 e += (mes[len_E + i] - '0') * pow;
 pow /= 10;
}

ということではないかと思います。
    • good
    • 0
この回答へのお礼

参考にさせていただきます。

お礼日時:2005/12/28 22:57

rentaheroです。


PICは触ってないので、一般人で。

そもそもatoi(3)に対する引数の型が間違ってます。
atoiは文字列へのポインタを渡さなければなりません。

mesはchar のポインタか配列のようですから、
mes[len_N+1]はcharそのものです。

1文字だけ数値にしたい場合は、
n = mes[len_N+1]-'0';
とするべきだし、
同じ位置からintとして数値を取り出したい場合は、
n = atoi(&mes[len_N + 1]);
または
n = atoi(mes + len_N + 1);
となります。

'N'を検出する処理は問題ないと思います。

この回答への補足

ポインタ操作ができないようです

補足日時:2005/12/14 10:20
    • good
    • 0

PCでやってもatoi(3)はエラーになりますね。


#include <stdio.h>
#include <stdlib.h>
#define NGPSBUFF 58

int
main(void)
{
char mes[NGPSBUFF];
int i;
long N, E;
char *n, *e;


gets(mes); //ここでGPSデータをmesに代入する

for (i = 0; i < NGPSBUFF; i++) {
if (mes[i] == 'N')
break;
}
++i;
n = &mes[i];
for (; i < NGPSBUFF; i++) {
if (mes[i] == 'E')
break;
}
mes[i] = '\0';
++i;
e = &mes[i];
for (; i < NGPSBUFF; i++) {
if (mes[i] == 'G')
break;
}
mes[i] = '\0';

N = atoi(n);
printf("n:%ld\n", N);
E = atoi(e);
printf("e:%ld\n", E);

return 0;
}

この回答への補足

一部参考にしてみましたがやはりポインタ操作とのころで
処理が停止しています。
その問題を回避しつつ、数字の文字列をだすには
どうしたらいいでしょうか?

補足日時:2005/12/14 10:18
    • good
    • 0

atoi関数の考え方がまずいですよね。


atoiに与える引数はキャラクタ型ポインタですからnullポインタが出てくるところまで動作してしまうんではないでしょうか。
char buf[2] = {0,0};
とでもしておいて、
buf[0] = mes[len_N+1];
n=atoi(buf);
printf("n:%d",n);
とでもすればうまくいきそうにみえますね。

この回答への補足

知人いわく
このコンパイラはポインタ操作ができないらしいのです
どうしたらいいでしょうか?
また文字列を取り出す時にはどうしたらいいでしょうか?

補足日時:2005/12/14 10:17
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報