43
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

最強の100円マイコンR8C/M12A、M11A

Last updated at Posted at 2021-10-08

M12A11A.jpg

何故最強と言えるのか?

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

IMG_0135s.jpg

R8C_Writer.png

上記回路のように 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 が便利です!

vscode_scs.jpg

GitHub の R8C のルートを開くようなショートカットを用意してプロジェクトを開始できるように、R8C/.vscode 以下に専用の設定ファイルを置いてあります。

vsc_sc_propaty.png

むすび

現実には、もっと安いマイコンは数多くありますが、通常、プログラム容量とコストは比例するものです。

それと、内蔵しているペリフェラルもかなり充実している事から、かなり色々なガジェットに応用が出来るものと思います。

C/C++ でプログラム開発が出来て、入門用教材としても優れています。
※手持ちの USB シリアルがあれば、100 円で、ガジェットを作成可能です!

43
36
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?