Соединение I2C с модулем камеры MT9D111, странные результаты после записи регистров через i2C

В настоящее время я работаю над платформой камеры на основе модуля MT9D111 от Micron. Первое, что нужно сделать, это записать конфигурацию в многочисленные регистры чипа, что делается через соединение i2C.

Я адаптировал код из здесь для тестирования с помощью Arduino Uno. . Питание 3,3 В и тактовая частота 8 МГц также обеспечиваются Arduino.

Кажется, все работает нормально, но есть некоторые проблемы, причину которых я не знаю.

Итак, вот код (я только что добавил последовательность мягкого сброса в соответствии с Руководством для разработчиков):

const int freqOutputPin = 9;   // Выходной контакт OC1A для плат ATmega328

#define TMR1 0

#include <Wire.h>
#include <avr/io.h>
#include <util/delay.h>
//#include <TimerOne.h>
#include <avr/interrupt.h>

void setup() {
  pinMode(freqOutputPin, OUTPUT);
  Serial.begin(9600);

  TCCR1B |= (1 << CS10);  // выбор прескалера 0b001 (Tclk/1)
  TCCR1B &= ~((1 << CS12) | (1 << CS11)); // отключаем биты CS12 и CS11
  TCCR1A |= ((1 << WGM11) | (1 << WGM10)); //Настроить таймер 1 для режима TOP (с TOP = OCR1A)
  TCCR1B |= ((1 << WGM13) | (1 << WGM12));
  TCCR1A |= (1 << COM1A0); // Включить таймер 1 Сравнить выходной канал A в режиме переключения
  TCCR1A &= ~(1 << COM1A1);
  TCNT1 = 0;
  OCR1A = TMR1;

  delay(500);  //Начальная задержка
  Wire.begin(); // присоединяемся к шине i2c в качестве мастера
  Serial.begin(9600);
  Serial.println("MT9D111 Camera Module + Arduino");
  Serial.println("Read and Write 16-bit register value example");
  Serial.println("*  Read expected value = 0x1519 from Register 0x00");
  Serial.println("*  Write value = 0xA5F0 to Register 0x20:1");
  Serial.println();
  init1(); //выполнить код только 1 раз
}

void loop() {
}

void init1() {
  int16_t a;

  delay(500);  // ждем начала
  Serial.print("Soft reset first");
  Serial.println();
  soft_reset();//делаем программный сброс при запуске

 //***************Конфигурация здесь!******************//
  Serial.print("Read result from register 0x00");
  a = read_reg(0);
  Serial.println();
  Serial.print("0x");
  Serial.println(a, HEX);  //распечатать результат
  Serial.println();
  Serial.print("Read original data from register 0x0a, should be 11");
  Serial.println();
  a = read_reg(10);  
  Serial.print("0x");
  Serial.println(a, HEX);  //распечатать результат
  Serial.println();

  // Включаем эту часть для записи регистра
  //Некоторые примеры чтения и записи следуют
  Serial.print("Writing 0xA5F0 in register 0x20:1");
  Serial.println();
  write_reg(32, 1, 165, 240);
  Serial.print("Read new value from register 0x20:1");
  Serial.println();
  a = read_reg(32);
  Serial.print("0x");
  Serial.println(a, HEX);  //распечатать результат
  Serial.println();
  Serial.print("Writing 0xA1F3 in register 0x20:1");
  Serial.println();
  write_reg(32, 1, 161, 243);
  Serial.print("Read new value from register 0x20:1");
  Serial.println();
  a = read_reg(32);  
  Serial.print("0x");
  Serial.println(a, HEX);  //распечатать результат
  Serial.println();
}

//Запись 2-байтового регистра
void write_reg(int reg_address, int page, int data_msb, int data_lsb) {
  delay(5);  //5 мс
  Wire.beginTransmission(93); // передать на устройство 93, модуль камеры
  Wire.write(240);   //адрес регистрации страницы
  Wire.write(0);
  Wire.write(page);   //выбираем страницу 0/1/2
  Wire.endTransmission(1);    // прекращаем передачу
  Wire.beginTransmission(93); // передать на устройство 93, модуль камеры
  Wire.write(reg_address);   // адрес регистра 8-битный, десятичный
  Wire.write(data_msb);  //мсбайт
  Wire.write(data_lsb);  //lsbyte
  Wire.endTransmission(1);    // прекращаем передачу
}

//чтение 2-байтового регистра
//будьте осторожны с выбранной страницей регистрации
int16_t read_reg(int reg_address) {
  int16_t err;
  delay(5);  //5 мс
  Wire.beginTransmission(93); // передать на устройство 93, модуль камеры
  Wire.write(reg_address);   // адрес регистра 8-битный, десятичный
  err = Wire.endTransmission(1);    // прекращаем передачу
  Serial.println(err);
  Wire.requestFrom(93, 2, 1); // значение запроса формы устройства 93, 2 байта со стоповым битом
  int16_t result = ((Wire.read() << 8) | Wire.read());  //читаем 16 бит
  return result;
}

//Выполнить программный сброс, необходимый при запуске
void soft_reset(){
  write_reg(101, 0, 160, 0);//регистры записи в соответствии с руководством разработчика
  write_reg(195, 1, 5, 1);
  write_reg(13, 0, 0, 33);
  delay(5);
  write_reg(13, 0, 0, 0);
  delay(5);//ждем, пока i2c снова будет готов
}

Выполнение этого кода дает мне следующий результат на последовательном мониторе:

Последовательный монитор

Итак, вот вопросы:

  1. Есть ли у вас идеи, почему я получаю дополнительный FFFF при чтении регистра после его записи? (подчеркнуто синим)
  2. Почему в выводе есть лишние нули? (отмечено желтым цветом)

, 👍1

Обсуждение

Как вы заставили это работать. Я попробовал тот же код с OV2640, но всегда получаю ошибку 2 и значение читается как 0xFFFF. Пожалуйста, помогите мне., @Sriranjan Rasakatla

У вас все еще есть руководство разработчика MT9D111? Кажется, я не могу найти его в Интернете., @Emmet H

Нашел здесь: https://files.niemo.de/aptina_pdfs/MT9D111_Dev_Guide.book.pdf, @deinoppa


1 ответ


Лучший ответ:

1

0 исходит из вашего кода:

Serial.println(err);

Он печатает код ошибки. 0, следовательно, ошибки нет.

Что касается дополнительного FFFF, я бы сказал, что это потому, что вы используете целые числа со знаком. Измените объявление a на uint16_t и посмотрите, исправит ли это проблему.

,

Спасибо, это была быстрая помощь. Решил проблемы :-), @deinoppa

Рад был помочь :-), @dda