処理速度の問題ですか?

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

現在,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
  • わわいです
    ざっと見たところ、受信も送信も、ビジーループ(プログラム待ち)で構成されてるようですが、これだと文字列を送信している間は受信操作ができません。
    また、文字列の受信している間も送信操作はできません
    ということで、おそらくは、文字列の送信している間に受信しているデータを取りこぼしているのではないかと思われます

    これに対処するには、受信操作を割り込み対応させ、キューバッファに溜めていくような操作が必要となります

    #文字列受信ルーチンあたりにも問題がありそですねー

    追記:
    案の定、受信ルーチンがまずいですね
    文字列の最後の\nが来ると次の文字列受信までブロックしてしまいますねー

  •  >わわいさん

    http://www.tetras.uitec.jeed.or.jp/files/news/2014/rijicho_2-6.pdf

    キューバッファに溜めていくようなプログラムは,上記のURL(p.289-)の

    __interrupt(cect=23) void INT_SCI3(void)

    {

         ...

    }

    ようなプログラムになりますか?

    URLのプログラムはH8なので,RXで書くと

    #pragma interrupt (Excep_SCI1_RXI1)
    void Excep_SCI1_RXI1(void)
    { 

       ...

    }

    となると思うのですが...

     

     

  • わわいです
    まあ、そういうことですね
    受信割り込みを発生させるようにして、割り込みルーチンでは受信データを(たとえば128文字分の)キューバッファに溜めていく、という操作を行います。
    メインルーチンでは、キューバッファに溜まっている文字を順番に取り出し、1行分のメッセージに再構築し、1行溜まったら、それを加工し、送信するようにします
    受信割り込みを使えば、送信中であっても受信処理が行えるようになるので、受信漏れが発生することはなくなる、ということになります。

    ただ注意すべきは、割り込みというものはいつ発生するか予測がつかないため、割り込みルーチン内とメインルーチン両方で操作する変数がある場合、メインルーチンではその変数の取扱いをよく考える必要があります

Reply
  • わわいです
    まあ、そういうことですね
    受信割り込みを発生させるようにして、割り込みルーチンでは受信データを(たとえば128文字分の)キューバッファに溜めていく、という操作を行います。
    メインルーチンでは、キューバッファに溜まっている文字を順番に取り出し、1行分のメッセージに再構築し、1行溜まったら、それを加工し、送信するようにします
    受信割り込みを使えば、送信中であっても受信処理が行えるようになるので、受信漏れが発生することはなくなる、ということになります。

    ただ注意すべきは、割り込みというものはいつ発生するか予測がつかないため、割り込みルーチン内とメインルーチン両方で操作する変数がある場合、メインルーチンではその変数の取扱いをよく考える必要があります

Children