お世話になっております.
現在,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); } }
115200bpsで間に合わないとなると、sscanfの処理によほど時間がかかっているのかもしれません。 割り込みで対応したとしても、sscanfの処理が遅いと、いずれはバッファがあふれてしまいます。 まずは、割り込みに手を付ける前に、処理時間の分析が必要です。(オシロがありますか?) CSVの1行はCR(\r),LF(\n)で終了しているはずなので、Sci1Gets()の処理は単純に'\r'なら読み捨て、'\n'で終了とした方が間違いがないと思います。
オシロで受信や送信しているデータのタイミングを見たり、sscanfの処理時間(前後でポートをON/OFFする)を見たりすることで、間に合わない原因がわかると思います。 読み捨ては、strに格納せずに次の受信を行います。(受信ループでcontinueする)