/*************************************************************************
* Title: I2C master library using hardware TWI interface
* Author: Peter Fleury <<a href="mailto:pfleury@gmx.ch">pfleury@gmx.ch</a>> <a href="http://jump.to/fleury">http://jump.to/fleury</a>
**************************************************************************/
/*
ADC + UART
Hardware: ATmega8 @ 7.372800MHz
PC Software:Hyper terminal @ 9600 baud, Nincs Paritas Bit, 1 Stop Bit, Flow Control = NONE
*/
#define F_CPU 7372800UL // rendszer orajel: 7.3728 MHz
#define USART_BAUDRATE 9600 // soros kommunikácio sebessege: 9600 bps
#define UBRR_ERTEK ((F_CPU / (USART_BAUDRATE * 16UL)) - 1) // UBRR
#define SCL_CLOCK 100000L // I2C sebessege Hz-ben
#define I2C_READ 1 // adatiranyt jelzo bit - olvasas
#define I2C_WRITE 0 // adatiranyt jelzo bit - iras
#define HMC6352 0x42 // iranytumodul I2C cime
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <compat/twi.h>
void KonfigUART() // UART beallitasa
{
// 9600 bps soros kommunikácio sebesseg beallitasa
UBRRL = UBRR_ERTEK; // UBRR_ERTEK also 8 bitjenek betoltese az UBRRL regiszterbe
UBRRH = (UBRR_ERTEK>>8); // UBRR_ERTEK felso 8 bitjenek betoltese az UBRRH reg.-be
// Aszinkron mod, 8 Adat Bit, Nincs Paritas Bit, 1 Stop Bit
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
//Ado es Vevo aramkorok bekapcsolasa + az RX interrupt engedelyezese
UCSRB |= (1 << RXEN) | (1 << TXEN); //
}
char UARTAdatFogad() // Ez a fuggveny a beerkezo adatokat kiolvassa az UDR regiszter bejovo pufferebol
{
while(!(UCSRA & (1<<RXC))) // Varakozas amig nincs uj bejovo adat
{
//Varakozas
}
//Most mar van beerkezett adat, amit kiolvasunk a pufferbol
return UDR;
}
void UARTAdatKuld(char data) // Ez a fuggveny a kuldendo adatot beirja az UDR regiszter kimeno pufferjebe
{
while(!(UCSRA & (1<<UDRE))) // Varakozas amig az Ado kesz nem lesz az adatkuldesre
{
//Varakozas
}
// Az Ado mar kesz az adatkuldesre, a kuldendo adatot a kimeno pufferjebe irjuk
UDR=data;
}
/*************************************************************************
I2C periferia inicializalasa
*************************************************************************/
void i2c_init(void)
{
TWSR = 0;
TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
}
/*************************************************************************
Startjel kiadasa, majd az eszkozazonosito cim es adatirany elkuldese
Fuggv. parameter: I2C eszkozazonosito cim, adatirany
Fuggv. altal visszadott ertek: 0 = eszkoz elerheto, 1= eszkoz elerese sikertelen
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
uint8_t twst;
// START jel kuldese
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// varakozas amig az atvitel be nem fejezodik
while(!(TWCR & (1<<TWINT)));
// TWI Statusz Register ertekenek ellenorzese, elooszto bitek kimaszkolasa.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
// eszkozazonosito cim kuldese
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// varakozas amig az atvitel be nem fejezodik es az ACK/NACK nyugtazas be nem erkezik
while(!(TWCR & (1<<TWINT)));
// TWI Statusz Register ertekenek ellenorzese, elooszto bitek kimaszkolasa.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
return 0;
}
/*************************************************************************
Startjel kiadasa, majd az eszkozazonosito cim es adatirany elkuldese
Ha az eszkoz foglalt, varakozas amig kesz nem lesz (ack polling)
Fuggv. parameter: I2C eszkozazonosito cim, adatirany
*************************************************************************/
void i2c_start_wait(unsigned char address)
{
uint8_t twst;
while ( 1 )
{
// START jel kuldese
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// varakozas amig az atvitel be nem fejezodik
while(!(TWCR & (1<<TWINT)));
// TWI Statusz Register ertekenek ellenorzese, elooszto bitek kimaszkolasa.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
// eszkozazonosito cim kuldese
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// varakozas amig az atvitel be nem fejezodik
while(!(TWCR & (1<<TWINT)));
// TWI Statusz Register ertekenek ellenorzese, elooszto bitek kimaszkolasa.
twst = TW_STATUS & 0xF8;
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
{
// az eszkoz foglalt, Stop jel kuldese, irasi muvelet befejezese
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// varakozas amig a Stop utasitas vegre nem hajtodik es az I2C busz szabad nem lesz
while(TWCR & (1<<TWSTO));
continue;
}
//if( twst != TW_MT_SLA_ACK) return 1;
break;
}
}
/*************************************************************************
Ismetelt Startjel kiadasa, majd az eszkozazonosito cim es adatirany elkuldese
Fuggv. parameter: I2C eszkozazonosito cim, adatirany
Fuggv. altal visszadott ertek: 0 = eszkoz elerheto, 1= eszkoz elerese sikertelen
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start( address );
}
/*************************************************************************
Stopjel kuldese, kommunikacio lezarasa ,I2C bus szabadda tetele *************************************************************************/
void i2c_stop(void)
{
// STOP jel kuldese
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// varakozas amig a Stop utasitas vegre nem hajtodik es az I2C busz szabad nem lesz
while(TWCR & (1<<TWSTO));
}
/*************************************************************************
Egy bajt kuldese az I2C eszkozre
Fuggv. parameter: byte to be transfered
Fuggv. altal visszaadott ertek: 0 iras sikeres, 1 iras sikertelen *************************************************************************/
unsigned char i2c_write( unsigned char data )
{
uint8_t twst;
// adat irasa a korabban megcimzett eszkozbe
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
// varakozas amig az atvitel be nem fejezodik
while(!(TWCR & (1<<TWINT)));
// TWI Statusz Register ertekenek ellenorzese, elooszto bitek kimaszkolasa.
twst = TW_STATUS & 0xF8;
if( twst != TW_MT_DATA_ACK) return 1;
return 0;
}
/*************************************************************************
Egy bajt kiolvasasa az I2C eszkozbol, tovabbi adatok kerese
Fuggv. altal visszaadott ertek: az I2C eszkozbol kiolvasott bajt *************************************************************************/
unsigned char i2c_readAck(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
/*************************************************************************
Egy bajt kiolvasasa az I2C eszkozbol, a kiolvasast Stop bit koveti
Fuggv. altal visszaadott ertek: az I2C eszkozbol kiolvasott bajt *************************************************************************/
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
int iranymeres()
{
unsigned char hi_byte;
unsigned char lo_byte;
i2c_init(); // I2C inicializalasa
i2c_start_wait(HMC6352+I2C_WRITE); // iranytumodul I2C cim es adatirany (iras) megadasa
i2c_write('A'); // iranyszogmeresre utasito parancs
i2c_stop(); // Stopjel kuldese, I2C busz szabadda tetele
_delay_ms(10); // varakozas 10 ms-ig
i2c_rep_start(HMC6352+I2C_READ); // ismetelt Start jel (Restart) + adatirany (olvasas)
hi_byte = i2c_readAck(); // iranyszog beolvasasa az iranytumodulrol(magas bajt)
lo_byte = i2c_readNak(); //iranyszog beolvasasa az iranytumodulrol(alacsony bajt)
i2c_stop(); // Stopjel kuldese, I2C bus szabadda tetele
return ((hi_byte << 8) | lo_byte);
}
intmain(void) // Foprogram
{
KonfigUART(); // UART Konfiguralasa
unsigned int H = 0;
char data;
while(1)
{
data = UARTAdatFogad(); // A berekezo bajt fogadasa
if(data == 'm') // Ha a fogadott bajt a 'm'-mel egyezik meg, megmerjuk az iranyszoget
{
H = iranymeres();
UARTAdatKuld('0'+(H/1000) % 10); // Ezresek ertekenek kiirasa
UARTAdatKuld('0'+(H/100) % 10); // Szazasok ertekenek kiirasa
UARTAdatKuld('0'+(H/10) % 10); // Tizesek ertekenek kiirasa
UARTAdatKuld('0'+H % 10); // Egyesek ertekenek kiirasa
UARTAdatKuld('\n'); // Kovetkezo sor
UARTAdatKuld('\r'); // Ugras a sor elejere
_delay_ms(100); // várakozás 0.1 másodpercig
}
}
}