処理速度の問題ですか?

お世話になっております.

現在,RX621を用いて,PCからTeratermを介してシリアル通信で受信したCSVファイル(オンラインデータで毎時刻上書きされている)をカンマで分割し,各値を名前の付けた文字列に格納し,そのうち1つの文字列をPCへ送信し,Teratermに表示させるプログラムを作成しています.

Teratermで1秒ごとにCSVファイルを送った場合,プログラム通りTeratermに送信した1つの文字列が1秒ごとに表示されますが,

Teratermのマクロを1/10秒ごとに変更した場合,最初の時刻のCSVデータは表示されますが,それ以降のデータが表示されません.

カンマで分割せずにそのままPCで送った場合は1/10秒ごとでもTeratermに表示されるため,分割の処理速度が原因であると思うのですが,何かアイデアがあればご教授願います.

以下は作成したRX621のプログラムです.

 

#include <machine.h>
#include "iodefine.h"
#include <stdio.h>
#include <stdlib.h>

// #define USE_IR
#define DDR_IN 0
#define DDR_OUT 1

static void delay_1ms(void)
{
// 実測でループ回数を決定
unsigned int n = 20000;
while (n--)
nop();
}


void delay_ms(unsigned int n)
{
while (n--)
delay_1ms();
}


void setup_clock(void)
{
// SCKCRはワードで一括指定しても良い。

// ICLK x8
SYSTEM.SCKCR.BIT.ICK = 0;
while (SYSTEM.SCKCR.BIT.ICK != 0) ;

// PCLK x4
SYSTEM.SCKCR.BIT.PCK = 1;
while (SYSTEM.SCKCR.BIT.PCK != 1) ;
}

void setup_sci(void)//シリアル通信の初期設定関数
{
// SCI1: P26/TXD1, P30/RXD1
MSTP(SCI1) = 0;
SCI1.SCR.BYTE = 0;
PORT2.DDR.BIT.B6 = DDR_OUT;
PORT3.DDR.BIT.B0 = DDR_IN;
PORT3.ICR.BIT.B0 = 1;
SCI1.SMR.BYTE = 0;
SCI1.BRR = 12;
// wait 1 bit time
// 1 / 9600 = 約 0.11ms -> 1msとする。
delay_ms(1);
SCI1.SCR.BYTE |= 0x30; // TE=1,RE=1
}


unsigned char sci_recv(void)//シリアル通信受信関数
{
unsigned char CsvData; //受信したデータを格納する変数の宣言(SCI1.RDR がunsigned char型なので)

#ifdef USE_IR
while (IR(SCI1,RXI1) == 0) ;
#else
while (SCI1.SSR.BIT.RDRF == 0) ;
#endif

CsvData =SCI1.RDR; //格納したデータをdataに格納する
return CsvData; //受信したデータを返す
}


void Sci1Gets(char *str) // 文字列受信
{
int i;

for(i = 0; i< 70;){
int recievedChar;
recievedChar = sci_recv();
if(recievedChar == '\r' || recievedChar == '\n'){
if(i>0){
break;
}
}else{
str[i++] = (char)recievedChar;
}
}
str[i] = '\0';
}


/*--- 一文字送信する関数 ---*/
void sci_send(char ch)
{
while (SCI1.SSR.BIT.TDRE == 0) ;
SCI1.TDR = ch;
while(!SCI1.SSR.BIT.TEND);
}

/*--- 文字列を送信する関数 ---*/
void sci_puts(char* str)
{
while(*str != '\0')
{
sci_send(*str);
str++;
}
}


void main(void)//メイン関数
{

char str[70];
char A[8], B[8], C[8], D[8], E[8], F[8], G[8];

setup_clock();
setup_sci(); // シリアル通信の初期設定

while(1){

Sci1Gets(str);
sscanf(str, "%[^\t\r\n ,],%[^\t\r\n ,],%[^\t\r\n ,],%[^\t\r\n ,],%[^\t\r\n ,],%[^\t\r\n ,],%s" , A,B,C,D,E,F,G); // 文字列data2をカンマで区切り、配列Dataに格納する

sci_puts(A);
}

}

Parents
  • 外部クロックが不明ですが、コメントから9600bpsで通信しているようなので、もっと速度を上げれば、とりあえず取りこぼしがなくなるのではないかと思います。(何だか見覚えのあるコードだと思ったら、小文字の関数は私が以前投稿したサンプルですね)
  • >Higetakaさん
    115200bpsで通信していますが,速度を上げても変化ありませんでした.

    >(何だか見覚えのあるコードだと思ったら、小文字の関数は私が以前投稿したサンプルですね)
    参考にさせて頂いています.
  • 115200bpsで間に合わないとなると、sscanfの処理によほど時間がかかっているのかもしれません。
    割り込みで対応したとしても、sscanfの処理が遅いと、いずれはバッファがあふれてしまいます。
    まずは、割り込みに手を付ける前に、処理時間の分析が必要です。(オシロがありますか?)

    CSVの1行はCR(\r),LF(\n)で終了しているはずなので、Sci1Gets()の処理は単純に'\r'なら読み捨て、'\n'で終了とした方が間違いがないと思います。

  • >Higetakaさん
    オシロはありますが,オシロで何を確認するのでしょうか?

    >Sci1Gets()の処理は単純に'\r'なら読み捨て、'\n'で終了とした方が間違いがないと思います。
    「読み捨て」と「終了」は何が違うのでしょうか?
    どちらも break;  ではないですよね...
  • オシロで受信や送信しているデータのタイミングを見たり、sscanfの処理時間(前後でポートをON/OFFする)を見たりすることで、間に合わない原因がわかると思います。

    読み捨ては、strに格納せずに次の受信を行います。(受信ループでcontinueする)

  • >わわいさん,Higetakaさん
    teratermのマクロを少し修正してみたところ,1/10秒,1/100秒の送受信を達成することができました.(ただし,Teratermのスクロールバッファの最大になるまでの実験時間なら...)
    teratermのマクロで pause 1/10 としていたことが原因だったようで,mpause 100 と記述すると上手くいきました.pause は分数を扱えないのかも知れません.

    結局割り込みは使わなかったのですが,後に必要になるかもしれないので,この機会に触れて見たいと思います.ありがとうございました.
Reply
  • >わわいさん,Higetakaさん
    teratermのマクロを少し修正してみたところ,1/10秒,1/100秒の送受信を達成することができました.(ただし,Teratermのスクロールバッファの最大になるまでの実験時間なら...)
    teratermのマクロで pause 1/10 としていたことが原因だったようで,mpause 100 と記述すると上手くいきました.pause は分数を扱えないのかも知れません.

    結局割り込みは使わなかったのですが,後に必要になるかもしれないので,この機会に触れて見たいと思います.ありがとうございました.
Children
No Data