2024年12月8日 星期日

[8051] 用CH552讀取語音IC的狀態

參考資訊:PXT-ASRPlanetX_MicroPython

電路圖:


程式碼:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <Arduino.h>

#define SDA_PIN 31 // 定義 SDA 為 P2
#define SCL_PIN 30  // 定義 SCL 為 P3

#define I2C_DELAY_US 5  // I²C 時鐘延遲 (調整延遲來控制速率)

// 語音設備 I²C 位址
#define VOICE_I2C_ADDR 0x0B

// 初始化 I²C 線路
void i2c_init() {
  pinMode(SDA_PIN, OUTPUT);
  pinMode(SCL_PIN, OUTPUT);
  digitalWrite(SDA_PIN, HIGH);
  digitalWrite(SCL_PIN, HIGH);
}

// 產生 I²C 起始信號
void i2c_start() {
  digitalWrite(SDA_PIN, HIGH);
  digitalWrite(SCL_PIN, HIGH);
  delayMicroseconds(I2C_DELAY_US);
  digitalWrite(SDA_PIN, LOW);
  delayMicroseconds(I2C_DELAY_US);
  digitalWrite(SCL_PIN, LOW);
}

// 產生 I²C 停止信號
void i2c_stop() {
  digitalWrite(SDA_PIN, LOW);
  digitalWrite(SCL_PIN, HIGH);
  delayMicroseconds(I2C_DELAY_US);
  digitalWrite(SDA_PIN, HIGH);
  delayMicroseconds(I2C_DELAY_US);
}

// 傳送 1 個位元
void i2c_send_bit(bool bit) {
  digitalWrite(SDA_PIN, bit);
  delayMicroseconds(I2C_DELAY_US);
  digitalWrite(SCL_PIN, HIGH);
  delayMicroseconds(I2C_DELAY_US);
  digitalWrite(SCL_PIN, LOW);
}

// 接收 1 個位元
bool i2c_read_bit() {
  pinMode(SDA_PIN, INPUT);
  delayMicroseconds(I2C_DELAY_US);
  digitalWrite(SCL_PIN, HIGH);
  delayMicroseconds(I2C_DELAY_US);
  bool bit = digitalRead(SDA_PIN);
  digitalWrite(SCL_PIN, LOW);
  pinMode(SDA_PIN, OUTPUT);
  return bit;
}

// 傳送 1 個位元組 (8 位元) 並讀取 ACK/NACK
bool i2c_write_byte(uint8_t data) {
  for (uint8_t i = 0; i < 8; i++) {
    i2c_send_bit(data & 0x80);
    data <<= 1;
  }
  // 接收 ACK/NACK
  return !i2c_read_bit();  // 0: ACK, 1: NACK
}

// 讀取 1 個位元組 (8 位元)
uint8_t i2c_read_byte(bool ack) {
  uint8_t data = 0;
  for (uint8_t i = 0; i < 8; i++) {
    data <<= 1;
    if (i2c_read_bit()) {
      data |= 0x01;
    }
  }
  i2c_send_bit(!ack);  // 傳送 ACK (0) 或 NACK (1)
  return data;
}

// 寫入資料到 I²C 裝置
bool i2c_write(uint8_t addr, uint8_t *data, uint8_t len) {
  i2c_start();
  if (!i2c_write_byte(addr << 1)) {  // 傳送寫入位址
    i2c_stop();
    return false;
  }
  for (uint8_t i = 0; i < len; i++) {
    if (!i2c_write_byte(data[i])) {  // 傳送資料
      i2c_stop();
      return false;
    }
  }
  i2c_stop();
  return true;
}

// 從 I²C 裝置讀取資料
bool i2c_read(uint8_t addr, uint8_t *buffer, uint8_t len) {
  i2c_start();
  if (!i2c_write_byte((addr << 1) | 1)) {  // 傳送讀取位址
    i2c_stop();
    return false;
  }
  for (uint8_t i = 0; i < len; i++) {
    buffer[i] = i2c_read_byte(i < (len - 1));  // 除了最後一個位元組外,都傳送 ACK
  }
  i2c_stop();
  return true;
}

// 讀取語音 I²C 設備的資料
bool read_voice_data(uint8_t *buffer, uint8_t len) {
  return i2c_read(VOICE_I2C_ADDR, buffer, len);  // 從語音設備讀取資料
}

void setup() {

  i2c_init();
}

void loop() {
  uint8_t voice_data[2];  // 用來接收語音設備的資料

  // 從語音設備讀取資料
  if (read_voice_data(voice_data, 1)) {
    USBSerial_print("Voice Data: ");
    USBSerial_println(voice_data[0], HEX);  // 顯示語音設備的第1個位元組
  } else {
    USBSerial_print("Failed to read voice data\n");
  }

  delay(100);  // 等待 100 msec
}

執行結果:
Voice Data: 0
Voice Data: 1
Voice Data: 0
Voice Data: 0
Voice Data: 0
Voice Data: 0
Voice Data: 0
Voice Data: 0
Voice Data: 11

沒有留言:

張貼留言