何故最強と言えるのか?
100円で買える史上最強のマイコンと言えば↑コレです。
でもー、ROMが2キロバイト、RAMが256バイトではなぁー・・・
とお嘆きの方々、コッソリ秘密を教えますw
カタログスペックでは、ROMサイズ2Kバイト、RAMサイズ256バイトとなっていますが、実際は・・
ROMサイズ64Kバイト、RAMサイズ1366バイトが存在し、実際に使えます。
これだけのスペックなら、何か小物を作る際には、ほとんど困る事も無く、パッケージがDIPなのもあって、気軽に利用できます。
製造中止品なので、在庫が無くなればそれでお終いですが、この事実があまり公になっていないのと、Arduino のような環境でプログラム出来ないので、イマイチ人気が無く、入手性も問題無いようです。
内蔵のペリフェラルもそこそこ充実していて、主な特徴をあげると・・
- 2.7V ~ 5.5V の電源電圧で動作
- 最大 20MHz 動作
- オンチップオシレータ
- 1K バイト x2 のデータフラッシュ
- 6チャネル10ビット A/D コンバーター内蔵(サンプルホールドあり)
- 2チャネルのコンパレーター
- 3チャネルのタイマー(RJ2、RB2、RC)
- UART(シリアルインターフェース)
これだけあれば応用次第で、かなり色々なアプリケーションにマッチします。
※I2C のインターフェースがありませんが、ソフトウェアー I2C ドライバーを使う事で、I2C デバイスを扱う事が出来ます。
開発環境
この R8C は、M32C のサブセット版で、gcc/M32C で開発が可能です。
※C++14 での実装を行っているので、ルネサス純正 C/C++ コンパイラではコンパイル出来ません。
今回、専用の C++ フレームワークを公開して、C++ でプログラミングが出来るようにしています。
また、ルネサス社純正のプログラマー(Renesas Flash Programmer Vx)では、カタログスペックを超えてプログラムを書き込む事が出来ない為、専用のプログラミングツールも公開しています。
詳しくは、GitHub のリンクを参照して下さい。
プログラムの書き込み方法
R8C/Mxx シリーズは、シリアルインターフェースを使ってプログラムを書き込む事が出来ます。
詳細は、github を参照して下さい。
安価な、USBシリアルなどを使って、簡単に書き込む事が出来ます。
マルチプラットホーム対応の R8C/Mxx フラッシュプログラマー r8c_prog を公開しています。
Uranus-W10./d/Git/R8C/PLUSE_INP_sample % r8c_prog
Renesas R8C Series Programmer Version 0.82b
Copyright (C) 2015, Hiramatsu Kunihito (hira@rvf-rc45.net)
usage:
r8c_prog[options] [mot file] ...
Options :
-d, --device=DEVICE Specify device name
-e, --erase Perform a device erase to a minimum
--erase-all, --erase-chip Perform rom and data flash erase
--erase-rom Perform rom flash erase
--erase-data Perform data flash erase
-i, --id=xx:xx:xx:xx:xx:xx:xx Specify protect ID
-P, --port=PORT Specify serial port
-a, --area=ORG,END Specify read area
-r, --read Perform data read
-s, --speed=SPEED Specify serial speed
-v, --verify Perform data verify
--device-list Display device list
-V, --verbose Verbose output
-w, --write Perform data write
--progress display Progress output
-h, --help Display this
上記回路のように 2 回路の SW を設ける事で、通常(RUN 側)動作時は、UART との通信として利用し、FLASH 書き込み時は(WRITE 側)にして、プログラムを書き込みます。
※ WRITE 時は「MODE」端子を LOW レベルにしています。
※回路図では、USB シリアルとの接続は、10ピンコネクタになっていますが、写真のボードでは、6ピンコネクタとしています。
※スイッチを切り替えたら、「RESET」を押して、モードを切り替えてから、プログラムします。
Uranus-W10./d/Git/R8C/FIRST_sample % make run
r8c_prog -d R5F2M120 --progress -e -w -v first_sample.mot
Erase: #####################################
Write: #####################################
Verify: #####################################
サンプルプログラム
このマイコン用にサンプルをいくつか用意していますので参考にして下さい。
プロジェクト | 概要 |
---|---|
FIRST_sample | LED点滅サンプル |
UART_sample | シリアルインターフェースの送信、受信サンプル |
TIMER_sample | タイマーRBのサンプル(インターバルタイマー) |
ADC_sample | A/D変換のサンプル |
DATA_FLASH_sample | データフラッシュの初期化、リード、ライト |
PWM_sample | タイマーRCのサンプル(PWM出力) |
RC_SERVO_sample | ラジコン用サーボの動作テスト(PWM、2出力) |
COMP_sample | コンパレーターのサンプル |
DS1371_sample | I2C RTC デバイスのサンプル(DS1371) |
DS3231_sample | I2C RTC デバイスのサンプル(DS3231) |
EEPROM_sample | I2C EEPROM デバイスのテスト |
VL53L0X_sample | I2C VL53K0X レーザー距離センサのサンプル |
SWITCH_sample | スイッチ入力テスト(チャタリング除去とトリガー判定) |
TOUCH_sample | タッチスイッチのテスト |
ENCODER_sample | エンコーダー入力テスト |
PLUSE_OUT_sample | タイマーRJを使ったパルス出力テスト |
PLUSE_INP_sample | タイマーRJを使った周波数計測テスト |
PLUSE_OUT_LCD | タイマーRJ、LCD、エンコーダ |
ARITH_sample | 文字列による計算式、評価サンプル |
MPU6050_sample | MPU6050 加速度、ジャイロ、センサー、サンプル |
BMP180_sample | Bosh BMP180 温度、標高、センサー、サンプル |
MAX7219_sample | LED ディスプレイ・ドライバー、サンプル |
MAX6675_sample | SPI 接続、k熱電対温度センサー、サンプル |
THERMISTOR_sample | サーミスターを使った温度検出、サンプル |
LCD_DOT_sample | 128x32 mono color graphics のテスト |
SD_sample | pFatFS を使った、SD カードのテスト |
RC_SERVO_tester | ラジコン用サーボのテスター(JR、又はフタバPWM出力、1チャネル用) |
USB_CHECKER | USB 電流、電圧チェッカー |
AD9833_sample | DDS デバイスのサンプル(AD9833) |
FIRST_sample を観てみる(LED 点滅)
コンパイル:
- C++14 でコンパイルしています。
- プロジェクトに含まれる Makefile は、独自の工夫がしてあり、「make」と入力するだけで、完全な従属規則生成など、自動化されています。
- この Makefile は IDE におけるプロジェクトファイルに相当するものです。
Uranus-W10./d/Git/R8C/FIRST_sample % make
mkdir -p release/; \
m32c-elf-g++ -MM -DDEPEND_ESCAPE -std=c++14 -Wall -Werror -Wno-unused-variable -fno-exceptions -Os -mcpu=r8c -DF_CLK=20000000 -I. -I../ -I../M120AN main.cpp \
| sed 's/main\.o:/release\/main.o release\/main.d:/' > release/main.d ; \
[ -s release/main.d ] || rm -f release/main.d
mkdir -p release/common/; \
m32c-elf-gcc -MM -DDEPEND_ESCAPE -std=gnu99 -Wall -Werror -Wno-unused-variable -fno-exceptions -Os -mcpu=r8c -DF_CLK=20000000 -I. -I../ -I../M120AN ../common/init.c \
| sed 's/init\.o:/release\/common\/init.o release\/common\/init.d:/' > release/common/init.d ; \
[ -s release/common/init.d ] || rm -f release/common/init.d
mkdir -p release/common/; \
m32c-elf-gcc -MM -DDEPEND_ESCAPE -std=gnu99 -Wall -Werror -Wno-unused-variable -fno-exceptions -Os -mcpu=r8c -DF_CLK=20000000 -I. -I../ -I../M120AN ../common/vect.c \
| sed 's/vect\.o:/release\/common\/vect.o release\/common\/vect.d:/' > release/common/vect.d ; \
[ -s release/common/vect.d ] || rm -f release/common/vect.d
mkdir -p release/common/; \
m32c-elf-as -c -I. -I../ -I../M120AN -o release/common/start.o ../common/start.s
mkdir -p release/common/; \
m32c-elf-gcc -c -std=gnu99 -Wall -Werror -Wno-unused-variable -fno-exceptions -Os -mcpu=r8c -DF_CLK=20000000 -I. -I../ -I../M120AN -o release/common/vect.o ../common/vect.c
mkdir -p release/common/; \
m32c-elf-gcc -c -std=gnu99 -Wall -Werror -Wno-unused-variable -fno-exceptions -Os -mcpu=r8c -DF_CLK=20000000 -I. -I../ -I../M120AN -o release/common/init.o ../common/init.c
mkdir -p release/; \
m32c-elf-g++ -c -std=c++14 -Wall -Werror -Wno-unused-variable -fno-exceptions -Os -mcpu=r8c -DF_CLK=20000000 -I. -I../ -I../M120AN -o release/main.o main.cpp
m32c-elf-gcc -mcpu=r8c -nostartfiles -Wl,-Map,first_sample.map -T ../M120AN/m120an.ld -o first_sample.elf release/common/start.o release/common/vect.o release/common/init.o release/main.o -lstdc++
m32c-elf-size first_sample.elf
text data bss dec hex filename
380 168 0 548 224 first_sample.elf
m32c-elf-objcopy --srec-forceS3 --srec-len 32 -O srec first_sample.elf first_sample.mot
m32c-elf-objdump -h -S first_sample.elf > first_sample.lst
ソースコード:
//=====================================================================//
/*! @file
@brief R8C LED 点滅 @n
LED は、P1_0(20)、P1_1(19)に接続(吸い込み点灯)@n
※M120AN(20)
@author 平松邦仁 (hira@rvf-rc45.net)
@copyright Copyright (C) 2017, 2021 Kunihito Hiramatsu @n
Released under the MIT license @n
https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
namespace {
// LED は '0' で点灯、'1' で消灯するように接続するので、LED クラスの論理を反転して定義する
typedef device::PORT<device::PORT1, device::bitpos::B0, false> LED0;
typedef device::PORT<device::PORT1, device::bitpos::B1, false> LED1;
}
int main(int argc, char *argv[])
{
using namespace device;
// クロック関係レジスタ・プロテクト解除
PRCR.PRC0 = 1;
// 高速オンチップオシレーターへ切り替え
OCOCR.HOCOE = 1;
utils::delay::micro_second(1); // >=30us(125KHz)
SCKCR.HSCKSEL = 1;
CKSTPR.SCKSEL = 1;
// LED 設定
{
LED0::DIR = 1;
LED1::DIR = 1;
}
// LED 点滅メイン
while(1) {
LED0::P = 0;
LED1::P = 1;
// 250ms (0.25s)
utils::delay::milli_second(250);
LED0::P = 1;
LED1::P = 0;
// 250ms (0.25s)
utils::delay::milli_second(250);
}
}
C++ フレームワークのおかげで、判りやすく直観的な操作で、プログラムを実装する事が出来ます。
クロック周波数のブースト
R8C/Mxx では、起動時、低い周波数で起動します。
以下の手順で、最高速度(20MHz)までブーストします。
using namespace device;
// クロック関係レジスタ・プロテクト解除
PRCR.PRC0 = 1;
// 高速オンチップオシレーターへ切り替え
OCOCR.HOCOE = 1;
utils::delay::micro_second(1); // >=30us(125KHz)
SCKCR.HSCKSEL = 1;
CKSTPR.SCKSEL = 1;
LED ポートの定義と動作
typedef device::PORT<device::PORT1, device::bitpos::B0, false> LED0;
typedef device::PORT<device::PORT1, device::bitpos::B1, false> LED1;
- 点滅に利用する LED を定義します。
「device::PORT」テンプレートクラスは、ポート、ビット位置のパラメーターを使って、1つのポートオブジェクトを定義しています。
3番目のパラメーターに「false」を渡す事で、反転入出力とする事が出来ます。
ポートに LED を吸い込みで点灯するように接続しても、「1」で LED が点灯、「0」で消灯するようにプログラム出来ます。
実際の出力は反転されて、1--->0、0--->1 となります。
- ポートを出力にするには
LED::DIR = 1;
- ポート出力を設定するには
LED::P = 1; // LED 点灯
LED::P = 0; // LED 消灯
- 今回は出力としていますが、ポートの入力状態を取得する場合は
auto n = LED::P();
などとします。
※Arduino のポート操作 API と異なり、PORT テンプレートクラスでは最適化が十分行われる為、以下のように、無駄なコードが殆ど出現しません。
80f8: 7e 9f 48 05 bset:g 0,0xa9 // LED0::DIR = 1;
80fc: 7e 9f 49 05 bset:g 1,0xa9 // LED1::DIR = 1;
8100: 7e 9f 78 05 bset:g 0,0xaf // LED0::P = 0;
8104: 7e 8f 79 05 bclr:g 1,0xaf // LED1::P = 1;
ソフトウェアー遅延
あまり正確では無いですが、ソフトウェアーによる遅延 API を用意してあります。
※20MHz で動作する前提でループファクターが調整されています。
※以下の場合は250ミリ秒(0.25秒)です。
// LED 点滅メイン
while(1) {
LED0::P = 0;
LED1::P = 1;
// 250ms (0.25s)
utils::delay::milli_second(250);
LED0::P = 1;
LED1::P = 0;
// 250ms (0.25s)
utils::delay::milli_second(250);
}
R8C/C++ フレームワークでは、デバイスの操作は、ハードウェアーマニュアルに沿った正確な名称を使っています。
VSC を使った開発
開発環境は、VSC が便利です!
GitHub の R8C のルートを開くようなショートカットを用意してプロジェクトを開始できるように、R8C/.vscode 以下に専用の設定ファイルを置いてあります。
むすび
現実には、もっと安いマイコンは数多くありますが、通常、プログラム容量とコストは比例するものです。
それと、内蔵しているペリフェラルもかなり充実している事から、かなり色々なガジェットに応用が出来るものと思います。
C/C++ でプログラム開発が出来て、入門用教材としても優れています。
※手持ちの USB シリアルがあれば、100 円で、ガジェットを作成可能です!