Опыт работы с TWI в ATmega8(CV)

Автор: g1ar от 18-05-2015, 18:29

Описание регистров я приводить не буду, их достаточно в интернете, да и без лишней нужды в них лезть не приходиться в большинстве случаев. А вот то что нужно знать - это формула которая определяет частоту работы TWI - всеми известен I2C.
Опыт работы с TWI в ATmega8(CV)

TWBR - задает коэффициент деления частоты генератора скорости связи. TWPS - Биты 0:1 предделителя TWI
Несложными движениями выражаем TWBR, он то нам и нужен. Получилось следующее -
TWBR = ( (CPU_F/SCL_F) - 16) / (2*4^TWPS);
Если поставить значение TWPS -00, сокращаем формулу до -
TWBR = ( (CPU_F/SCL_F) - 16) / (2*1) - не должен быть 0 или больше 255!
Теперь дело за малым, зная как работает twi и покурив даташит был написан сл.код -

#define CPU_F              4000000UL // 4МГц
#define SCL_F              100000UL  // 100кГц, 400кГц - максимум для twi
// Значение пропуска, проверить что бы не совпадало с возможными данными
// Иначе изменить на неиспользуемое число
#define Skip_Flag           0xff 
// Адрес устройства в формате 7бит(без бита RW)
#define Dev_Adr             0x00 


//Инициализация twi
void twi_Init(void) 
{
   TWBR = ( ( (CPU_F)/(SCL_F)-16 ) /2 ) ;
   TWSR = 0; //Очищаются биты TWPS0 и TWPS1
}

// Запись по twi, reg_adr - адрес регистра, data - значение, если не нужно пишем Skip_Flag
void twi_write(unsigned char reg_adr, unsigned char data)
{
  // Сброс флага прерывания TWINT, установка Старта, установка разрешения работы twi
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
 // Ждем пока будет свободна линия, если занята
  while(!(TWCR & (1<<TWINT)));

  // Передаем адрес с флагом записи 0 
  TWDR = (Dev_Adr<<1) | 0;
 // Говорим, что мы хотим передать данные
  TWCR = (1<<TWINT)|(1<<TWEN); 
 // Ждем окончания передачи данных
  while(!(TWCR & (1<<TWINT)));
  
  // Передаем адрес регистра
  TWDR = reg_adr;
  TWCR = (1<<TWINT)|(1<<TWEN); 
  while(!(TWCR & (1<<TWINT)));
  
  // Тут два пути, или нам просто нужно было установить адрес регистра и считать с него, тогда пропускаем ф-ю
 // Либо устанавливаем значение в регистр
  if (data != Skip_Flag )
{   // /Пишем значение
     TWDR = data;
     TWCR = (1<<TWINT)|(1<<TWEN); 
     while(!(TWCR & (1<<TWINT)));
  }  
  // Устанавливаем условие завершения передачи данных (СТОП)
  TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);  
}

// Чтение 
unsigned char twi_read(void)
{
  unsigned char data; 

  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
  while(!(TWCR & (1<<TWINT))); 
  
  // Передаем адрес с флагом чтения 1
  TWDR = (Dev_Adr<<1) | 1;

  TWCR = (1<<TWINT)|(1<<TWEN); 
  while(!(TWCR & (1<<TWINT)));   
 
  // Очистка флага прерывания TWINT
  TWCR = (1<<TWINT)|(1<<TWEN);
  // Ждем окончания приема..
  while(!(TWCR & (1<<TWINT)));
  // Считываем байт данных
  data = TWDR;
  
  // Стоп
  TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
  // Возвращаем принятые данные
  return data; 
}



В коде реализация выглядит так

twi_Init();
twi_write(0x00, Skip_Flag); // 0x00 - обычно под этим адресом какой-то DevID, Skip_Flag - ничего не записываем, только чтение по этому адресу
data = twi_read(); // Принимаем ID

Теги: twi, i2c, mega8, atmega8, codevision, avr

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.