- Код: Выделить всё • Развернуть
- // Wire Slave Receiver
 // by Nicholas Zambetti <http://www.zambetti.com>
 
 // Demonstrates use of the Wire library
 // Receives data as an I2C/TWI slave device
 // Refer to the "Wire Master Writer" example for use with this
 
 // Created 29 March 2006
 
 // This example code is in the public domain.
 
 
 #include <Wire.h>
 
 void setup()
 {
 Wire.begin(0b00000100); // join i2c bus
 Wire.onReceive(receiveEvent); // register event
 Serial.begin(9600); // start serial for output
 }
 
 void loop()
 {
 delay(100);
 }
 
 // function that executes whenever data is received from master
 // this function is registered as an event, see setup()
 void receiveEvent(int howMany)
 {
 while(1 < Wire.available()) // loop through all but the last
 {
 char c = Wire.read(); // receive byte as a character
 Serial.print(c); // print the character
 }
 }
Мега644 работает на частоте 16МГц от внешнего кварца. В неё прошит такой код:
- Код: Выделить всё • Развернуть
- #define F_CPU 16000000UL //1 MHz
 #include <avr/io.h>
 #include <util/delay.h>
 #include <avr/interrupt.h>
 #include <util/twi.h>
 #include <stdio.h>
 #include "def.h"
 #include "utils.h"
 //#include "uart.h"
 //#include "timer.h"
 #include "segment.h"
 
 
 //адрес ведомого с которым хотим пообщаться
 #define SLAVE_ADDR 0b00000100
 
 //макрос адреса + бит чтения
 #define SLA_R (SLAVE_ADDR | 0b00000001)
 //макрос адреса + бит записи
 #define SLA_W (SLAVE_ADDR & 0b11111110)
 
 // отправка команды СТАРТ
 uint8_t I2C_StartCondition(void)
 {
 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
 while (!(TWCR & (1<<TWINT)));//ожидание установки бита TWIN
 if((TWSR & 0xf8) != TW_START) {
 segment_write_num(3);
 return 1;
 }
 return 0;
 }
 
 // отправка СТОП
 void I2C_StopCondition(void)
 {
 TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
 }
 
 // отправка адреса
 uint8_t I2C_SendAddr(uint8_t addr)
 {
 TWDR = addr; //загрузка значения в регистр данных
 TWCR = (1<<TWINT)|(1<<TWEN); //начало передачи байта данных
 while (!(TWCR & (1<<TWINT))); //ожидание установки бита TWIN
 if((TWSR& 0xf8) != TW_MT_SLA_ACK) {
 segment_write_num(4);
 return 1;
 }
 return 0;
 }
 
 //отправка байта
 uint8_t I2C_SendByte(uint8_t c)
 {
 TWDR = c;//загрузка значения в регистр данных
 TWCR = (1<<TWINT)|(1<<TWEN);//начаало передачи байта данных
 while (!(TWCR & (1<<TWINT)));//ожидание установки бита TWIN
 if((TWSR& 0xf8) != TW_MT_DATA_ACK) {
 segment_write_num(5);
 return 1;
 }
 return 0;
 }
 
 //инициализация I2C как передатчика
 void I2C_Init (uint8_t value)
 {
 TWBR = value;
 }
 
 void setup();
 
 int main(void)
 {
 setup();
 _delay_ms(1000);
 I2C_Init(72);
 
 while(1) {
 if(I2C_StartCondition()) {
 goto wait;
 }
 if(I2C_SendAddr(SLA_W)) {
 goto wait;
 }
 if(I2C_SendByte(0x1)) {
 goto wait;
 }
 
 wait:
 I2C_StopCondition();
 _delay_ms(1000);
 }
 
 while(1) {
 _delay_ms(1000);
 }
 
 return 0;
 }
 
 void setup()
 {
 segment_init();
 sei();
 }
Значение 72 для регистра TWBR взял из атмеловского аппноута 315 (см. скрин). Фунцкия segment_write_num(n) выводит свой аргумент на семисегментный индикатор для отладки. Валится всё на передаче адреса, после передачи адреса выполняется такой код
- Код: Выделить всё • Развернуть
- if((TWSR& 0xf8) != TW_MT_SLA_ACK) {
 segment_write_num(4);
 return 1;
 }
и выводит на индикатор цифру 4, т.е. ACK от ардуины не получен. Подключение проверял много раз, пробовал с разными подтягивающими резисторами - 2.2К, 4.7К, 10К, 22К, ничего не работает. Смотрел осциллографом, на линиях SDA и SCL что-то происходит, рассмотреть детальнее на моём осциллографе невозможно. Прошу помощи!

 
 
