使ったボード
雑誌の付録.
当時はHEWを利用して開発するのが主流だったようだが,Windows10マシンにHEWを入れるのは気が引けるので,e2studio + gcc(Renesas拡張) をメインに進めたい.
ボードにはレギュレータやUSB(残念ながらmini USB)など一通り必要なものは付いているので,USBケーブル1本で始められる.
SoCはRX62N 144Pin
SoCとして,R5F562N7BDFBが付いている.
CPUコアはRXv1で,最高動作周波数は100MHz.
144ピンのSoCで,I/Oは103ピンあり,
入力プルアップ抵抗内蔵:ポート9,A,B,C,D,E,G
オープンドレイン出力:ポート0,1,2,3(P30~P34),C
5Vトレラント対応端子:ポート0(P00,P01,P02,P07),ポート1(P12,P13,P16,P17),ポート2(P20,kP21),ポート3(P33)
(上記ボードには12MHzの水晶が載っている)
開発環境
- Windows10
- e2studio(gnurx)
- Renesas Flash Programmer V3.01
少し古いSoCなので,e2studio+gnurxでの開発情報がなかなか見つけられない(当時はHEW).動作確認が取れた方法を,ここに記しておく.
PCとはUSBケーブルで接続する
このSoCはUSB接続でプログラムを書き込む機能が付いている(DFUみたいなものか?)
MD0ピンをGNDに落とした状態でリセットすると,Bootモードになる.その状態でデバイスマネージャーに上記のデバイスが表示されれば,Windowsに認識されている.
ボードへの電源供給も,USBから行える.
e2studioでプロジェクトを作る
まずはLチカ
まずはLチカで動作を確かめる.ボード上にチップLEDが1つ用意されている.P15に接続されている.
以下,ソースコードの抜粋.
int main(void) {
PORT1.DDR.BIT.B5 = 1;
while(1) {
PORT1.DR.BIT.B5 ^= 1;
for(int i=0; i < 1000000; i++);
// TODO: add application code here
}
return 0;
}
Lチカするソースコードをe2studioに用意し,Renesas Flash Programmerで書き込んでみる.
e2studioでプロジェクトを作りビルドする
「プロジェクト」-「プロパティ」と開き,下記の様にコンパイラを指定してから,ビルドする.
HardwareDebugフォルダに生成物ができる.
Renesas Flash Programmerで書き込む
1:プロジェクトを作る(e2studioのプロジェクトとは関係ない)
2:ツールはUSB Directを選ぶ
3: メインクロックを設定する
4:接続に成功した画面(まだプログラムは書き込んでいない)
プログラムファイルとして.mot
形式のファイルを選択し,「スタート」をクリックすると書き込める.
サンプル・プログラム
サンプル:タイマーでLチカ
#include <iodefine.h>
#include <interrupt_handlers.h>
#define PCLK 48
volatile unsigned int utimer;
void initTimer(void){
MSTP(CMT1) = 0;
CMT1.CMCR.WORD = 0x0040;
CMT1.CMCOR = PCLK*1000000L/1000000L/8L - 1;
ICU.IER[IER_CMT1_CMI1].BIT.IEN_CMT1_CMI1 = 1;
ICU.IPR[IPR_CMT1_CMI1].BYTE = 8;priority level
CMT.CMSTR0.WORD |= 0x0002;
utimer = 0;
}
unsigned int getTimer(void){
return utimer;
}
void delay_us(unsigned int us){
utimer = 0;
while(utimer <= us);
}
void init(){
PORT1.DDR.BIT.B5 = 1; //On Board LED
}
int main(void) {
init();
initTimer();
while(1) {
PORT1.DR.BIT.B5 ^= 1;
delay_ms(1000);
}
return 0;
}
extern unsigned int utimer;
:
//;0x0074 CMTU0_CMT1
void INT_Excep_CMT1_CMI1(void){utimer++; }
:
サンプル:キャラクタ・ディスプレイSC1602
デバイス
家に一杯あったのでこれを使った.5V品だったので,Write専用で使うことにする.
上記「タイマーでLチカ」の,タイマー部分を切り出しtimer.c
とtimer.h
とした.
LCDドライバ
参考サイト(4)を参考にさせていただいて,ポーティングした.
#include "lcd.h"
#include "timer.h"
#include <iodefine.h>
void DelayTCYx(int tick){
delay_us(tick);
}
void lcd_init(void){
DelayTCYx(15000); // 15ms*(48MHz/4)=180,000
LCD_RS=0;
lcd_out4( LCD_FUNCM | LCD_8BIT ); // 8bit
DelayTCYx(5000); // 5ms*(48MHz/4)= 60,000
lcd_out4( LCD_FUNCM | LCD_8BIT ); // 8bit
DelayTCYx(4000); // 4ms*(48MHz/4)= 48,000
lcd_out4( LCD_FUNCM | LCD_8BIT ); // 8bit
DelayTCYx(4000); // 4ms*(48MHz/4)= 48,000
lcd_out4( LCD_FUNCM | LCD_4BIT); // 4bit
DelayTCYx(4000); // 4ms*(48MHz/4)= 48,000
lcd_out8( LCD_FUNCM | LCD_4BIT | 0b1000 );
DelayTCYx(4000); // 4ms*(48MHz/4)= 48,000
lcd_out8( LCD_DISPM | LCD_DISPON | LCD_CURON | LCD_BLINKOFF );
DelayTCYx( 167);
lcd_out8( LCD_ENTRYM | LCD_INC | LCD_NONSHIFT);
DelayTCYx( 167); // 0.167ms*(48MHz/4)= 2,000
lcd_clear();
}
void lcd_clear(void){
LCD_RS=0;
lcd_out8( LCD_CLEAR );
DelayTCYx(2000); // 2ms*(48MHz/4)= 24,000
}
void lcd_en(unsigned char d){
LCD_RS=0;
lcd_out8( LCD_DISPM | d);
DelayTCYx(40); // 40μs*(48MHz/4)= 480
}
void lcd_puts(const char* buf){
LCD_RS=1;
while(*buf){
lcd_out8(*buf);
DelayTCYx(50); // 50μs*(48MHz/4)= 600
++buf;
}
}
void lcd_putc(unsigned char c){
LCD_RS=1;
lcd_out8(c);
DelayTCYx(50); // 50μs*(48MHz/4)= 600
}
void lcd_ddram(unsigned char ads){
LCD_RS=0;
lcd_out8( LCD_DDADS | ads );
DelayTCYx(40); // 40μs*(48MHz/4)= 480
}
void lcd_ddramxy(unsigned char x,unsigned char y){
unsigned char ads = 0x40*y - (2<=y ? (0x40*2-0x14) : 0)+x;
lcd_ddram(ads);
}
void lcd_cgram(unsigned char ads,unsigned char* buf){
LCD_RS=0;
lcd_out8( LCD_CGADS | ads );
DelayTCYx(40); // 40μs*(48MHz/4)= 480
LCD_RS=1;
for(int n=0;n<8;n++){
lcd_out8( buf[n] );
DelayTCYx(40); // 40μs*(48MHz/4)= 480
}
}
void lcd_disp(const unsigned char* buf){
const unsigned char* p=buf;
unsigned char x=0;
unsigned char y=0;
LCD_RS=0;
lcd_out8( LCD_CURHOME );
DelayTCYx(2000); // 2ms*(48MHz/4)= 24,000
LCD_RS=1;
while(*p){
if(x==LCD_CMAX || *p=='\n'){
++y;
lcd_ddramxy(0,y);
DelayTCYx(50); // 50μs*(48MHz/4)= 600
LCD_RS=1;
x=0;
}
if(*p!='\n'){
lcd_out8(*p);
DelayTCYx(50); // 50μs*(48MHz/4)= 600
++x;
}
++p;
}
}
void lcd_out4(unsigned char data){
unsigned char t1;
PORT6.DR.BIT.B7 = (data & 0x20) >> 5;
PORT6.DR.BIT.B6 = (data & 0x40) >> 6;
PORT6.DR.BIT.B5 = (data & 0x80) >> 7;
PORT0.DR.BIT.B1 = (data & 0x10) >> 4;
LCD_E=1;
DelayTCYx(5);
LCD_E=0;
}
void lcd_out8(unsigned char data){
lcd_out4(data);
lcd_out4(data<<4);
}
サンプル:PWM
MTU4
MTU4は,主に相補PWMなどで使うチャネルのようである.
幾つかモードがある.ここではシンプルなPWMモード1(P.939)で使う.
このモードでは2つのレジスタを使い,Duty比とサイクルタイム(PWM周波数の逆数)を設定する.
試した感じでは,MTIOC4A-A端子からモード1でPWM信号を出すだけでも,MTU4.TIORH.BIT.IOB=0x01
の設定が必須だった.
関係するレジスタ
iodefine.hのレジスタ名 | 通称 | 機能 | ページ |
---|---|---|---|
MTUA.TRWER.BIT.RWE | RWE | レジスタ書込み許可 | 984 |
MTUA.TSTR.BIT.CST4 | CST4 | 1でタイマスタート | |
MTUA.TOER.BIT.OE4A | OE4A | MTU出力許可(MTIOC4A) | 903 |
IOPORT.PFCMTU.BIT.MTUS4 | MTUS4 | ||
MTU4.TCR.BIT.CCLR | CCLR | カウンタクリア選択 | 873 |
MTU4.TCR.BIT.CKEG | CKEG | カウントエッジ選択(立上り/立下り) | 873 |
MTR4.TCR.BIT.TPSC | TPSC | タイマプリスケーラ選択 | 873, 875 |
MTU4.TCNT | TCNT | カウンタ | |
MTU4.TMDR.BIT.MD | タイマの動作モード選択 | 876 | |
MTU4.TIORH.BIT.IOA | IOA | MTIOC4A端子の機能(コンペアマッチでHigh/Low/トグル/出力禁止) | 878, 886 |
MTU4.TIORH.BIT.IOB | IOB | MTIOC4B端子の機能 | 878, 882 |
MTU4.TIORL.BIT.IOC | IOC | MTIOC4C端子の機能 | 887 |
MTU4.TGRA | TGRA | コンペアマッチのターゲット | |
MTU4.TGRB | TGRB | コンペアマッチのターゲット | |
MTU4.TGRC | TGRC | コンペアマッチのターゲット |
プログラム
void pwm4_init(){
MTUA.TRWER.BIT.RWE = 1; //レジスタ書込み禁止解除
MSTP(MTU4) = 0; //MTU4電源ドメインON
MTUA.TSTR.BIT.CST4 = 0; //タイマを停止
MTUA.TOER.BIT.OE4A = 1; //MTIOC4A選択
IOPORT.PFCMTU.BIT.MTUS4 = 0;
MTU4.TCR.BIT.TPSC = 0x02;
MTR4.TCR.BIT.CKEG = 0x00; //立ち上がりカウント選択
MTR4.TCR.BIT.CCLR = 0x01; //TGRBのコンペアマッチでクリア
MTU4.TCNT = 0x0000;
MTU4.TMDR.BYTE = 0x02; //PWMモード1
MTU4.TIORH.BIT.IOA = 0x01; //カウンタリセット
MTU4.TIORH.BIT.IOB = 0x02; //
MTU4.TIORL.BIT.IOC = 0x00;
MTU4.TGRA = 0x0600; //PWMサイクル設定
MTU4.TGRB = 0x0300; //Duty設定
//MTU4.TGRC = 0x0600;
MTUA.TSTR.BIT.CST4 =1; //タイマスタート
}
サンプル:UART
Renesasアプリケーションノート‥(1)
https://www.renesas.com/us/ja/document/apn/934691
SCI0でUARTを使う解説‥(2)
https://blog.goo.ne.jp/lm324/e/29f9d9a1c17cd38d2f4261e1b0ac4652
(2)のページで紹介されているプログラムを利用させていただく.
以下の割り込み関数をinthandler.c
に移す.
void INT_Excep_SCI0_ERI0(void)
void INT_Excep_SCI0_RXI0(void)
void INT_Excep_SCI0_TXI0(void)
関連する変数をinthandler.c
内でextern宣言する.
SCI0は,GPIO20
(TxD0)37ピンとGPIO21
(RxD0)36ピンに割り当てられている.これらは5VトレラントなのでUSB-シリアル変換などで動作確認しやすい.
サンプル:ADC
ソフトウェア・スタートでADCを使う.AD0.ADCSR.BIT.ADST=1
によってワンショットでADCする.
ADCできるとAD0.ADCSR.BIT.ADST==0
になる.
関係するレジスタ
iodefine.hのレジスタ名 | 通称 | 機能 | ページ |
---|---|---|---|
AD0.ADCSR.BIT.CH | CH | ADチャネル設定 | 1708 |
AD0.ADCSR.BIT.ADST | ADST | ADスタート | 1708 |
AD0.ADCR.BIT.MODE | MODE | 動作モード選択 | 1710 |
AD0.ADCR.BIT.CKS | CKS | クロック選択 | 1710 |
AD0.ADCR.BIT.TRGS | TRGS | トリガ選択 | 1710 |
AD0.ADDPR.BIT.DPSEL | DPSEL | LSB/MSB選択 | 1711 |
AD0.ADDRA | ADDR | データレジスタ(AN0) | 1707 |
AD0.ADDRB | ADDR | データレジスタ(AN1) | 1707 |
AD0.ADDRC | ADDR | データレジスタ(AN2) | 1707 |
AD0.ADDRD | ADDR | データレジスタ(AN3) | 1707 |
プログラム
void initAD(){
MSTP(AD0) = 0;
AD0.ADCSR.BIT.CH = 0x01; //for using AN1
AD0.ADCR.BIT.MODE = 0x00;
AD0.ADCR.BIT.CKS = 0x03;
AD0.ADDPR.BIT.DPSEL = 0; //LSB
}
int main(void) {
initAD();
while(1) {
/* ADC */
AD0.ADCSR.BIT.ADST = 1; //ADC Start
for(int i=0; i<100; i++);
for(; AD0.ADCSR.BIT.ADST;) //Waiting for ADC done
for(int i=0; i<100; i++);
contrastAD = AD0.ADDRB >> 2;
float rating = contrastAD / 256.0f;
}
return 0;
}
サンプル:USB PCDC(USB UART)
Renesasのサンプル・プログラムを動かす.日本語ドキュメントが付属しており,プログラムの動きの解説がとても分かりやすい.ただし,サンプルのe2studio用プロジェクトはコンパイラがCCRXとなる.
●RXファミリ USB Peripheral Communication Device Class Driver (PCDC)
https://www.renesas.com/jp/ja/document/scd/rx-family-usb-peripheral-communication-device-class-driver-pcdc-sample-code?language=ja&r=1054421
このサンプルは,「RX62NのUART」と「RX62NのUSB PCDC」間でテキストをフォワードするもの.
ダウンロードデータ内には,サンプルプログラムの流れが分かりやすく書いてあるので,読んでおくとよい.
サンプルには,ECHO
とUART
という2つが含まれている.
ここでは,UART
サンプルを利用する.まずRXが外部とUARTで通信する処理を削除する.そしてUSB経由(UART)でPCのターミナルにメッセージを投げられる機能だけを残す.ついでに関数化してmainループから利用しやすくする.
USBケーブルだけでデバッグメッセージを表示できるようになるので便利です.
作り方
「RXファミリ USB Peripheral Communication Device Class Driver (PCDC)」をダウンロードし,e2studioでプロジェクトを読み込む.
複数のRenesas提供のサンプルプログラムを使っていると,プロジェクト名が,被ってしまうので,名称を変えておく(どのサンプルもプロジェクト名が全部RX62Nなので,変えておかないと新しいものを読み込めなくなる).
r_usb_pcdc_uart_apl.h
,r_usb_pcdc_uart_apl.c
,main.c
を編集する.
前述の通り,2つのサンプルから選択する.具体的にはr_usb_pcdc_apl_config.h
のサンプル選択の#define
行を#define OPERATION_MODE (USB_UART)
とする.
CCRXでコンパイル.
API
次のように関数化した.
API | 機能 | ファイル |
---|---|---|
void usb_init(void) | 初期化 | r_usb_pcdc_apl.c |
void usb_loop(void) | ループ処理(定期的に呼ぶ) | r_usb_pcdc_apl.c |
uint8_t usb_message[32] | USB-UART経由で投げるメッセージ | r_usb_pcdc_apl.c |
#include <string.h>
#include "r_usb_basic_if.h"
#include "r_usb_pcdc_if.h"
#include "r_usb_pcdc_apl_config.h"
#if defined(USE_LPW)
#include "r_usb_rsk_lowpower.h"
#endif /* defined(USE_LPW) */
#define NUM_STRING_DESCRIPTOR (7u)
#define USB_ECHO (0) /* Loop back(Echo) mode */
#define USB_UART (1) /* USB Serial(VCOM) converter mode */
#define DATA_LEN (64)
/* LINE_CODING request wLength */
#define LINE_CODING_LENGTH (0x07u)
extern uint8_t g_apl_device[];
extern uint8_t g_apl_configuration[];
extern uint8_t *g_apl_string_table[];
void usb_init (void);
void usb_loop(void);
#include "r_usb_pcdc_apl.h"
#include "stdio.h"
#if OPERATION_MODE == USB_UART
#include "r_sci_rx_if.h"
#include "r_usb_rsk_sci.h"
static void apl_init(void);
static void usb_pin_setting(void);
static uint8_t g_usb_data[DATA_LEN];
static uint8_t g_sci_data[DATA_LEN];
static uint8_t g_is_usb_bulk_writing;
static uint8_t g_is_usb_interrupt_writing;
static usb_pcdc_linecoding_t g_line_coding;
const static usb_descriptor_t usb_descriptor = { g_apl_device, /* Pointer to the device descriptor */
g_apl_configuration, /* Pointer to the configuration descriptor for Full-speed */
USB_NULL, /* Pointer to the configuration descriptor for Hi-speed */
USB_NULL, /* Pointer to the qualifier descriptor */
g_apl_string_table, /* Pointer to the string descriptor table */
NUM_STRING_DESCRIPTOR };
uint8_t g_is_serial_state;
uint8_t g_serial_state[2];
sci_hdl_t console;
void R_USB_PinSet_USB0_PERI(void);
void R_USB_PinSet_USB1_PERI(void);
usb_ctrl_t ctrl;
usb_cfg_t cfg;
usb_err_t err;
uint8_t usb_message[32] = "";
void usb_init(void) {
apl_init(); /* Application program initialization */
usb_pin_setting(); /* USB MCU pin setting */
USB_RSK_SCI_INIT();
ctrl.module = USE_USBIP;
ctrl.type = USB_PCDC;
cfg.usb_speed = USB_SUPPORT_SPEED; /* USB_HS/USB_FS */
cfg.usb_mode = USB_PERI;
cfg.p_usb_reg = (usb_descriptor_t*) &usb_descriptor;
R_USB_Open(&ctrl, &cfg); /* Initializes the USB module */
}
void usb_loop(void) {
switch (R_USB_GetEvent(&ctrl)) {
case USB_STS_CONFIGURED:
g_is_usb_bulk_writing = USB_NO;
g_is_usb_interrupt_writing = USB_NO;
ctrl.type = USB_PCDC;
R_USB_Read(&ctrl, g_usb_data, DATA_LEN);
break;
case USB_STS_WRITE_COMPLETE:
if (USB_PCDC == ctrl.type) {
/* Bulk IN(CDC data) transfer has been completed */
g_is_usb_bulk_writing = USB_NO;
} else {
/* Interrupt IN(SerialState) transfer has been completed */
g_is_usb_interrupt_writing = USB_NO;
}
break;
case USB_STS_REQUEST: /* Receive Class Request */
if (USB_PCDC_SET_LINE_CODING == (ctrl.setup.type & USB_BREQUEST)) {
ctrl.type = USB_REQUEST;
R_USB_Read(&ctrl, (uint8_t*) &g_line_coding, LINE_CODING_LENGTH);
} else if (USB_PCDC_GET_LINE_CODING
== (ctrl.setup.type & USB_BREQUEST)) {
ctrl.type = USB_REQUEST;
R_USB_Write(&ctrl, (uint8_t*) &g_line_coding, LINE_CODING_LENGTH);
} else {
}
break;
case USB_STS_REQUEST_COMPLETE: /* Complete Class Request */
if (USB_PCDC_SET_LINE_CODING == (ctrl.setup.type & USB_BREQUEST)) {
/* RS-232C Line set.(Parameter : line_coding) */
usb_cpu_Sci_Set1(&g_line_coding);
} else if (USB_PCDC_GET_LINE_CODING
== (ctrl.setup.type & USB_BREQUEST)) {
/* none */
} else if (USB_PCDC_SET_CONTROL_LINE_STATE
== (ctrl.setup.type & USB_BREQUEST)) {
} else {
}
break;
case USB_STS_SUSPEND:
case USB_STS_DETACH:
#if defined(USE_LPW)
low_power_mcu();
#endif /* defined(USE_LPW) */
break;
case USB_STS_NONE:
if (USB_NO == g_is_usb_bulk_writing) {
ctrl.type = USB_PCDC;
err = R_USB_Write(&ctrl, usb_message, 32);
if (USB_SUCCESS == err) {
g_is_usb_bulk_writing = USB_YES;
}
}
/* SCI Error -> USB Notification */
if (USB_NO == g_is_usb_interrupt_writing) {
/* Check whether the SerialState information is or not*/
if (0 != g_is_serial_state) {
/* Send the SerialState information for SCI to USB Host */
ctrl.type = USB_PCDCC;
err = R_USB_Write(&ctrl, (uint8_t*) &g_serial_state, 2);
if (USB_SUCCESS == err) {
g_is_usb_interrupt_writing = USB_YES;
g_is_serial_state = 0;
}
}
}
break;
default:
break;
}
}
static void apl_init(void) {
memset((void* )&g_line_coding, 0, sizeof(usb_pcdc_linecoding_t));
memset(g_usb_data, 0, DATA_LEN);
memset(g_sci_data, 0, DATA_LEN);
memset(g_serial_state, 0, 2);
memset(console, 0, sizeof(sci_hdl_t));
g_is_usb_bulk_writing = USB_NO;
g_is_usb_interrupt_writing = USB_NO;
g_is_serial_state = 0;
} /* End of function apl_init */
static void usb_pin_setting(void) {
#if USE_USBIP == USB_IP0
R_USB_PinSet_USB0_PERI();
#else /* USE_USBIP == USE_USBIP0 */
R_USB_PinSet_USB1_PERI();
#endif /* USE_USBIP == USE_USBIP0 */
} /* End of function usb_pin_setting */
#endif /* OPERATION_MODE == USB_UART */
使い方
mainプログラムからは,次のように使う.
この例では,ADCのデータをUSB経由で順次PCに送っている.
#include "r_usb_basic_if.h"
#include "stdio.h"
#include "r_usb_pcdc_apl.h"
uint16_t ADValue;
extern uint8_t usb_message[32]; //表示したいメッセージを設定する
void initAD(){
MSTP(AD0) = 0;
AD0.ADCSR.BIT.CH = 0x01;
AD0.ADCR.BIT.MODE = 0x00;
AD0.ADCR.BIT.CKS = 0x03;
AD0.ADDPR.BIT.DPSEL = 0; //LSB
}
void main (void)
{
PORT1.DDR.BIT.B5 = 1; //On Board LED
PORT1.DR.BIT.B5 = 0;
initAD();
usb_init(); //初期化
while(1){
for(int i=0; i<5000000; i++);
usb_loop(); //定期的に呼ぶ
/* ADC */
AD0.ADCSR.BIT.ADST = 1;
for(int i=0; i<100; i++);
for(; AD0.ADCSR.BIT.ADST;) /* wait adc complete */
for(int i=0; i<100; i++);
ADValue = AD0.ADDRB; /* valid AN0 MSB8 */
snprintf(usb_message, 16, " Value: %d \r\n", ADValue);
}
}
ハードウェアの初期化
動作クロックなどをデフォルトの設定から変えたい場合は,
generate/hwinit.c の HardwareSetup()に書く.
:
void HardwareSetup(void)
{
SYSTEM.SCKCR.LONG = 0x00C10100; //システムクロックなどの設定
/*
SCI.SMR.BYTE = 0;
SCI.SMR.BIT.CA = 1;
:
*/
}
参考サイト
(0)ユーザ―マニュアル
https://www.renesas.com/jp/ja/document/mah/rx62n-group-rx621-group-users-manual-hardware-rev140?language=ja&r=1054421
(1)データシート
https://www.renesas.com/us/en/document/dst/rx62nrx621-group-datasheet-rev140
(2)ビルドと書き込み
https://setoti.hatenablog.com/entry/rx_write
(3)
https://www.haljion.net/index.php/2019-11-13-03-27-18/119-2019-11-13-03-22-16/rx-62n/226-2019-11-18-00-17-25
(4)山本ワールド;LCDモジュール(SC1602) 4bitモードライブラリー
http://yamatyuu.net/computer/pic/usbio2/lcdc_lib1/index.html
(5)忘備録-備忘録
https://blog.goo.ne.jp/lm324/e/99f735aef942ce6b965cd2f985acdf73
(6)
https://www.elec-hobbyist.com/MicomMemo/RX62_Micom/RX62_Explana_2.html
(7)ソフトウェア開発日記,C言語で文字列・数値変換を行う方法
https://lightgauge.net/language/c-language/6946/