- Код: Выделить всё
// 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 что-то происходит, рассмотреть детальнее на моём осциллографе невозможно. Прошу помощи!