Últimamente he estado usando ATMega32A y ATMega324PA y aprendí varias técnicas de codificación en la programación de AVR C. Uno de estos códigos que escribí es avr_twi.c para comunicarse con un acelerómetro I2C
Ahora me migraron a ATXMega32D4, y puedo hacer frente al nuevo dispositivo con pocas dificultades. Sin embargo, no puedo hacer funcionar la programación I2C para la serie XMega y específicamente para ATXMega32D4. El código se adjunta a continuación
#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);
}
Si alguien tiene experiencia en AVR XMega I2C, publique un código de ejemplo con al menos alguna explicación. Gracias