/* P9_2.c - Test I2C byte read with DS1337 * * This program initializes the SERCOM1 as I2C and continuously * reads the register 0 of the DS1337. * Register 0 contains the second count. The clock is powered-up * enabled and the second count is incrementing. The bit 0 is * used to turn on and off the LED0 of the SAMD21 Xplained Pro * board. The LED0 should blink every second. * PA16 = SDA, PA17 = SCL * No errors or acknowledgement are checked. * * Tested with Atmel Studio 7 v7.0.1006 and Keil MDK-ARM v5.21a. */ #include "samd21.h" unsigned char* ARRAY_PORT_PINCFG0 = (unsigned char*)®_PORT_PINCFG0; unsigned char* ARRAY_PORT_PMUX0 = (unsigned char*)®_PORT_PMUX0; #define SLAVE_ADDR 0x68 /* 1101 000. DS1337 */ void I2C2_init(void) ; int I2C2_byte_write(unsigned char saddr, unsigned char maddr, unsigned char data); int I2C2_byte_read(unsigned char saddr, unsigned char maddr, unsigned char* data); void delayMs(int n); int main (void) { unsigned char data; I2C2_init(); REG_PORT_DIRSET1 = 0x40000000; /* make PB30 output */ while (1) { I2C2_byte_read(SLAVE_ADDR, 0, &data); if (data & 1) REG_PORT_OUTCLR1 = 0x40000000; /* turn on LED0 */ else REG_PORT_OUTSET1 = 0x40000000; /* turn off LED0 */ delayMs(10); } } void I2C2_init(void) { REG_PM_APBCMASK |= 0x00000008; /* SERCOM1 bus clock */ GCLK->CLKCTRL.reg = 0x4015; /* SERCOM1 core clock */ ARRAY_PORT_PINCFG0[16] |= 1; /* allow pmux to set PA16 pin configuration */ ARRAY_PORT_PINCFG0[17] |= 1; /* allow pmux to set PA17 pin configuration */ ARRAY_PORT_PMUX0[8] = 0x22; /* PA16 = SDA, PA17 = SCL */ REG_SERCOM1_I2CM_CTRLA = 1; /* reset SERCOM1 */ while (REG_SERCOM1_I2CM_CTRLA & 1) {} /* wait for reset to complete */ REG_SERCOM1_I2CM_CTRLA = 0x14; /* master mode */ REG_SERCOM1_I2CM_BAUD = 0; /* 1MHz main clock -> ~100KHz I2C clock */ REG_SERCOM1_I2CM_CTRLA |= 2; /* enable SERCOM1 */ REG_SERCOM1_I2CM_STATUS = 0x10; /* force idle */ } int I2C2_byte_read(unsigned char saddr, unsigned char maddr, unsigned char* data) { while((REG_SERCOM1_I2CM_STATUS & 0x30) != 0x10) ; /* wait until idle */ REG_SERCOM1_I2CM_ADDR = saddr << 1; /* send slave address */ while((REG_SERCOM1_I2CM_INTFLAG & 1) == 0); /* wait until saddr sent */ REG_SERCOM1_I2CM_DATA = maddr; /* send memory address */ while((REG_SERCOM1_I2CM_INTFLAG & 1) == 0); /* wait until maddr sent */ REG_SERCOM1_I2CM_ADDR = (saddr << 1) | 1; /* send restart with slave address */ while((REG_SERCOM1_I2CM_INTFLAG & 2) == 0); /* wait until data received */ *data = REG_SERCOM1_I2CM_DATA; /* read data */ REG_SERCOM1_I2CM_CTRLB |= 0x40000; /* generate nack */ REG_SERCOM1_I2CM_CTRLB |= 0x30000; /* issue a stop */ return 0; } // delay n milliseconds (1MHz CPU clock) void delayMs(int n) { int i; for (; n > 0; n--) for (i = 0; i < 199; i++) __asm("nop"); }