質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
組み込み開発

組み込み開発とは、スマートフォンや家電、自動車などに組み込まれているコンピューターシステムの開発のことです。特定の用途に特化しており、限られた機能のための開発を指します。組み込み開発で作られた機器を組み込み機器と呼び、近年ではPCのオペレーションシステム(OS)にも採用されています。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

Q&A

解決済

2回答

1414閲覧

RXマイコンでのRS232CでのFIFO通信方法のイメージについて

Nyanmage.neko

総合スコア7

組み込み開発

組み込み開発とは、スマートフォンや家電、自動車などに組み込まれているコンピューターシステムの開発のことです。特定の用途に特化しており、限られた機能のための開発を指します。組み込み開発で作られた機器を組み込み機器と呼び、近年ではPCのオペレーションシステム(OS)にも採用されています。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

0グッド

1クリップ

投稿2023/09/07 00:43

実現したいこと

  • C言語での通信方法とデータ処理についてのイメージを確立させたい
  • 関数を使いこなせるようになりたい
  • データの取得について処理の具体例が知りたい

前提

現在RX64Mマイコンを使用し、e2studioにてプログラムを書いています。
スマートコンフィグレータを使用してのコード生成を行っています。
SCIF9を使用してRS232Cの通信を使用と考えているのですが、下記の壁にぶつかっています。

<受信データを取得するためにどういった手順を踏めばよいか>
APIのリファレンスマニュアルや、ハードウェアマニュアルでのレジスタの確認をしながら、生成されたコードを読み、通信の開始/停止用の関数などの仕様を確認しています。なんとなくですが、コード生成されたものがハードウェアマニュアルマニュアル記載のレジスタの設定を行っていることや、関数呼び出しで通信が開始されることは理解できたのですが、いざプログラムを書こうにも、何からすればよいのか分からなくなってきました。

キャラクタ同期をしようと思っているので、
①通信開始の関数を呼び出し通信可能状態にする
②受信開始の関数
MD_STATUS R_<Config_SCI0>_Serial_Receive ( uint8_t * const rx_buf, uint16_t rx_num );
[引数]
uint8_t * const rx_buf;  受信したデータを格納するバッファへのポインタ
uint16_t rx_num; 受信するデータの総数
[戻り値]
MD_OK  正常終了
MD_ARGERROR 引数 rx_num の指定が不正
に自分で指定した受信データを格納したい変数のポインタと予定されているデータ数を引き渡す。
③変数に格納された値を読み、キャラクタ同期のスタート制御文字ならそのまま値を読み込み

のような感じで考えているのですが、どういったことに気を使わなくてはいけないのか、ご教授いただければと思います。
以下、コード生成したソースを参考に添付します。

C言語

1//Config_SCIF9.c 2#include "r_cg_macrodriver.h" 3#include "Config_SCIF9.h" 4#include "r_cg_userdefine.h" 5 6volatile uint8_t * gp_scifa9_tx_address; /* SCIFA9 transmit buffer address */ 7volatile uint16_t g_scifa9_tx_count; /* SCIFA9 transmit data number */ 8volatile uint8_t * gp_scifa9_rx_address; /* SCIFA9 receive buffer address */ 9volatile uint16_t g_scifa9_rx_count; /* SCIFA9 receive data number */ 10volatile uint16_t g_scifa9_rx_length; /* SCIFA9 receive data length */ 11 12void R_Config_SCIF9_Create(void) 13{ 14 volatile uint16_t dummy; 15 uint32_t w_count; 16 17 /* Cancel SCIFA9 module stop state */ 18 MSTP(SCIFA9) = 0U; 19 20 /* Clear transmit/receive enable bits */ 21 SCIFA9.SCR.BIT.TE = 0U; 22 SCIFA9.SCR.BIT.RE = 0U; 23 24 /* Reset transmit/receive FIFO data register operation */ 25 SCIFA9.FCR.BIT.TFRST = 1U; 26 SCIFA9.FCR.BIT.RFRST = 1U; 27 28 /* Read and clear status flags */ 29 dummy = SCIFA9.FSR.WORD; 30 SCIFA9.FSR.WORD = 0x00U; 31 32 dummy = (uint16_t) SCIFA9.LSR.BIT.ORER; 33 SCIFA9.LSR.BIT.ORER = 0U; 34 35 /* Set clock enable bits */ 36 SCIFA9.SCR.WORD = _0000_SCIF_INTERNAL_SCK_UNUSED; 37 38 /* Set transmission/reception format */ 39 SCIFA9.SMR.WORD = _0000_SCIF_CLOCK_PCLK | _0000_SCIF_STOP_1 | _0000_SCIF_PARITY_DISABLE | 40 _0000_SCIF_DATA_LENGTH_8 | _0000_SCIF_ASYNCHRONOUS_MODE; 41 SCIFA9.SEMR.BYTE = _00_SCIF_16_BASE_CLOCK | _00_SCIF_NOISE_FILTER_DISABLE | _00_SCIF_DATA_TRANSFER_LSB_FIRST | 42 _00_SCIF_BAUDRATE_SINGLE; 43 44 /* Clear modulation duty register select */ 45 SCIFA9.SEMR.BIT.MDDRS = 0U; 46 47 /* Set bit rate */ 48 SCIFA9.BRR = 0xC2U; 49 50 /* Wait for at least 1-bit interval */ 51 for (w_count = 0U; w_count <= _000004E0_SCIF_1BIT_INTERVAL; w_count++) 52 { 53 nop(); 54 } 55 56 /* Set FIFO trigger conditions */ 57 SCIFA9.FTCR.WORD = _0000_SCIF_TX_FIFO_TRIGGER_NUM_0 | _0080_SCIF_TX_TRIGGER_TFTC_VALID | 58 _0100_SCIF_RX_FIFO_TRIGGER_NUM_1 | _8000_SCIF_RX_TRIGGER_RFTC_VALID; 59 SCIFA9.FCR.WORD = _0000_SCIF_LOOPBACK_DISABLE | _0000_SCIF_MODEM_CONTROL_DISABLE; 60 61 /* Disable transmit/receive FIFO data register reset operation */ 62 SCIFA9.FCR.BIT.TFRST = 0U; 63 SCIFA9.FCR.BIT.RFRST = 0U; 64 65 /* Set interrupt priority */ 66 IPR(SCIFA9, TXIF9) = _0F_SCIF_PRIORITY_LEVEL15; 67 IPR(SCIFA9, RXIF9) = _0F_SCIF_PRIORITY_LEVEL15; 68 69 /* Set RXD9 pin */ 70 MPC.PB6PFS.BYTE = 0x0AU; 71 PORTB.PMR.BYTE |= 0x40U; 72 73 /* Set TXD9 pin */ 74 MPC.PB7PFS.BYTE = 0x0AU; 75 PORTB.PMR.BYTE |= 0x80U; 76 77 R_Config_SCIF9_Create_UserInit(); 78} 79 80void R_Config_SCIF9_Start(void) 81{ 82 /* Clear interrupt flag */ 83 IR(SCIFA9,TXIF9) = 0U; 84 IR(SCIFA9,RXIF9) = 0U; 85 86 /* Enable SCIF interrupt */ 87 IEN(SCIFA9,TXIF9) = 1U; 88 ICU.GENAL0.BIT.EN4 = 1U; 89 IEN(SCIFA9,RXIF9) = 1U; 90 ICU.GENAL0.BIT.EN5 = 1U; 91 ICU.GENAL0.BIT.EN6 = 1U; 92 ICU.GENAL0.BIT.EN7 = 1U; 93} 94 95void R_Config_SCIF9_Stop(void) 96{ 97 98 /* Disable serial transmit */ 99 SCIFA9.SCR.BIT.TE = 0U; 100 101 /* Disable serial receive */ 102 SCIFA9.SCR.BIT.RE = 0U; 103 104 /* Disable TXI interrupt */ 105 SCIFA9.SCR.BIT.TIE = 0U; 106 107 /* Disable RXI, ERI, BRI and DRI interrupt */ 108 SCIFA9.SCR.BIT.RIE = 0U; 109 IR(SCIFA9,TXIF9) = 0U; 110 IEN(SCIFA9,TXIF9) = 0U; 111 ICU.GENAL0.BIT.EN4 = 0U; 112 IR(SCIFA9,RXIF9) = 0U; 113 IEN(SCIFA9,RXIF9) = 0U; 114 ICU.GENAL0.BIT.EN5 = 0U; 115 ICU.GENAL0.BIT.EN6 = 0U; 116 ICU.GENAL0.BIT.EN7 = 0U; 117} 118 119MD_STATUS R_Config_SCIF9_Serial_Receive(uint8_t * const rx_buf, uint16_t rx_num) 120{ 121 MD_STATUS status = MD_OK; 122 123 if (rx_num < 1U) 124 { 125 status = MD_ARGERROR; 126 } 127 else 128 { 129 g_scifa9_rx_count = 0U; 130 g_scifa9_rx_length = rx_num; 131 gp_scifa9_rx_address = rx_buf; 132 133 SCIFA9.FTCR.BIT.RFTC = _01_SCIF_RX_TRIG_NUM; 134 135 SCIFA9.SCR.BIT.RE = 1U; 136 SCIFA9.SCR.BIT.RIE = 1U; 137 SCIFA9.SCR.BIT.REIE = 1U; 138 } 139 140 return (status); 141} 142 143MD_STATUS R_Config_SCIF9_Serial_Send(uint8_t * const tx_buf, uint16_t tx_num) 144{ 145 MD_STATUS status = MD_OK; 146 147 if (tx_num < 1U) 148 { 149 status = MD_ARGERROR; 150 } 151 else 152 { 153 gp_scifa9_tx_address = tx_buf; 154 g_scifa9_tx_count = tx_num; 155 SCIFA9.SCR.BIT.TE = 1U; 156 SCIFA9.SCR.BIT.TIE = 1U; 157 } 158 159 return (status); 160}

C言語

1//Config_SCIF9_user.c 2#include "r_cg_macrodriver.h" 3#include "Config_SCIF9.h" 4#include "r_cg_userdefine.h" 5 6extern volatile uint8_t * gp_scifa9_tx_address; /* SCIFA9 send buffer address */ 7extern volatile uint16_t g_scifa9_tx_count; /* SCIFA9 send data number */ 8extern volatile uint8_t * gp_scifa9_rx_address; /* SCIFA9 receive buffer address */ 9extern volatile uint16_t g_scifa9_rx_count; /* SCIFA9 receive data number */ 10extern volatile uint16_t g_scifa9_rx_length; /* SCIFA9 receive data length */ 11 12void R_Config_SCIF9_Create_UserInit(void) 13{ 14 /* Start user code for user init. Do not edit comment generated here */ 15 /* End user code. Do not edit comment generated here */ 16} 17 18#if FAST_INTERRUPT_VECTOR == VECT_SCIFA9_TXIF9 19#pragma interrupt r_Config_SCIF9_txif_interrupt(vect=VECT(SCIFA9,TXIF9),fint) 20#else 21#pragma interrupt r_Config_SCIF9_txif_interrupt(vect=VECT(SCIFA9,TXIF9)) 22#endif 23static void r_Config_SCIF9_txif_interrupt(void) 24{ 25 uint16_t count = 0; 26 27 /* Get the amount of untransmitted data stored in the FRDR register */ 28 uint16_t dummy_fdr = SCIFA9.FDR.BIT.T; 29 30 /* Write data to the transmit FIFO data register */ 31 while ((0U < g_scifa9_tx_count) && (count < (_10_SCIF_FIFO_MAX_SIZE - dummy_fdr))) 32 { 33 SCIFA9.FTDR = *gp_scifa9_tx_address; 34 gp_scifa9_tx_address++; 35 g_scifa9_tx_count--; 36 count++; 37 } 38 39 if (1U == SCIFA9.FSR.BIT.TDFE) 40 { 41 SCIFA9.FSR.BIT.TDFE = 0U; 42 } 43 44 if (0U >= g_scifa9_tx_count) 45 { 46 SCIFA9.SCR.BIT.TIE = 0U; 47 SCIFA9.SCR.BIT.TEIE = 1U; 48 } 49} 50 51void r_Config_SCIF9_teif_interrupt(void) 52{ 53 if (1U == SCIFA9.FSR.BIT.TEND) 54 { 55 SCIFA9.SCR.BIT.TE = 0U; 56 SCIFA9.SCR.BIT.TEIE = 0U; 57 } 58 59 r_Config_SCIF9_callback_transmitend(); 60} 61 62#if FAST_INTERRUPT_VECTOR == VECT_SCIFA9_RXIF9 63#pragma interrupt r_Config_SCIF9_rxif_interrupt(vect=VECT(SCIFA9,RXIF9),fint) 64#else 65#pragma interrupt r_Config_SCIF9_rxif_interrupt(vect=VECT(SCIFA9,RXIF9)) 66#endif 67static void r_Config_SCIF9_rxif_interrupt(void) 68{ 69 uint16_t count = 0; 70 71 /* Get the amount of receive data stored in FRDR register */ 72 uint16_t dummy_fdr = SCIFA9.FDR.BIT.R; 73 74 /* Read data from the receive FIFO data register */ 75 while ((g_scifa9_rx_length > g_scifa9_rx_count) && (count < dummy_fdr)) 76 { 77 *gp_scifa9_rx_address = SCIFA9.FRDR; 78 gp_scifa9_rx_address++; 79 g_scifa9_rx_count++; 80 count++; 81 } 82 83 /* If remaining data is less than the receive trigger number, receive interrupt will not occur. 84 In this case, set trigger number to 1 to force receive interrupt for each one byte of data in FRDR */ 85 if ((_01_SCIF_RX_TRIG_NUM > (g_scifa9_rx_length - g_scifa9_rx_count)) && (1U != SCIFA9.FTCR.BIT.RFTC)) 86 { 87 SCIFA9.FTCR.BIT.RFTC = 1U; 88 } 89 90 /* Clear receive FIFO data full flag */ 91 if (1U == SCIFA9.FSR.BIT.RDF) 92 { 93 SCIFA9.FSR.BIT.RDF = 0U; 94 } 95 96 if (g_scifa9_rx_length <= g_scifa9_rx_count) 97 { 98 /* All data received */ 99 SCIFA9.SCR.BIT.RE = 0U; 100 101 r_Config_SCIF9_callback_receiveend(); 102 } 103} 104 105void r_Config_SCIF9_erif_interrupt(void) 106{ 107 if (1U == SCIFA9.FSR.BIT.ER) 108 { 109 r_Config_SCIF9_callback_error(RECEIVE_ERROR); 110 /* clear receive error flag */ 111 SCIFA9.FSR.BIT.ER = 0U; 112 } 113} 114 115void r_Config_SCIF9_brif_interrupt(void) 116{ 117 if (1U == SCIFA9.LSR.BIT.ORER) 118 { 119 r_Config_SCIF9_callback_error(OVERRUN_ERROR); 120 /* clear overrun error flag */ 121 SCIFA9.LSR.BIT.ORER = 0U; 122 } 123 124 if (1U == SCIFA9.FSR.BIT.BRK) 125 { 126 r_Config_SCIF9_callback_error(BREAK_DETECT); 127 /* clear break detect flag */ 128 SCIFA9.FSR.BIT.BRK = 0U; 129 } 130} 131 132void r_Config_SCIF9_drif_interrupt(void) 133{ 134 /* Start user code for r_Config_SCIF9_drif_interrupt. Do not edit comment generated here */ 135 /* End user code. Do not edit comment generated here */ 136} 137 138static void r_Config_SCIF9_callback_transmitend(void) 139{ 140 /* Start user code for r_Config_SCIF9_callback_transmitend. Do not edit comment generated here */ 141 /* End user code. Do not edit comment generated here */ 142} 143 144static void r_Config_SCIF9_callback_receiveend(void) 145{ 146 /* Start user code for r_Config_SCIF9_callback_receiveend. Do not edit comment generated here */ 147 /* End user code. Do not edit comment generated here */ 148} 149 150static void r_Config_SCIF9_callback_error(scif_error_type_t error_type) 151{ 152 /* Start user code for r_Config_SCIF9_callback_error. Do not edit comment generated here */ 153 /* End user code. Do not edit comment generated here */ 154} 155 156

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

何からすればよいのか分からなくなってきました

と言われてしまうとこちらも何を説明すればいいのかもわからなくなっちゃうんですけどね。

気をつけることは前の質問で言っているのですが、それを「処理」に落とし込むなら(もちろんこれが唯一ではありません)

0. 切り出した1フレームを格納するバッファを用意しておいて、

  1. 1文字ずつ受信して、それがAFだったらフレームの切り出し開始(AFでなければ捨てる)
  2. 次の1バイトはデータサイズだから(ですね?)そのバイト数だけデータを受信してバッファに蓄積して
  3. その次を1文字受信してそれがEFであれば切り出し完了でフレームを処理に回す
  4. EFでなかったならフレームは受信失敗なので捨てて1.からやり直し

ということになるかと思います。


受信関数の使い方、という話であれば、私の前回の回答も結構間違ってて(といいながら今回のを実験してみたわけでもない。RXのボードは手元にあるけれど...)
・要求した文字数を受信した時に呼ばれるコールバック処理をr_Config_SCIF9_callback_receiveend(void)の二行のコメントの間に記述しておく
・要求する受信文字数と、その文字数を格納するバッファを引数にR_Config_SCIF9_Serial_Receive(uint8_t * const rx_buf, uint16_t rx_num)を呼ぶ。
・指定文字数を受信し終わると、割り込みで先のr_Config_SCIF9_callback_receiveend(void)が呼び出される
ということのようです。
なので、受信処理の状態遷移をr_Config_SCIF9_callback_receiveend()に書いておいて、R_Config_SCIF9_Serial_Receive()を呼び出し、空のループで(割り込み中で)必要データが溜まるのを待つ、というようなことになりそうな気がします。


結局気になってコードを書いてみちゃったので。もちろん、あくまでサンプルなので、あなたの用途でいろいろ不具合があるかも知れません。
扱いやすさの関係で開始コードは0x30, 終端コードは0X39。なんかスマートコンフィグレータが拗ねたのでSCIは8。大勢に影響ないとは思うけど、マイコンはRX671。

C

1volatile int rcvd = 0; 2#define START 0x30 3#define END 0x39 4int rcvFrame(uint8_t buf[]) { 5 uint16_t num; 6 // スタートマーク待ち 7 buf[0] = 0; 8 do { 9 num = 1; 10 rcvd = 0; 11 R_Config_SCI8_Serial_Receive(buf, num); 12 while (!rcvd) 13 ; 14 } while (buf[0] != START); 15 // データサイズ取得 16 num = 1; 17 rcvd = 0; 18 R_Config_SCI8_Serial_Receive(buf, num); 19 while (!rcvd) 20 ; 21 // データ本体+終了マーク待ち 22 num = buf[0] + 1; 23 rcvd = 0; 24 R_Config_SCI8_Serial_Receive(buf, num); 25 while (!rcvd) 26 ; 27 return buf[num-1] == END; 28} 29void main(void) { 30 uint8_t buf[256]; 31 R_Config_SCI8_Create(); 32 R_Config_SCI8_Start(); 33 while (1) { 34 int rc= rcvFrame(buf); 35 buf[255] = 0; //ブレークかける為の無意味な処理 36 } 37}

C

1static void r_Config_SCI8_callback_receiveend(void) 2{ 3 /* Start user code for r_Config_SCI8_callback_receiveend. Do not edit comment generated here */ 4 rcvd=1; 5 /* End user code. Do not edit comment generated here */ 6}

投稿2023/09/07 11:41

編集2023/09/08 07:27
thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Nyanmage.neko

2023/09/07 23:09

前回のご質問でもご回答いただきありがとうございました。 私自身関数の使い方が把握できていなかったので、前回の質問で見るべき場所が解決したおかげで今回の質問に至っています。色々調べた結果、「結局何をすればいいんだろう」「まず何をするべきなんだ...」とパニックになっていました...。前回もそうでしたが、私の伝わりづらい質問を良く理解して下さりありがとうございます。 コールバック処理とは具体的にどういった処理でしょうか。 「1文字ずつ受信して、それがAFだったらフレームの切り出し開始(AFでなければ捨てる)」 であるように、「AF」が最初の場合に 「R_Config_SCIF9_Serial_Receive(uint8_t * const rx_buf, uint16_t rx_num)」 に、格納バッファと受信文字数を引数として渡して、データを保存。 →関数を用意しなければ、そのまま捨てられる という処理を行うかどうかの判断がコールバック処理でしょうか。 表示がされておらず回答を確認する前に今回y_waiwai様を先にベストアンサーとさせていただいております。大変申し訳ございません。
thkana

2023/09/08 01:29

コールバックは、何かの処理に対して登録したとき、その処理の内部から自動的に呼び出される処理のことを言います。 今回で言えば、R_Config_SCIF9_Serial_Receive()関数を呼び出したあと(割り込みによって受信して)指定した文字数を受信した時点で割り込みコンテキストでコールバック関数r_Config_SCIF9_callback_receiveend()が自動的に呼び出される、ということと思われます。 処理内容は言葉で説明するより結局サンプルコードを書かないと説明しきれないなぁ... システムが変わっていなければ、ベストアンサーはいくらでも変更できたはずです。あなたにとって一番解決に寄与した「ベスト」を選んで下さい。(逆に、解決していないのなら無理にベストアンサーを選ぶこともありません。プログラムを書けてから選んだっていいはずですし、回答に依らずに自己解決してしまうことだってあり得ます)
Nyanmage.neko

2023/09/08 02:59

「Config_SCIF9_user.c」の「static void r_Config_SCIF9_rxif_interrupt(void)」内の101行目に、 「r_Config_SCIF9_callback_receiveend();」がありますね。 まさに「static void r_Config_SCIF9_rxif_interrupt(void)」内に登録され、内部から自動的に呼び出されるようになっていました。 そして、「r_Config_SCIF9_callback_receiveend();」が呼び出される直前の処理で、 「SCIFA9.SCR.BIT.RE = 0U;」によって受信動作が禁止されていますね。 送信の場合は、「static void r_Config_SCIF9_txif_interrupt(void)」の最後で、 「SCIFA9.SCR.BIT.TEIE = 1U;」送信完了割込み要求を許可して、 「void r_Config_SCIF9_teif_interrupt(void)」のTEIF割込みで、 送信完了フラグが1であることを確認して、送信動作と送信完了割込み要求を禁止していました。 その後に、「r_Config_SCIF9_callback_transmitend();」がありますね。 受信も送信も自動で呼び出されるようになっていることが理解できました。いまいち「送信完了割込み要求」という言葉が理解しづらい感じはしますが....。 処理の内容についてはやはり一度書いて動作を確認するのが一番でしょうか。 ベストアンサーについて変更可能ですね。私がこのサイトの仕様を理解しきれていませんでした。この質問については実際に動かした結果まで知りたいので、ベストアンサーは保留します。某知恵〇のように期限があるものだと思っていました。
thkana

2023/09/08 08:44

あ、FIFO入れてなかった...多分大きくは変わらないと思うけれど。(RX671だとSCI9はFIFO入らないみたい)
Nyanmage.neko

2023/09/12 10:00

サンプルコードありがとうございます。RX671だとSCI9はFIFOじゃないんですね。 大変助かりました。どういった動きになるのか確認し、自分でも記述してみます。
Nyanmage.neko

2023/09/26 05:19 編集

の一先ずプログラムを書いてみましたが、何かが悪くデータの取得が行われなかったです。 シリアル通信をスタートしたままにして、信号をマイコンに送りましたが、「recearray[i] 」の中身は確認ができませんでした。デバッグの仕方に問題がある可能性がありますが、もしかするとこのやり方だと、値が保存されずに初期化されてしまうのでしょうか。 (省いていますが、ヘッダーファイルのインクルードは行っています) ```C #define START 0xAF #define END 0xEF extern volatile uint8_t * gp_scifa9_rx_address; void receiveDate(void){ uint8_t buf[256]; uint16_t num = 6; R_Config_SCIF9_Serial_Receive(buf, num); uint8_t recearray[5] ={0}; recearray[0] = * gp_scifa9_rx_address; if(recearray[0] == START){ for(int i=0; recearray[i] == END; i++){ recearray[i] = * gp_scifa9_rx_address; } } } void main(void) { R_Config_SCIF9_Create(); R_Config_SCIF9_Start(); receiveDate(); } ```
Nyanmage.neko

2023/09/26 05:18

もう一つ単純に、下記の記述を試しましたが、date1~date6まで常に0になりますね。 まったく値の取得ができていないようです。このdate1~date6をならべて順に代入する方法は、過去にRenesasに問い合わせた際の方法です。 ``` void main(void){ R_Config_SCIF9_Create(); R_Config_SCIF9_Start(); uint8_t buf[256]; uint16_t num = 6; R_Config_SCIF9_Serial_Receive(buf, num); uint8_t date1 = SCIFA9.FRDR; uint8_t date2 = SCIFA9.FRDR; uint8_t date3 = SCIFA9.FRDR; uint8_t date4 = SCIFA9.FRDR; uint8_t date5 = SCIFA9.FRDR; uint8_t date6 = SCIFA9.FRDR; } ```
thkana

2023/09/26 23:47

実機でのトレース等しておらず字面を眺めただけですが、 > 一先ずプログラムを書いてみました recearrayに意味のあるデータが拾えるプログラムにはなっていないように思います。 if(recearray[0] == START){ for(int i=0; recearray[i] == END; i++){ recearray[i] = * gp_scifa9_rx_address; } for文の"継続条件"はrecearray[i] == ENDですが、recearray[0]==STARTでこのfor文に入るわけですからrecearray[0]==ENDは必ず偽、ループは一度も実行されず次へ進みます。 > もう一つ FIFOを使った例はちゃんと見ていませんが、R_Config_SCIF9_Serial_Receive()関数から呼ばれる割り込みでFIFOのデータは使われてしまっているのではないのですか? さらにFIFOを読んでも意味のあるデータは取得できないと思いますが如何?
thkana

2023/09/26 23:50

> 過去にRenesasに問い合わせた際の方法 前提となる条件が異なっているのでは? R_Config_SCIF9_Serial_Receive()実行後に読み込む、という話だったのでしょうか?
Nyanmage.neko

2023/09/27 01:15

ご回答ありがとうございます。 文の継続条件の間違いをご指摘いただきありがとうございます。デバッグするとint=iが増えることなく次のステップに移っていたので納得しました。 R_Config_SCIF9_Serial_Receive()関数で値の保存先と送られてくるデータ数の指定を行うということは上記した返信で書いている通りですが、その値が実際に利用されているのは、Config_SCIF9_user.c内の、 「static void r_Config_SCIF9_rxif_interrupt(void)」で、1バイト受信するたびに、この割込みハンドラが呼び出されるようです。この割込みの中に、 r_Config_SCIF9_callback_receiveend()関数があるので、この関数内に、データ受信後に行う処理、上記で私が書きました「void receiveDate(void)」みたいな処理内容を書かなければいけなかったようです。なので、FIFOのデータを読もうとしても取得できなかった可能性が高いです。 >過去にRenesasに問い合わせた際の方法、については「R_Config_SCIF9_Serial_Receive()実行後に読み込む」、という前提は示されておらず、私の方で勝手に判断していました。r_Config_SCIF9_callback_receiveend()内に書けば受信できた可能性はあります。 上記内容加味してプログラム書き直して動作を確認してみます。
Nyanmage.neko

2023/09/27 05:04

改めて過去にいただいた回答など確認し整理していましたが、最初にいただいた回答の中にある、 「R_Config_SCIF9_Serial_Receive()を呼び出し、空のループで(割り込み中で)必要データが溜まるのを待つ、というようなことになりそうな気がします。」 ここが出来ていないことが原因となっていそうです。 教えていただきたいのですが、「空のループ」とはどういった物なのでしょうか。mian関数があるソースファイルに書くwhile(1)ループとは別物ですか?
thkana

2023/09/27 22:39

> 空ループ rcvFrame()関数の19行目付近 > while (!rcvd) > ; がそれです。 (然るべく仕込んでおけば)シリアルの受信はメインコンテキスト(メインのプログラムの流れ)には関係なく処理が進み、指定文字数が溜まります。なので、メイン側では、R_Config...関数を呼び出したあとはその終了条件が満たされるのをただひたすら待つ(他の仕事があるならやってもいいですけれど)ということになります。
Nyanmage.neko

2023/09/29 07:48

ご回答ありがとうございます。空のループを使用し、とりあえずワンショットだけのデータ取得が成功しました! 二回目のループを回すとデータの頭とお尻の取得がズレたりすることも確認できたので、そのあたり目的のデータが来た時に値を取得するようにこれからプログラムできそうです。様々なことを教えていただきありがとうございました。
thkana

2023/09/29 22:06

> そのあたり目的のデータが来た時に値を取得するようにこれからプログラムできそうです というのに対応したサンプルを提示して、「できそうです」と言われるのもなんだか微妙だなぁ... 結構脅してはいるけれど、通信が乱れるのは余程厳しい状況だけだったりするので、ズレが簡単に再現できてしまうようだとそもそもの処理に問題があることを疑ったほうがよいと思います。
Nyanmage.neko

2023/10/01 23:37

返信ありがとうございます。 >というのに対応したサンプルを提示して、「できそうです」と言われるのもなんだか微妙だなぁ... 私自身が初学者なので、今すぐに出来ますとは断言できません。頂いたサンプルの「スタートマーク待ち」「データ本体+終了マーク待ち」などはマネしながらになると思いますが、自分自身のプログラミング能力が低いため、書き方についてはまだまだ勉強する必要があります。例えば、頂いたサンプルの「num = buf[0] + 1;」が「return buf[num-1] == END;」がどういった処理なのかについては理解が進んでいませんが、これは「配列」の仕様に関わる部分なので、そこまで聞くのは如何かと思っています。分からない部分がまだあるので、上記のような返信になっています。 >ズレが簡単に再現できてしまうようだとそもそもの処理に問題があることを疑ったほうがよい スタートと終了を適切に見れていない可能性があるので、おそらく記述の問題ですね。頂いたサンプルをまねしながら修正致します。
guest

0

R_Config_SCIF9_Serial_Receive関数は、単に受信バッファとそのサイズを設定して、シリアル受信を開始する関数です
実際の受信データは、先の受信バッファの先頭から、g_scifa9_rx_countのバイト分格納されます
あなたのすべきことは、

  1. R_Config_SCIF9_Serial_Receive関数を実行して受信バッファを設定、受信動作を開始
  2. g_scifa9_rx_countを読み出し0であればなにもしない
  3. g_scifa9_rx_countが0以上であれば、受信バッファアドレスからデータを読み出し、g_scifa9_rx_countを0にして、gp_scifa9_rx_addressに受信バッファアドレスを代入します

ってことで、プログラムの実行中は、定期的に2,3を繰り返し実行するってことになります
注意すべきは、3で、g_scifa9_rx_countとgp_scifa9_rx_addressの操作をしている最中は、受信割り込みがかかってしまうと不味いので、この間は割込み禁止にしなければなりません

投稿2023/09/07 05:18

編集2023/09/07 07:37
y_waiwai

総合スコア88024

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Nyanmage.neko

2023/09/07 07:01

大変詳しいご回答ありがとうございます。関数の認識が間違っていることや、手順が良くわかりました。 認識の確認をさせてほしいのですが、 「Config_SCIF9_user.c」内にある、67行目の「static void r_Config_SCIF9_rxif_interrupt(void)」の中身を確認すると、 while ((g_scifa9_rx_length > g_scifa9_rx_count) && (count < dummy_fdr))  ⑤ { *gp_scifa9_rx_address = SCIFA9.FRDR; ① gp_scifa9_rx_address++;        ② g_scifa9_rx_count++;          ③ count++;                ④ } となっているので、 ①FRDRレジスタに格納されている受信データを1バイトの「*gp_scifa9_rx_address」のメモリに代入 ②1バイト分の番地を増やす ③格納できるバイト数が増えたので同様にカウントを1増やす ④受信データ量が増えるため比較用に作成されたカウントも1増やす ⑤「Config_SCIF9.c」の119行目「MD_STATUS R_Config_SCIF9_Serial_Send」に引数として渡していた推定バイト数に「g_scifa9_rx_count++;」が追いつくと受信終了 と考えたのですが、合っていますでしょうか。「SCIFA9.FRDR」内のデータがキャラクタ同期の制御文字だった場合に、上記の処理が行われるようなプログラムを書く必要があるのかなと考えました。
y_waiwai

2023/09/07 07:41 編集

あ、そですね。 勘違いしてました。 受信バッファの先頭から受信データ読み出し、ですね 回答の方も修正しときますね んで、RS232Cなどの調歩同期式であれば、キャラクタ同期ってのはないので、そこらへんは考えないでいいです。 で、送信関数R_Config_SCIF9_Serial_Sendの方は、送信データ列の先頭アドレスと、送信バイト数を入れてやれば、あとは割り込みで勝手に送信してくれます #送信終了はg_scifa9_tx_countの値をチェックしましょう
Nyanmage.neko

2023/09/07 09:22

ご返信ありがとうございます。 実は外部機器からは、「AF 06 B4 00 01 01 00 1A EF」というように、AFで始まりEFで終わる仕様でデータが送信されてくるため、いわゆるキャラクタ同期となるのかなと思っていましたが、考えなくていいというのは、どういった意味合いでしょうか。単純にデータが送られてくるたびに取得するだけなので、確かに考えなくてもいいなとはふと思いました。 送信の方についてもありがとうございます。送信の方はカウントはマイナスされて減っていくようになっていますね。こう見ると送信の方が扱いは簡単に見えます。
y_waiwai

2023/09/07 11:49

単純に受信データを読んで、AFで始まってFEで終わるデータ列を検出すればいいだけです。 これは同期とかそういうはなしではなくて、単なる通信フォーマットのはなしですね
Nyanmage.neko

2023/09/07 22:52

理解しました。詳細な説明ありがとうございました。大変助かりました。教えていただいた手順でまずは簡単なプログラムを書いて、データを取得してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問