概要
前回のつづき、とりあえずいろんな機能をRL78-G23で試していく
(様々違いがあるだろうが、他のRenesasマイコンでも同じように使えるだろう。)
↓セットアップ等前回
['26/05/29]winドライバーポリシー変更への対処
2026/05/29付けでwinのドライバーアップデートによってE2,E2 lite emuが使えなくなる問題発生。
お知らせ通り、配布されたドライバーを手動で当てて修正できる。
書き込み・デバッグ
RFPを使う
Renesas Flash Programmerを使うと、マイコンにプログラムを書きこんで単体動作させられる。

ツールやボードの設定を済ませたら接続。
.hex,.mot,.srecなどがプログラムファイルらしい。
{projectname}\HardwareDebug内にあるのでそれでよさそう。
書き込みが完了の後、emulatorとマイコンの配線を切断するとマイコンが動く。書き込み用のピンTOOL0がHIGHであることが動作の条件らしい。
e2studio側でやる
・デバッグなら上の虫アイコンを押せばデバッガが起動する。コードの途中で動作を止めたり、変数を観察できたりする。
・書き込み/実行をe2studioでやる方法。
(e2studioでやると言っていいのか怪しいが)外部実行からRFPを利用して書き込む。
実行>外部ツール構成を選択。以下のように設定。

ロケーション:C:\Program Files (x86)\Renesas Electronics\Programming Tools\Renesas Flash Programmer V3.22\rfp-cli.exe
作業ディレクトリー:${workspace_loc}/${project_name}
引数:-d RL78 -t e2l -run -a "${project_loc}/HardwareDebug/${project_name}.srec"
実行すると、ビルドされた.srecが書き込まれ、またTOOL0がHIGHに上がり、マイコンが自走する。
マイコン基本機能を使うためのコンフィグ類
共通
基本的にscfgで使いたい機能の設定、ピン割り当てなどを行い、コード生成された関数たちをメインコードや各ユーザー向けファイルで使っていく。
生成されたコードファイルはsmc_genフォルダ内、各モジュール名のフォルダの中にある。APIの使い方を確認できるほか、xxxxxx_user.cには直接書いたりする。
GPIO
scfgのコンポーネント > I/OポートからConfig_PORTを作成。
使いたいピンが属するPORTのチェックボックスを入れる(ピン名:PxyのときPORTxに属する。xは2桁もある。)。


端子>端子番号から使うピンにシンボリック名をつける。

あとはメインコード内からR_Config_PORT_Create();の後、PIN_WRITE(YOURoutpin) = PIN_READ(YOURinpin);などして使える。
シンボリック名を付けなかったり、↑みたいなマクロを使わず直接レジスタを叩いたりできるだろうが、こちらの方が便利で整理だろう。
softwareDelay
scfgのコンポーネント > その他からr_bspを作成。
API functions disable(R_BSP_SoftwareDelay)をEnableへ設定。
R_BSP_SoftwareDelay(10, BSP_DELAY_MICROSECS);でdelayがつかえる。
Lチカサンプルコード↓
DAC (analog出力)
scfgのコンポーネント > D/Aコンバータから使いたいDACをつくる。ピンANO0,ANO1に対応(2ピンしかない?)。
R_Config_DAC0_Create();、R_Config_DAC0_Start();の後、R_Config_DAC0_Set_ConversionValue(val);で使える。
分解能は8bitで固定?
タイマー割り込み
scfgのコンポーネント > タイマ・アレイ・ユニットからインターバル・タイマを選択。動作・リソースを目的に設定してTAUを作成。
TAUコンポーネントの設定からインターバル時間を設定できる。
Config_TAU0_0_user.c内、void r_Config_TAU0_0_interrupt()内に処理内容を書く。
DAC同様、R_Config_TAU0_0_Start();で開始。
割り込みでDACなど外の関数を使いたいとき、_user.cからもincludeしないと使えない。
シリアルプリント
scfgのコンポーネント>シリアル・アレイユニットからUARTを追加。
動作クロックをfSELクロック選択fIHPにする。(外部クロック等特別なことをしたいのでなければこれで。)
転送レートを適切な値にする。
R_Config_UART1_Create();、R_Config_UART1_Start();の後、R_Config_UART1_Send((uint8_t *)&txt, txtlen)で送れる。
以下、シリアルプリントのサンプルを書く。
smc_gen>Config_UART1内のConfig_UART1_user.cに送信完了用のフラグ変数をつくる。
/* Start user code for global. Do not edit comment generated here */
extern volatile uint8_t g_uart1_tx_end;
/* End user code. Do not edit comment generated here */
...
static void r_Config_UART1_callback_sendend(void)
{
/* Start user code for r_Config_UART1_callback_sendend. Do not edit comment generated here */
g_uart1_tx_end = 1;
/* End user code. Do not edit comment generated here */
}
main.cにSerialPrintfを実装する。送信が終わっていれば送信、未完ならスキップ。ノンブロッキング優先で。
#include <stdio.h>
#include <stdarg.h>
char log_buf[64];
volatile uint8_t g_uart1_tx_end = 1;
void SerialPrintf(const char *format, ...)
{
// UART送信器が空いている(=1)ときだけ処理する(ビジーなら即座にスルー)
if (g_uart1_tx_end == 1)
{
va_list args;
va_start(args, format);
// vsnprintf を使うと、可変長引数(...)をそのままバッファに展開できる
// sizeof(log_buf) を指定することで、配列のサイズを超えてメモリを壊す心配もありません
int len = vsnprintf(log_buf, sizeof(log_buf), format, args);
va_end(args);
// 文字列の組み立てに成功していれば送信
if (len > 0)
{
g_uart1_tx_end = 0; // 送信開始(ビジー状態にする)
R_Config_UART1_Send((uint8_t *)log_buf, len); // 割り込みに丸投げして即離脱!
}
}
}
int main(void)
{
EI();
R_Config_UART1_Create();
R_Config_UART1_Start();
g_uart1_tx_end = 1;
while(1)
{
SerialPrintf("%d %d\r\n", 0, 1);
}
return 0;
}
...自分が使っているライター(E2 lite)にはコムポート機能が無いらしい。というか、RL78-G23はTOOL0ピンという半二重なピンを用いて書き込みを行い、普通のシリアルとは少し違う?らしい?
arduino種ばかり触ってきたので、書き込み器があればシリアルできると思い込んでいたが。
適当なシリアル-USB変換器を挟んでデバッグすることにした。
SPI(CSI)
scfgのコンポーネント>シリアル・アレイユニットからSPI(CSI)を追加。
動作、リソースを目的に合わせて設定。今回は送受信、使用するのは01ポートとする。
SPIの設定。
端子タブを開くと、(今回はSAU1に)設定した通りの端子割り当てがされていることを確認できる。備考欄に「この端子を初期化するコンポーネントが割り振られていません」と書かれていないことをチェック。コンソールにscfgによる端子割り当てのログが出ていたりするので、それも参考うに。
CSpinについては普通にGPIOで設定する。
以下、SPIでMCP3204と送受信するコードのサンプル。送信内容、受信分析を変えればあらかた他のSPIモジュールにも使えるだろう。
smc_gen>Config_CSI00内のConfig_CSI00_user.cに送信完了用のフラグ変数をつくる。codegeneraterのコメント指示がある場所に以下のように書き加える。
...
/* Start user code for global. Do not edit comment generated here */
volatile uint8_t g_csi_r_end = 0;
/* End user code. Do not edit comment generated here */
...
static void r_Config_CSI00_callback_receiveend(void)
{
/* Start user code for r_Config_CSI00_callback_receiveend. Do not edit comment generated here */
g_csi_r_end = 1;
/* End user code. Do not edit comment generated here */
}
main.cに送受信関数をつくる。
extern volatile uint8_t g_csi_r_end;//Config_CSI00_user.cで定義した送信完了フラグを外部参照
uint16_t MCP3204_Read(int ch) {
uint8_t tx_data[3];
uint8_t rx_data[3];
uint16_t adc_result = 0;
// 1. 送信データの準備 (引数 ch に応じてビットを生成)
tx_data[0] = 0x06; // スタートビット(1) + SGL/DIFF(1) + D2(0)
// 💡 ch (0〜3) の下位2ビットを取り出して、最上位(ビット7, 6)までシフトする
tx_data[1] = (uint8_t)((ch & 0x03) << 6);
tx_data[2] = 0x00; // ダミーデータ
// 2. チップセレクト(CS)ピンをLOWにする (通信開始)
g_csi_r_end = 0;
PIN_WRITE(CSpin) = 0;
// 3. 3バイトの送受信を実行
R_Config_CSI00_Send_Receive(tx_data, 3, rx_data);
// 通信完了を待つ
while (g_csi_r_end == 0)
{
// 転送完了待ち(一瞬で抜けます)
}
// 4. CSピンをHIGHに戻す (通信終了)
PIN_WRITE(CSpin) = 1;
// 5. 受信データから12ビット分を抽出する
adc_result = ((uint16_t)(rx_data[1] & 0x0F) << 8) | rx_data[2];
return adc_result;
}
↑見ての通りブロッキングな処理になっているので注意。
int main(void)
{
EI();
R_Config_PORT_Create();
R_Config_CSI00_Create();
R_Config_CSI00_Start();
volatile uint16_t res0=0;
volatile uint16_t res1=0;
while(1)
{
res0=MCP3204_Read(0);
res1=MCP3204_Read(1);
}
return 0;
}
あとはmain内で呼び出してやって完成。
ほかやること
・デバッグ機能深堀り
・単体動作どうするの?
ガチ余談(どうでもいい)
ずっと気になってるんだけど、コード生成で生まれるファイルのコメントアウトにRenesasのコピーライトが記載されているが、e2studioのtypo検知がRinsesに訂正しようとしてくる...。



