· 

ArduinoたちでI2C

 

Arduino同士でI2C通信してもらいます。
R4がMaster、R3がSlaveでR3はI2Cメモリーとして働いてもらいます。R4のI/Oが5Vなので、R3とレベル変換なしに通信できるのがいい。さすがルネ。

I2Cの接続はとても簡単です。SCL同士、SDA同士を接続するだけ。

wire_master_study1.ino

#include <stdint.h>
#include <Wire.h>

uint8_t slave_address = 0x55;
uint16_t slave_memadr[] = {0x0000, 0x0010, 0x0020, 0x0130};

void setup(void)
{
    Wire.begin();
    Serial.begin(115200);
}
uint8_t cnt = 0;
void loop(void)
{
    uint8_t txbuf[16];
    uint8_t rxbuf[16];
    uint8_t i;
    char uart_txbuf[128];
    for (i = 0; i < 16; i++){
        txbuf[i] = cnt + i;
    }
    Serial.println("start ");
    sprintf(
        uart_txbuf,
        "%04X : %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
        slave_memadr[0], txbuf[0], txbuf[1], txbuf[2], txbuf[3], txbuf[4], txbuf[5], txbuf[6], txbuf[7],
        txbuf[8], txbuf[9], txbuf[10], txbuf[11], txbuf[12], txbuf[13], txbuf[14], txbuf[15]);
    Serial.println(uart_txbuf);
    Wire.beginTransmission(slave_address);
    Wire.write((uint8_t)((slave_memadr[0] >> 8) & 0x00FF));
    Wire.write((uint8_t)((slave_memadr[0] >> 0) & 0x00FF));
    for (i = 0; i < 16; i++){
        Wire.write(txbuf[i]);
    }
    Wire.endTransmission();
    delay(10);

    Wire.beginTransmission(slave_address);
    Wire.write((uint8_t)((slave_memadr[0] >> 8) & 0x00FF));
    Wire.write((uint8_t)((slave_memadr[0] >> 0) & 0x00FF));
    //Wire.endTransmission();
    Wire.requestFrom(slave_address, 16);
    for (i = 0; i < 16; i++){
        rxbuf[i] = Wire.read();
    }
    Wire.endTransmission();
    sprintf(
        uart_txbuf,
        "       %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
        rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7],
        rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11], rxbuf[12], rxbuf[13], rxbuf[14], rxbuf[15]);
    Serial.println(uart_txbuf);
    cnt = ((cnt + 1) & 0x3F);
    delay(1000);
}

wire_slave_study1.ino

#include <Wire.h>

uint8_t slave_address = 0x55;
uint8_t slave_memory[0x0500];
uint16_t adr;
uint8_t recv_flag;

void requestEvent(){
    uint8_t n;
    uint16_t i = 0;
    for (n = 0, i = 0; n < 64; n++, i++){
        Wire.write(slave_memory[adr + i]);
    }
}
void receiveEvent(int n){
    uint16_t i = 0;
    if (Wire.available()){
        adr = (uint16_t)(Wire.read()) * 256;
    }
    if (Wire.available()){
        adr = adr + (uint16_t)(Wire.read());
    }
    while (Wire.available()){
        slave_memory[adr + i] = Wire.read();
        i = i + 1;
    }
    recv_flag = 1;
}

void setup(void)
{
    pinMode(A5, INPUT_PULLUP);
    pinMode(A4, INPUT_PULLUP);
    Wire.begin(slave_address);
    Serial.begin(115200);
    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);
    recv_flag = 0;
}

void loop(void)
{
    char uart_txbuf[16];
    uint16_t i;
    if (recv_flag == 1){
        recv_flag = 0;
        sprintf(uart_txbuf, "%04X : ", adr);
        Serial.print(uart_txbuf);
        for (i = 0; i < 16; i++){
            sprintf(uart_txbuf, "%02X", slave_memory[adr + i]);
            Serial.print(uart_txbuf);
        }
        Serial.println("");
    }
}
はい。いつも通りのいきなりな感じです。
デバイスアドレスは0x55で1バイト目がメモリ(のふり)のアドレスのHighバイトで、2バイト目がLowバイトを指示する。Slave側はこれを記憶しておく。続けてデータが来れば、それを保存していき、リクエストが来ればWire.writeでデータを返送する。
通信の全体像はこんな感じ。

Masterが送っている(書き込んでいる(つもり))部分はこんな感じ。

Masterが要求してSlaveが返答している部分はこんな感じ。

いい感じです。

いやーついでといえばついでで久しぶりに更新しましたー。
ついでがなければ、冬休みまで放置するところやったわ。ここ1,2ヶ月でも世の中がどんどん混沌としてきて、どうなっちゃうんやろ。
供給を人質にして、(自らが作りこんだ)問題の対応にコストアップを要求してくるメーカーがあったり、まさに苦難の行軍。