ArduinoのEEPROMに初期値を書いておきたいことってまれにある。が、じつはすんなりではない。書いてくれないぞっていう結果と、じゃぁどうやって書くかってのをメモっておく。
まずはこういうコードを書く。EEMEMってのがこれをEEPROMに入れるぜってことを示している。ちなみにPROGMEMってのはFlashにはいる。
eeprom_initial_value.ino
#include <avr/eeprom.h> #include <EEPROM.h> typedef struct tag_test_data_element_struct{ uint8_t upper:4; uint8_t lower:4; }test_data_element_struct_t; typedef union tag_test_data_struct{ uint8_t asByte; test_data_element_struct_t elm; }test_data_struct_t; typedef struct tag_test_struct{ uint8_t len; test_data_struct_t data[247]; uint8_t cmd1[4]; uint8_t cmd2[4]; }test_struct_t; volatile test_struct_t test_mem EEMEM = { 23,{ 0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x02,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x03,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x04,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x05,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x06,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x07,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x08,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x09,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0A,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0B,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0C,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0D,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0E,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0F,0x12,0x23,0x34,0x45,0x56,0x67,0x78},{0x01,0x02,0x03,0x04},{0xDE,0xAD,0xBE,0xEF} }; test_struct_t test_data; void setup(){ uint8_t d[256]; char line[100]; Serial.begin(115200); for(int i=0;i<256;i++){ d[i]=EEPROM.read(i); } for(int i=0;i<16;i++){ sprintf( line, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", d[i*16+0],d[i*16+1],d[i*16+2],d[i*16+3],d[i*16+4],d[i*16+5],d[i*16+6],d[i*16+7], d[i*16+8],d[i*16+9],d[i*16+10],d[i*16+11],d[i*16+12],d[i*16+13],d[i*16+14],d[i*16+15] ); Serial.println(line); } #if 0 EEPROM.get(0, test_data); Serial.println(test_data.len); for(int i=0;i<247;i++){ Serial.print(test_data.data[i].elm.upper); Serial.print("/"); Serial.println(test_data.data[i].elm.lower); } for(int i=0;i<4;i++){ Serial.print(test_data.cmd1[i]); } Serial.println(""); for(int i=0;i<4;i++){ Serial.print(test_data.cmd2[i]); } Serial.println(""); #endif } void loop(){ }
コンパイル結果が出力されるようにする。
.vscode/arduno.json
{ "board": "arduino:avr:uno", "port": "COM5", "sketch": "eeprom_initial_value.ino", "output": "../output" }
で、書き込んで、シリアルモニターを見ると、
書き込まれていないTT
ではコンパイル結果はどうなっているのか、
.eepファイルができていて、中身はそれらしい。つまり、書き込んでくれないんだよ。どうしたらいいのか、あまり情報がないんよー。ギブアップ。(下のほうの<悶絶の記録>参照)
どうすっか、、、
#include <avr/eeprom.h> #include <EEPROM.h> typedef struct tag_test_data_element_struct{ uint8_t upper:4; uint8_t lower:4; }test_data_element_struct_t; typedef union tag_test_data_struct{ uint8_t asByte; test_data_element_struct_t elm; }test_data_struct_t; typedef struct tag_test_struct{ uint8_t len; test_data_struct_t data[247]; uint8_t cmd1[4]; uint8_t cmd2[4]; }test_struct_t; test_struct_t test_mem = { 23,{ 0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x02,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x03,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x04,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x05,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x06,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x07,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x08,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x09,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0A,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0B,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0C,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0D,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0E,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0, 0x0F,0x12,0x23,0x34,0x45,0x56,0x67,0x78},{0x01,0x02,0x03,0x04},{0xDE,0xAD,0xBE,0xEF} }; void setup(){ uint8_t d[256]; char line[100]; EEPROM.put(0,test_mem); delay(100); Serial.begin(115200); for(int i=0;i<256;i++){ d[i]=EEPROM.read(i); } for(int i=0;i<16;i++){ sprintf( line, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", d[i*16+0],d[i*16+1],d[i*16+2],d[i*16+3],d[i*16+4],d[i*16+5],d[i*16+6],d[i*16+7], d[i*16+8],d[i*16+9],d[i*16+10],d[i*16+11],d[i*16+12],d[i*16+13],d[i*16+14],d[i*16+15] ); Serial.println(line); } } void loop(){ }
はい、実行時に書いちゃいます。(現実逃避ーー)
できた、、、
eepファイルを作る、そして書き込む、ってやりたかったが、まぁわからんのよ。いつか再挑戦するかもしれない。
<悶絶の記録=失敗>
コードの書き込みに使われているavrdudeはeepromも書き込めるので、書き込み用のtaskを作るという寝技でとりあえずやっつける。何かを設定することでコードの書き込みと同時にやってくれる方法があるのかもしれないけど、まぁわからんのよねー。
で、avrdudeでeepromを書き込むにはどうするか、
C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\bin\avrdude.exe -C "C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf" -p atmega328p -c arduino -v -P COM5 -b 115200 -U eeprom:w:"..\output\eeprom_initial_value.ino.eep":i
かなり長いけど、こうすればいいらしい。
これをtaskとして登録する。
Terminal-->Configure Tasks...
どれを選んでも大手術なので、一番内容が近そうなこいつを選ぶ。
こうなる。
{ "version": "2.0.0", "tasks": [ { "type": "shell", "label": "Write EEPROM", "command": "C:\\Users\\hoge\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avrdude\\6.3.0-arduino17\\bin\\avrdude.exe", "args": [ "-C","\"C:\\Users\\hoge\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avrdude\\6.3.0-arduino17\\etc\\avrdude.conf\"", "-p","atmega328p", "-v", "-U","eeprom:w:\"..\\output\\eeprom_initial_value.ino.eep\":i", "-c","arduino", "-P","COM5", "-b","115200" ], "options": { }, } ] }
こうする。
avrdudeの場所とか、はPCによって違うので、事前に確認しておく。
Terminal-->Run Task...
さっき作ったやつがいるのでつつく。
なんのこっちゃかわからんけど、こいつをつつく。
* Executing task in folder eeprom_initial_value: C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\bin\avrdude.exe -C "C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf" -p atmega328p -c arduino -v -P COM5 -b 115200 -U eeprom:w:"..\output\eeprom_initial_value.ino.eep":i
avrdude.exe: Version 6.3-20190619
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf"
Using Port : COM5
Using Programmer : arduino
Overriding Baud Rate : 115200
AVR Part : ATmega328P
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PC2
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 1024 4 0 3600 3600 0xff 0xff
flash 65 6 128 0 yes 32768 128 256 4500 4500 0xff 0xff
lfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
efuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
lock 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : Arduino
Description : Arduino
Hardware Version: 3
Firmware Version: 4.4
Vtarget : 0.3 V
Varef : 0.3 V
Oscillator : 28.800 kHz
SCK period : 3.3 us
avrdude.exe: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.02s
avrdude.exe: Device signature = 0x1e950f (probably m328p)
avrdude.exe: safemode: lfuse reads as 0
avrdude.exe: safemode: hfuse reads as 0
avrdude.exe: safemode: efuse reads as 0
avrdude.exe: reading input file "..\output\eeprom_initial_value.ino.eep"
avrdude.exe: writing eeprom (256 bytes):
Writing | ################################################## | 100% 2.05s
avrdude.exe: 256 bytes of eeprom written
avrdude.exe: verifying eeprom memory against ..\output\eeprom_initial_value.ino.eep:
avrdude.exe: load data eeprom data from input file ..\output\eeprom_initial_value.ino.eep:
avrdude.exe: input file ..\output\eeprom_initial_value.ino.eep contains 256 bytes
avrdude.exe: reading on-chip eeprom data:
Reading | ################################################## | 100% 2.05s
avrdude.exe: verifying ...
avrdude.exe: verification error, first mismatch at byte 0x0000
0xff != 0x17
avrdude.exe: verification error; content mismatch
avrdude.exe: safemode: lfuse reads as 0
avrdude.exe: safemode: hfuse reads as 0
avrdude.exe: safemode: efuse reads as 0
avrdude.exe: safemode: Fuses OK (E:00, H:00, L:00)
avrdude.exe done. Thank you.
* The terminal process "C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -Command C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\bin\avrdude.exe -C "C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf" -p atmega328p -c arduino -v -P COM5 -b 115200 -U eeprom:w:"..\output\eeprom_initial_value.ino.eep":i" terminated with exit code: 1.
* Terminal will be reused by tasks, press any key to close it.
ターミナルにこう出る。ベリファイ結果がおかしい。
実はやっているようで、やってない。なんでやー
会社は椅子取りゲームへの全員参加を推奨しています。本当は普通に毎日行きたいが全員分の座席がないやん。やる気というかいろいろ失せるわ。
コメントをお書きください