Tiny AVR 1 Serisi - I2C (TWI)

 Bu yeni Attiny serisinde SPI ve I2C dışında kullanacağım bir birim kalmadı. AC ve DAC zaten oldukça basit ve hiç bir zaman kullanmam gerekmedi bu nedenle o konuları yazmayacağım. I2C atmega veya eski attiny serisine göre daha pratik. USI gibi her şeyi bizim yaptığımız bir donanıma göre çok üstün. Durum registeri biraz yetersiz. Atmega serisinde Status her adımı belirten bir yapıya sahipti. Veri transferinde hangi adımda olduğumuzu registeri okuyup anlayabiliyorduk. Bunda öyle değil o nedenle durum takibini bizim yapmamız gerekiyor. Atmegada her adım için sürekli register bit değişikliği yapıyorduk. Bu seride bu çok az. I2C nedir nasıl çalışır için eski konulara bakmak gerekecek. Burada sadece bu seride nasıl çalışır kısaca yazıp kütüphane paylaşacağım.

I2C

Birimin şeması bu şekildedir. Bir diğer fark I2C çalışma frekansı için gereken BAUD değerinin hesaplanmasıdır.

Tr (Trise) yükselen kenar süresidir ve ns olduğundan saniyeye çevirmek gerekir. Buna göre BAUD=(((float)F_CPU/F_SCL)/2)-(5+((((float)F_CPU*Trise)/1000)/1000)/2000) olur. BAUD ile I2C biriminin çalışma frekansını belirledikten sonra okuma/yazma kesmelerini açıp birimi çalıştırmak için MCTRLA registerinde ilgili bitleri ayarlıyoruz.

Start koşulu oluşturmak için MADDR registerine (okuma/yazma biti ekli şekilde) adresi yazmak yeterlidir. Hat boşta ve birim meşgul değilse start ve kesme oluşur. Yazma görevinde veri bitene kadar MDATA registerine gidecek veri yazılır. Bittiği zaman MCTRLB registeri MCMD biti ile stop ayarlanır. Okuma görevinde veri bitene kadar MCTRLB registerinde ACK gönderilecekse ACKACT biti "0" yapılmalı ve MCMD biti RECVTRANS ayarlanmalıdır. Okuma bitince NACK için ACKACT "1" yapılır ve stop koşulu oluşturulur. 

Bütün bunları kesme ile yapan bir uygulama notu yok. Ben eski çalışmalarıma uygun olarak yazdım. Status registeri çok detaylı bilgi vermediğinden durum takibini yazılımla yapmak zorunda kaldım. Çok uzatmadan tekrara düşmeden sadece kullanımı aktarmak istedim.

Kütüphane dosyası burada: TinyAVR-1/tiny1_i2c_master at main · haluks/TinyAVR-1 (github.com)

Örnek AHT10 uygulama

/*
 * attiny1614_i2c_master.c
 *
 * Created: 3.10.2023 16:38:01
 * Author : haluk
 */ 
 #define F_CPU 3333333
 #include <avr/io.h>
 #include <avr/interrupt.h>

#include <stdio.h>
#include "i2c_at1614_master.h"
#include "uart_at1614.h"
 #include <util/delay.h>
uint8_t aht_adr=0x38;//aht10adres
uint8_t aht_res=0xBA;//soft reset
uint8_t aht_init[]={0xE1,0x08,0x00};//init
uint8_t aht_trig[]={0xAC,0x33,0x00};//ölçüm başlatma
uint8_t aht_data[6];
uint32_t aht_temp=0;
uint32_t aht_hum=0;
float sicaklik=0.0;
float nem=0.0;
char str_data[64];
uint8_t okunan=0;
 uint8_t i=0; 
int main(void){
  i2c_init();
  uart_basla(Bd115200);
  //aht_adr=i2c_adres_scan();
  i2c_send_data(aht_adr,aht_res, N_REPEAT);//soft reset
  _delay_ms(1);
    i2c_send(aht_adr,aht_init,3, N_REPEAT);//init komutu  
  while (1) {      
    i2c_send(aht_adr,aht_trig,3,N_REPEAT);//ölçme tetik
    _delay_ms(150);//ölçüm aralığı
    i2c_read(aht_adr,6);// veri okuma  
    _delay_ms(10);//ölçüm aralığı  
    while (i2c_gelen()){//okunan veri alındı
    aht_data[i++]= i2c_oku();
    }
    i=0;
    aht_temp=((uint32_t)(aht_data[3]&0x0F)<<16)|((uint16_t)aht_data[4]<<8)|(aht_data[5]);
    aht_hum=(((uint32_t)aht_data[1]<<16)|((uint16_t)aht_data[2]<<8)|aht_data[3])>>4;
    sicaklik=((float)aht_temp/5242.88)- 50;//formülün sadeleştirilmiş hali
    nem=((float)aht_hum/10485.76);//formülün sadeleştirilmiş hali 
    sprintf(str_data,"\n%.2f--%.2f\n",sicaklik,nem);//sonuçları ekrana yazmak için
    uart_dizi(str_data);    
  
    }
}




Hiç yorum yok:

Yorum Gönder