1
\$\begingroup\$

Lately i have been using ATMega32A and ATMega324PA and learnt various coding techniques in AVR C programming. One such code i wrote is avr_twi.c for communicating with an I2C accelerometer

Now i got migrated to ATXMega32D4, and I can cope up with the new device with few difficulties. Yet I can't get the I2C programming for the XMega series and specifically for ATXMega32D4 to work. The code is attached below

        #include <avr/io.h>
        #define F_CPU 2000000UL
        #include <util/delay.h>
        #include <avr/interrupt.h>
        #include <avr/wdt.h> // watchdog timer
        #include <stdio.h>
        #include <string.h>
        #include <stdlib.h>
        #include <avr/eeprom.h>
        #include <avr/pgmspace.h>

        #define F_TWI 100000
        #define TWI_BAUD(FSYS, FTWI) ((FSYS / (2 * FTWI)) - 5)
        #define TWI_BAUDSETTING TWI_BAUD(F_CPU, F_TWI)

        int8_t twi_read=0;
        TWI_t * BMA = &TWIC;

        void uart_transmit(char data)
        {
            USARTD0.DATA = data;
            if(!(USARTD0.STATUS & USART_DREIF_bm)) {
                while(!(USARTD0.STATUS & USART_TXCIF_bm)); // wait for TX complete
            }
            USARTD0.STATUS |= USART_TXCIF_bm;  // clear TX interrupt flag
        }

        uint8_t uart_getchar()
        {
            while(!(USARTD0.STATUS & USART_RXCIF_bm)); // wait for RX complete
            return (uint8_t)USARTD0.DATA;
        }

        void uart_array(char c[])
        {
            unsigned int j;
            j=strlen(c);
            for(unsigned int i=0;i<j;i++)
            {
                uart_transmit_gsm(c[i]);
            }
        }

        static inline void init_oscillator() {
            // enable 2Mhz internal oscillator
            OSC.CTRL |= OSC_RC2MEN_bm;
            // wait for it to be stable
            while (!(OSC.STATUS & OSC_RC2MRDY_bm));
            // tell the processor we want to change a protected register
            CCP=CCP_IOREG_gc;
            CLK.CTRL=CLK_SCLKSEL_RC2M_gc;
            // callibrated oscillator as auto-calibration source
        }

        static inline void init_usart()
        {
            // set PD3 as output for TX0
            PORTD.DIRSET = PIN3_bm;
            PORTD.OUTSET = PIN3_bm;
            // Atmel-42005-8-and-16-bit-AVR-Microcontrollers-XMEGA-E_Manual.pdf
            USARTD0.BAUDCTRLA = 12; // BSEL
            USARTD0.BAUDCTRLB = 0 << USART_BSCALE_gp; // BSCALE
            // disable 2X
            USARTD0.CTRLB = USARTD0.CTRLB & ~USART_CLK2X_bm;
            // enable RX and TX
            USARTD0.CTRLB = USARTD0.CTRLB | USART_RXEN_bm | USART_TXEN_bm;
            // enable async UART 8N1
            USARTD0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc;
            USARTD0.CTRLC &= ~USART_SBMODE_bm;
            // set interrupt level for RX
            //USARTD0.CTRLA = (USARTD0.CTRLA & ~USART_RXCINTLVL_gm) | USART_RXCINTLVL_LO_gc;
        }

        void twi_init()
        {
            //smart-mode activate
            BMA->MASTER.CTRLB |= TWI_MASTER_SMEN_bm;
            //Baud-rate setting
            BMA->MASTER.BAUD |= TWI_BAUDSETTING;
            //Enable twi
            BMA->MASTER.CTRLA |= TWI_MASTER_ENABLE_bm;
            //status register
            BMA->MASTER.STATUS |= TWI_MASTER_BUSSTATE_IDLE_gc;
        }

        void twi_write_data(uint8_t writeAddr,uint8_t writeData)
        {
            uint8_t i;
            uart_array("stp1");
            BMA->MASTER.ADDR = 0x30;
            while(!(BMA->MASTER.STATUS&TWI_MASTER_WIF_bm));

            BMA->MASTER.DATA = writeAddr;
            while(!(BMA->MASTER.STATUS&TWI_MASTER_WIF_bm));

            BMA->MASTER.DATA = writeData;
            while(!(BMA->MASTER.STATUS&TWI_MASTER_WIF_bm));

        }

        int8_t twi_read_data(uint8_t readAddr)
        {

            BMA->MASTER.ADDR = 0x31;

            while(!(BMA->MASTER.STATUS&TWI_MASTER_WIF_bm));

            BMA->MASTER.DATA = 0x00;
            BMA->MASTER.ADDR = readAddr;
            while(!(BMA->MASTER.STATUS&TWI_MASTER_RIF_bm));

            return BMA->MASTER.DATA;
        }

        int main(void)
        {
            init_oscillator();
            init_usart();
            twi_init();
            twi_write_data(0x3D,0xFA);
            uart_transmit(twi_read_data(0x3D));
            while(1);
        }

If someone out there have some experience in AVR XMega I2C please do post an example code with atleast some explanation. Thank you

\$\endgroup\$
  • \$\begingroup\$ How about you posting your code, so we can try and see where you went wrong? \$\endgroup\$ – Majenko Dec 2 '14 at 19:35
  • 1
    \$\begingroup\$ This could be useful, perhaps: github.com/alexforencich/templates/blob/master/xmega.cpp/… \$\endgroup\$ – alex.forencich Dec 2 '14 at 23:28
  • \$\begingroup\$ @Majenko-notGoogle I have posted my code. It stucks at twi_write_data function \$\endgroup\$ – gzix Dec 3 '14 at 4:10
-1
\$\begingroup\$

Change USARTD0.STATUS with USARTD0_STATUS . If you Use Atmel Studio 6.2 you can see it is not pink if not recognized.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.