logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[mega8][C] komunikacja z kompasem po i2c

Mergot 10 Paź 2010 19:24 1182 0
REKLAMA
  • #1 8604527
    Mergot
    Poziom 11  
    Witam wszystkich,
    mam duże trudności z nawiązaniem komunikacja z kompasem cyfrowym HMC5843 przez protokół I2C.

    Wszystko ma działać na atmega8 (master) 3,3v @ 4MHz, bezpośrednio połączona z układem (slave).
    Pull-up'y na liniach SDA i SCL przez rezystory 4k7 są obecne.
    Komunikacja z prędkości 100kHz (sprawdzałem też dla 40 i 50kHz, efekt ten sam).

    Po uruchomieniu modułu TWI (procedura i2cInit() ), obie linie przechodzą w stan wysoki.
    Po uruchomieniu procedury wysyłającej instrukcje startowe dla kompasu (żeby dokonywał pomiaru ciągłego) obie linie przechodzą w stan niski - permanentnie.
    Po każdorazowym wysłaniu danych lub adresu przez TWI/I2C w rejestrze TWSR powinien pojawiać się Status Code informujący o efekcie operacji.

    Po wywołaniu init_hmc5843(); wartości status code to:

    1) i2cSendStart();
    Status Code: 0xA8
    2) i2cSendByte(HMC5843_WRITE); //write to the HMC5843
    Status Code: 0x80
    3) i2cSendByte(0x02); //Write to Mode register
    Status Code: 0x80
    4) i2cSendByte(0x00); //Clear bit 1, the MD1 bit
    Status Code: 0x80

    Podstawowy problem, to fakt, że żadne z tych kodów nie należy do trybu Master Transmitter (tabela 66 na stronie 180 datasheet).
    Występują w tabelach błędów dla SLAVE
    0xA8 - slave transmitter, tabela 69
    0x80 - slave receiver, tabela 68

    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    #define HMC5843_WRITE		0x3C
    #define HMC5843_READ		        0x3D
    #define HMC5843_CON_MES		0x00
    
    
    #define TRUE				-1
    #define FALSE				0
    
    #define START				0x08
    #define SLA_W_ACK			0x18
    #define DATA_ACK			0x28
    
    // Function declaration
    // ************************************
    void IOinit(void);
    
    int16_t read_hmc5843(char reg_adr);
    void init_hmc5843(void);
    
    void i2cInit(void);
    void i2cSetBitrate(uint8_t bitrateKHz);
    void i2cSendStart(void);
    void i2cSendStop(void);
    void i2cWaitForComplete(char status);
    void i2cSendByte(unsigned char data);
    unsigned char i2cReceiveByte(void);
    
    
    int main(void)
    {
    	
    	uint16_t		znak = 0;
    
    	IOinit(); 
    
    	i2cInit();
    
    
    	_delay_ms(100);
    
    	init_hmc5843();
    
    	_delay_ms(100);
    
    	for(;;)
    	{
    	}
    }
    
    // ###########################################################
    
    
    void IOinit(void)
    {
    
            //1 = output, 0 = input 
            DDRC = _BV(PC5) | _BV(PC4);
    	DDRB = 0b00000001;
    
    	PORTC = _BV(PC5) | _BV(PC4); //pullups on the I2C bus
    	
    }
    
    //=================================
    
    void i2cInit(void)
    {
    	// set i2c bit rate to 100 [kHz]
    	i2cSetBitrate(100);
    	
    	TWDR = 0xFF;                                      // Default content = SDA released.
    
    	// enable TWI (two-wire interface)
    	TWCR = (1<<TWEN);	// Enable TWI
    }
    
    //=================================
    
    void init_hmc5843(void)
    {
    
    	i2cSendStart();
    	i2cWaitForComplete(START);
    
    	i2cSendByte(HMC5843_WRITE); //write to the HMC5843
    	i2cWaitForComplete(SLA_W_ACK);
    
    	i2cSendByte(0x02); //Write to Mode register
    	i2cWaitForComplete(DATA_ACK);
    
    	i2cSendByte(0x00); //Clear bit 1, the MD1 bit
    	i2cWaitForComplete(DATA_ACK);
    
    	i2cSendStop();
    }
    
    //=================================
    
    void i2cSetBitrate(uint8_t bitrateKHz)
    {
    	uint8_t bitrate_div;
    
    	// i2c Prescaler Value = 1
    	TWSR = 0x00;
    	
    	// wyliczenie wartości dla TWI Bit Rate Register	
    	// SCL freq = F_CPU/(16+2*TWBR))
    
    	bitrate_div = (((FOSC/1000/bitrateKHz)-16)/2);
    		
    	TWBR = bitrate_div;
    
    }
    
    //=================================
    
    void i2cSendStart(void)
    {
    	// send start condition
    	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    }
    
    //=================================
    
    void i2cSendStop(void)
    {
    	// transmit stop condition
    	TWCR = (1<TWINT) | (1<<TWEN) | (1<<TWSTO);
    }
    
    //=================================
    
    void i2cWaitForComplete(char status)
    {
    	char i = 0;
    
    	// wait for i2c interface to complete operation
        while ((!(TWCR & (1<<TWINT))) && (i < 90))
    	{	
    		_delay_ms(1);
    		i++;
    	}
    
    }
    
    //=================================
    
    void i2cSendByte(unsigned char data)
    {
    	_delay_ms(1);
    	// save data to the TWDR
    	TWDR = data;
    	// begin send
    	TWCR = (1<<TWINT) | (1<<TWEN);
    }
    
    


    Ma ktoś pomysł od czego zacząć ?
    Nie mam możliwości sprawdzenia kompasu, dodam tylko tyle, że jest świeży ze sklepu, przyszedł polutowany do płytki.


    =============================
    =============================
    11.10.10
    Update.

    Problem został rozwiązany, zamykam temat.
  • REKLAMA
REKLAMA