BluePill(STM32F103C)でデータを保存する
BluePill はこれ
https://www.amazon.co.jp/dp/B01CZL6RGC/ref=cm_sw_em_r_mt_dp_U_OMcgFbSNZDFBN
以下、やったこと
BluePillのArduino化
こちらのサイトを参考にしました。
https://ht-deko.com/arduino/stm32f103c8t6.html
で、ST-link使ってブートローダも入れました。
Arduinoでデータ保存ができるか調べた
Arduinoは、EEPROMにデータを保存して電源が切れてもデータを維持できるらしい。
でも、BluePillには無いらしい。
かわりにチップ内のフラッシュメモリを利用してEEPROMをエミュレートできるらしい。
やってみた。
基本的なことは、
hardware>Arduino_STM32>STM32F1>libraries>EEPROM>EEPROM_example
にサンプルがあったので、それをちょっといじるだけでした。
# include <EEPROM.h>
int ledPin = PC13; // LED connected to digital pin 13
const char HELP_MSG[] = "Press :\r\n" \
" 0 display configuration\r\n" \
" 1 set configuration to 0x800F800 / 0x800FC00 / 0x400 (64k flash)\r\n" \
" 2 set configuration to 0x801F800 / 0x801FC00 / 0x400 (128k flash)\r\n" \
" 3 write/read variable\r\n" \
" 4 increment address\r\n" \
" 5 display pages top/bottom\r\n" \
" 6 initialize EEPROM\r\n" \
" 7 format EEPROM\r\n" \
" 9 read variable\r\n";
uint16 DataWrite = 0;
uint16 AddressWrite = 0x10;
void setup()
{
// initialize the digital pin as an output:
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
delay(10000);
Serial.print(HELP_MSG);
}
void loop()
{
uint16 Status;
uint16 Data;
while (Serial.available())
{
char cmd = (char)Serial.read();
Serial.println(cmd);
if (cmd == '0')
{
DisplayConfig();
}
else if (cmd == '1')
{
EEPROM.PageBase0 = 0x800F800;
EEPROM.PageBase1 = 0x800FC00;
EEPROM.PageSize = 0x400;
DisplayConfig();
}
else if (cmd == '2')
{
EEPROM.PageBase0 = 0x801F800;
EEPROM.PageBase1 = 0x801FC00;
EEPROM.PageSize = 0x400;
DisplayConfig();
}
else if (cmd == '3')
{
Status = EEPROM.write(AddressWrite, DataWrite);
Serial.print("EEPROM.write(0x");
Serial.print(AddressWrite, HEX);
Serial.print(", 0x");
Serial.print(DataWrite, HEX);
Serial.print(") : Status : ");
Serial.println(Status, HEX);
Status = EEPROM.read(AddressWrite, &Data);
Serial.print("EEPROM.read(0x");
Serial.print(AddressWrite, HEX);
Serial.print(", &..) = 0x");
Serial.print(Data, HEX);
Serial.print(" : Status : ");
Serial.println(Status, HEX);
++DataWrite;
}
else if (cmd == '9')
{
Status = EEPROM.read(AddressWrite, &Data);
Serial.print("EEPROM.read(0x");
Serial.print(AddressWrite, HEX);
Serial.print(", &..) = 0x");
Serial.print(Data, HEX);
Serial.print(" : Status : ");
Serial.println(Status, HEX);
}
else if (cmd == '4')
{
++AddressWrite;
}
else if (cmd == '5')
{
DisplayPages(0x20);
DisplayPagesEnd(0x20);
}
else if (cmd == '6')
{
Status = EEPROM.init();
Serial.print("EEPROM.init() : ");
Serial.println(Status, HEX);
Serial.println();
}
else if (cmd == '7')
{
Status = EEPROM.format();
Serial.print("EEPROM.format() : ");
Serial.println(Status, HEX);
}
else
Serial.print(HELP_MSG);
}
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
}
void DisplayConfig(void)
{
Serial.print ("EEPROM.PageBase0 : 0x");
Serial.println(EEPROM.PageBase0, HEX);
Serial.print ("EEPROM.PageBase1 : 0x");
Serial.println(EEPROM.PageBase1, HEX);
Serial.print ("EEPROM.PageSize : 0x");
Serial.print (EEPROM.PageSize, HEX);
Serial.print (" (");
Serial.print (EEPROM.PageSize, DEC);
Serial.println(")");
}
void DisplayHex(uint16 value)
{
if (value <= 0xF)
Serial.print("000");
else if (value <= 0xFF)
Serial.print("00");
else if (value <= 0xFFF)
Serial.print("0");
Serial.print(value, HEX);
}
void DisplayPages(uint32 endIndex)
{
Serial.println("Page 0 Top Page 1");
for (uint32 idx = 0; idx < endIndex; idx += 4)
{
Serial.print (EEPROM.PageBase0 + idx, HEX);
Serial.print (" : ");
DisplayHex(*(uint16*)(EEPROM.PageBase0 + idx));
Serial.print (" ");
DisplayHex(*(uint16*)(EEPROM.PageBase0 + idx + 2));
Serial.print (" ");
Serial.print (EEPROM.PageBase1 + idx, HEX);
Serial.print (" : ");
DisplayHex(*(uint16*)(EEPROM.PageBase1 + idx));
Serial.print (" ");
DisplayHex(*(uint16*)(EEPROM.PageBase1 + idx + 2));
Serial.println();
}
}
void DisplayPagesEnd(uint32 endIndex)
{
Serial.println("Page 0 Bottom Page 1");
for (uint32 idx = EEPROM.PageSize - endIndex; idx < EEPROM.PageSize; idx += 4)
{
Serial.print (EEPROM.PageBase0 + idx, HEX);
Serial.print (" : ");
DisplayHex(*(uint16*)(EEPROM.PageBase0 + idx));
Serial.print (" ");
DisplayHex(*(uint16*)(EEPROM.PageBase0 + idx + 2));
Serial.print (" ");
Serial.print (EEPROM.PageBase1 + idx, HEX);
Serial.print (" : ");
DisplayHex(*(uint16*)(EEPROM.PageBase1 + idx));
Serial.print (" ");
DisplayHex(*(uint16*)(EEPROM.PageBase1 + idx + 2));
Serial.println();
}
}
LEDのピン番号を修正したりした程度で、プログラムはあまり変えてません。(読み取りだけの機能は追加しました)
ただ、元のサンプルではアドレスが違っていたようで保存が出来なかったので、下記URLを参考に変えました。
フラッシュメモリはプログラムも書き込まれる場所なので、後ろの2ページ(2kバイト)を保存領域にするようです。
うちのBluePillは64kだったようなので、0x800F800と0x800FC00になるみたいでした。
上記プログラムを実行すると、HELPがシリアルモニタにでるので、64kの場合は1をセット、128kの場合は2をセットして、そのあと3をセットすることで保存と呼び出し(プラスデータの値を1加算)することができます。
あとは、電源を切って、もう一度起動して、1(または2)をセットしてから、9(呼び出しのみ)をするとちゃんとデータが保存できてました!
これで、サーボの初期パラメータを保存できる♪