Include Asf.H Uses Files from the Directory
Total Page:16
File Type:pdf, Size:1020Kb
Dokumentation der Softwarestände
ASF TRYOUT 3
Code
#include "asf.h" //Uses Files from the directory #include
/* Function Prototype */ void i2c_clock_init(void); void i2c_pin_init(void); void i2c_master_init_2(void); void i2c_master_transact(void); uint32_t calculate_baud(uint32_t, uint32_t); uint8_t tx_buf[BUF_SIZE] = {1, 2, 3}; uint8_t rx_buf[BUF_SIZE]; uint8_t i; volatile bool tx_done = false, rx_done = false;
/* I2C handler */ void SERCOM3_Handler(void) { /* Master on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.MB) { if (i == BUF_SIZE) { /* After transferring the last byte stop condition will be sent */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); tx_done = true; i = 0; } else { /* placing the data from transmitting buffer to DATA register*/ SERCOM3->I2CM.DATA.reg = tx_buf[i++]; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } } /* Slave on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.SB) { if (i == (BUF_SIZE-1)) { /* NACK should be sent before reading the last byte */ SERCOM3->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_done = true; } else { SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* sending ACK after reading each byte */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x2; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } } }
/*Assigning pin to the alternate peripheral function*/ static inline void pin_set_peripheral_function(uint32_t pinmux) { uint8_t port = (uint8_t)((pinmux >> 16)/32); PORT->Group[port].PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1; PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >> 16) & 0x01u))); PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux & 0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u))); } /* calculating the BAUD value using Fgclk,Fscl,Trise FSCL =fGCLK / (10 + BAUD +BAUDLOW + fGCLKTRISE )*/ uint32_t calculate_baud(uint32_t fgclk, uint32_t fscl) { float f_temp, f_baud; f_temp = ((float)fgclk/(float)fscl) - (((float)fgclk/(float)1000000)*0.3); f_baud = (f_temp/2)-5; return ((uint32_t)f_baud); } /* SERCOM clock and peripheral bus clock initialization */ void i2c_clock_init() { struct system_gclk_chan_config gclk_chan_conf; uint32_t gclk_index = SERCOM3_GCLK_ID_CORE; /* Turn on module in PM */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_SERCOM3); /* Turn on Generic clock for I2C */ system_gclk_chan_get_config_defaults(&gclk_chan_conf); /* Default is generator 0. Other wise need to configure like below */ /* gclk_chan_conf.source_generator = GCLK_GENERATOR_1; */ system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); system_gclk_chan_enable(gclk_index); } /* I2C pin initialization */ void i2c_pin_init() { /* PA08 and PA09 set into peripheral function D*/ pin_set_peripheral_function(PINMUX_PA22C_SERCOM3_PAD0); // SDA pin_set_peripheral_function(PINMUX_PA23C_SERCOM3_PAD1); // SCL } /* I2C master initialization */ void i2c_master_init_2() { /* By setting the SPEED bit field as 0x01, I2C Master runs at Fast mode + - 1MHz, By setting the SDAHOLD bit field as 0x02, SDA hold time is configured for 300-600ns, By setting the RUNSTDBY bit as 0x01,Generic clock is enabled in all sleep modes,any interrupt can wake up the device, SERCOM2 is configured as an I2C Master by writing the MODE bitfield as 0x5 */ SERCOM3->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SPEED (FAST_MODE_PLUS) | SERCOM_I2CM_CTRLA_SDAHOLD(0x2) | SERCOM_I2CM_CTRLA_RUNSTDBY | SERCOM_I2CM_CTRLA_MODE_I2C_MASTER; /* smart mode enabled by setting the bit SMEN as 1 */ SERCOM3->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP);
/* BAUDLOW is non-zero, and baud register is loaded */ SERCOM3->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(11) | SERCOM_I2CM_BAUD_BAUDLOW(22); /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* SERCOM2 peripheral enabled by setting the ENABLE bit as 1*/ SERCOM3->I2CM.CTRLA.reg |= SERCOM_I2CM_CTRLA_ENABLE; /* SERCOM Enable synchronization busy */ while((SERCOM3->I2CM.SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_ENABLE)); /* bus state is forced into idle state */ SERCOM3->I2CM.STATUS.bit.BUSSTATE = 0x1; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* Both master on bus and slave on bus interrupt is enabled */ SERCOM3->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB; /* SERCOM2 handler enabled */ system_interrupt_enable(SERCOM3_IRQn); } /* I2C master Transaction */ void i2c_master_transact(void) { i = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* slave address with Write(0) */ SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done); i = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* slave address with read (1) */ SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; while(!rx_done); /*interrupts are cleared */ SERCOM3->I2CM.INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB; } int main (void) { system_init(); i2c_clock_init(); i2c_pin_init(); i2c_master_init_2(); i2c_master_transact(); while(1); } Behavior
Gesamte Nachricht
Byte 1 & 2 Byte 3 & 4
Byte 5 & 6 Byte 7 & 8
Ende ASF Tryout 4
Code
#include "asf.h" //Uses Files from the directory #include
//Config Gyro #define MPU6050_GYRO_FS_250 0x00 #define MPU6050_RA_GYRO_CONFIG 0x1B #define MPU6050_GCONFIG_FS_SEL_BIT 4 #define MPU6050_GCONFIG_FS_SEL_LENGTH 2
//Config Accelerometer #define MPU6050_ACCEL_FS_2 0x00 #define MPU6050_RA_ACCEL_CONFIG 0x1C #define MPU6050_ACONFIG_AFS_SEL_BIT 4 #define MPU6050_ACONFIG_AFS_SEL_LENGTH 2
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
/* Function Prototype */ void i2c_clock_init(void); void i2c_pin_init(void); void i2c_master_init_2(void); void i2c_master_transact(void); uint32_t calculate_baud(uint32_t, uint32_t); uint8_t Allocated_BUF_SIZE;
uint8_t tx_Gyro_Config_buf[2] = {MPU6050_RA_GYRO_CONFIG, 0x00}; uint8_t tx_Acc_Config_buf[2] = {MPU6050_RA_ACCEL_CONFIG, 0x00}; uint8_t tx_buf[BUF_SIZE]; uint8_t rx_buf[BUF_SIZE]; uint8_t i; uint8_t readmode = 0; volatile bool tx_done = false, rx_done = false;
// //void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { //I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer); //*ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; //*ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; //*az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; //*gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9]; //*gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11]; //*gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13]; //}
//bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { //// 010 value to write //// 76543210 bit numbers //// xxx args: bitStart=4, length=3 //// 00011100 mask byte //// 10101111 original value (sample) //// 10100011 original & ~mask //// 10101011 masked | value //uint8_t b; //if (readByte(devAddr, regAddr, &b) != 0) { //uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); //data <<= (bitStart - length + 1); // shift data into correct position //data &= mask; // zero all non-important bits in data //b &= ~(mask); // zero all important bits in existing byte //b |= data; // combine data with existing byte //return writeByte(devAddr, regAddr, b); //} else { //return false; //} //}
/* I2C handler */ void SERCOM3_Handler(void) {
/* Master on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.MB) { if (i == Allocated_BUF_SIZE) { /* After transferring the last byte stop condition will be sent */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); tx_done = true; i = 0; } else { /* placing the data from transmitting buffer to DATA register*/ SERCOM3->I2CM.DATA.reg = tx_buf[i++]; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } } /* Slave on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.SB) { if (i == (Allocated_BUF_SIZE-1)) { /* NACK should be sent before reading the last byte */ SERCOM3->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_done = true; } else { SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* sending ACK after reading each byte */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x2; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } } } /*Assigning pin to the alternate peripheral function*/ static inline void pin_set_peripheral_function(uint32_t pinmux) { uint8_t port = (uint8_t)((pinmux >> 16)/32); PORT->Group[port].PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1; PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >> 16) & 0x01u))); PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux & 0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u))); } /* calculating the BAUD value using Fgclk,Fscl,Trise FSCL =fGCLK / (10 + BAUD +BAUDLOW + fGCLKTRISE )*/ uint32_t calculate_baud(uint32_t fgclk, uint32_t fscl) { float f_temp, f_baud; f_temp = ((float)fgclk/(float)fscl) - (((float)fgclk/(float)1000000)*0.3); f_baud = (f_temp/2)-5; return ((uint32_t)f_baud); } /* SERCOM clock and peripheral bus clock initialization */ void i2c_clock_init() { struct system_gclk_chan_config gclk_chan_conf; uint32_t gclk_index = SERCOM3_GCLK_ID_CORE; /* Turn on module in PM */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_SERCOM3); /* Turn on Generic clock for I2C */ system_gclk_chan_get_config_defaults(&gclk_chan_conf); /* Default is generator 0. Other wise need to configure like below */ /* gclk_chan_conf.source_generator = GCLK_GENERATOR_1; */ system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); system_gclk_chan_enable(gclk_index); } /* I2C pin initialization */ void i2c_pin_init() { /* PA08 and PA09 set into peripheral function D*/ pin_set_peripheral_function(PINMUX_PA22C_SERCOM3_PAD0); // SDA pin_set_peripheral_function(PINMUX_PA23C_SERCOM3_PAD1); // SCL } /* I2C master initialization */ void i2c_master_init_2() { /* By setting the SPEED bit field as 0x01, I2C Master runs at Fast mode + - 1MHz, By setting the SDAHOLD bit field as 0x02, SDA hold time is configured for 300-600ns, By setting the RUNSTDBY bit as 0x01,Generic clock is enabled in all sleep modes,any interrupt can wake up the device, SERCOM2 is configured as an I2C Master by writing the MODE bitfield as 0x5 */ SERCOM3->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SPEED (STANDARD_MODE_FAST_MODE) | SERCOM_I2CM_CTRLA_SDAHOLD(0x2) | SERCOM_I2CM_CTRLA_RUNSTDBY | SERCOM_I2CM_CTRLA_MODE_I2C_MASTER; /* smart mode enabled by setting the bit SMEN as 1 */ SERCOM3->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP);
/* BAUDLOW is non-zero, and baud register is loaded */ SERCOM3->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(11) | SERCOM_I2CM_BAUD_BAUDLOW(22); /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* SERCOM2 peripheral enabled by setting the ENABLE bit as 1*/ SERCOM3->I2CM.CTRLA.reg |= SERCOM_I2CM_CTRLA_ENABLE; /* SERCOM Enable synchronization busy */ while((SERCOM3->I2CM.SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_ENABLE)); /* bus state is forced into idle state */ SERCOM3->I2CM.STATUS.bit.BUSSTATE = 0x1; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* Both master on bus and slave on bus interrupt is enabled */ SERCOM3->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB; /* SERCOM2 handler enabled */ system_interrupt_enable(SERCOM3_IRQn); } /* I2C master Transaction */ void i2c_master_transact(void) { if(readmode == 0){ i = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* slave address with Write(0) */ SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done); i = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } /* slave address with read (1) */ if(readmode == 1){
SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; while(!rx_done); /*interrupts are cleared */ SERCOM3->I2CM.INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB; readmode =0; } } int main (void) { system_init(); i2c_clock_init(); i2c_pin_init(); i2c_master_init_2(); tx_buf[0] = MPU6050_RA_GYRO_CONFIG; tx_buf[1] = 0x00; Allocated_BUF_SIZE = 2; i2c_master_transact(); tx_buf[0] = MPU6050_RA_ACCEL_CONFIG; tx_buf[1] = 0x00; Allocated_BUF_SIZE = 2; i2c_master_transact(); readmode = 1; tx_buf[0] = 0x3B; Allocated_BUF_SIZE = 1; i2c_master_transact(); while(1); } Behavior
1 Byte
2nd Byte 3Byte
4th Byte 1st Byte
2nd Byte 1st & 2nd Byte
ASF Tryout 5
Code
#include "asf.h" #define STANDARD_MODE_FAST_MODE 0x0 #define FAST_MODE_PLUS 0X01 #define HIGHSPEED_MODE 0X02 #define SLAVE_ADDR 0x68 #define BUF_SIZE 10 uint8_t BUFFER_SIZE = 2;
//Config Gyro #define MPU6050_GYRO_FS_250 0x00 #define MPU6050_RA_GYRO_CONFIG 0x1B #define MPU6050_GCONFIG_FS_SEL_BIT 4 #define MPU6050_GCONFIG_FS_SEL_LENGTH 2
//Config Accelerometer #define MPU6050_ACCEL_FS_2 0x00 #define MPU6050_RA_ACCEL_CONFIG 0x1C #define MPU6050_ACONFIG_AFS_SEL_BIT 4 #define MPU6050_ACONFIG_AFS_SEL_LENGTH 2
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
/* Function Prototype */ void i2c_clock_init(void); void i2c_pin_init(void); void i2c_master_init_2(void); void i2c_master_transact(void); uint32_t calculate_baud(uint32_t, uint32_t); uint8_t Allocated_BUF_SIZE;
uint8_t tx_Gyro_Config_buf[2] = {MPU6050_RA_GYRO_CONFIG, 0x00}; uint8_t tx_Acc_Config_buf[2] = {MPU6050_RA_ACCEL_CONFIG, 0x00}; uint8_t tx_buf[BUF_SIZE] = {MPU6050_RA_ACCEL_CONFIG, MPU6050_ACCEL_FS_2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //uint8_t tx_buf[BUF_SIZE] = {0x43}; uint8_t rx_buf[BUF_SIZE] = {0xAA, 0xAA}; uint8_t i; uint8_t mode = 0; uint8_t readmode = 0; volatile bool tx_done = false, rx_done = false;
// //void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { //I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer); //*ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; //*ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; //*az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; //*gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9]; //*gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11]; //*gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13]; //} //bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { //// 010 value to write //// 76543210 bit numbers //// xxx args: bitStart=4, length=3 //// 00011100 mask byte //// 10101111 original value (sample) //// 10100011 original & ~mask //// 10101011 masked | value //uint8_t b; //if (readByte(devAddr, regAddr, &b) != 0) { //uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); //data <<= (bitStart - length + 1); // shift data into correct position //data &= mask; // zero all non-important bits in data //b &= ~(mask); // zero all important bits in existing byte //b |= data; // combine data with existing byte //return writeByte(devAddr, regAddr, b); //} else { //return false; //} //}
/* I2C handler */ void SERCOM3_Handler(void) {
/* Master on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.MB) { if (i == BUFFER_SIZE) { switch (mode) {
case 0: /* After transferring the last byte stop condition will be sent */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); tx_done = true; i = 0; break;
case 1: //SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; // SERCOM3->I2CM.CTRLB.bit.CMD = 0x1; // while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); //SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; // tx_done = true; // i = 0; SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); tx_done = true; i = 0; break; } }
else { /* placing the data from transmitting buffer to DATA register*/ SERCOM3->I2CM.DATA.reg = tx_buf[i++]; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } } /* Slave on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.SB) { if (i == (BUFFER_SIZE-1)) { /* NACK should be sent before reading the last byte */ SERCOM3->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_done = true; } else { SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* sending ACK after reading each byte */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x2; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } // { /* placing the data from transmitting buffer to DATA register*/ // SERCOM3->I2CM.DATA.reg = tx_buf[i++]; // while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); // }
} }
/*Assigning pin to the alternate peripheral function*/ static inline void pin_set_peripheral_function(uint32_t pinmux) { uint8_t port = (uint8_t)((pinmux >> 16)/32); PORT->Group[port].PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1; PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >> 16) & 0x01u))); PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux & 0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u))); } /* calculating the BAUD value using Fgclk,Fscl,Trise FSCL =fGCLK / (10 + BAUD +BAUDLOW + fGCLKTRISE )*/ uint32_t calculate_baud(uint32_t fgclk, uint32_t fscl) { float f_temp, f_baud; f_temp = ((float)fgclk/(float)fscl) - (((float)fgclk/(float)1000000)*0.3); f_baud = (f_temp/2)-5; return ((uint32_t)f_baud); } /* SERCOM clock and peripheral bus clock initialization */ void i2c_clock_init() { struct system_gclk_chan_config gclk_chan_conf; uint32_t gclk_index = SERCOM3_GCLK_ID_CORE; /* Turn on module in PM */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_SERCOM3); /* Turn on Generic clock for I2C */ system_gclk_chan_get_config_defaults(&gclk_chan_conf); /* Default is generator 0. Other wise need to configure like below */ /* gclk_chan_conf.source_generator = GCLK_GENERATOR_1; */ system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); system_gclk_chan_enable(gclk_index); } /* I2C pin initialization */ void i2c_pin_init() { /* PA08 and PA09 set into peripheral function D*/ pin_set_peripheral_function(PINMUX_PA22C_SERCOM3_PAD0); // SDA pin_set_peripheral_function(PINMUX_PA23C_SERCOM3_PAD1); // SCL } /* I2C master initialization */ void i2c_master_init_2() { /* By setting the SPEED bit field as 0x01, I2C Master runs at Fast mode + - 1MHz, By setting the SDAHOLD bit field as 0x02, SDA hold time is configured for 300-600ns, By setting the RUNSTDBY bit as 0x01,Generic clock is enabled in all sleep modes,any interrupt can wake up the device, SERCOM2 is configured as an I2C Master by writing the MODE bitfield as 0x5 */ SERCOM3->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SPEED (STANDARD_MODE_FAST_MODE) | SERCOM_I2CM_CTRLA_SDAHOLD(0x2) | SERCOM_I2CM_CTRLA_RUNSTDBY | SERCOM_I2CM_CTRLA_MODE_I2C_MASTER; /* smart mode enabled by setting the bit SMEN as 1 */ SERCOM3->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP);
/* BAUDLOW is non-zero, and baud register is loaded */ SERCOM3->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(11) | SERCOM_I2CM_BAUD_BAUDLOW(22); /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* SERCOM2 peripheral enabled by setting the ENABLE bit as 1*/ SERCOM3->I2CM.CTRLA.reg |= SERCOM_I2CM_CTRLA_ENABLE; /* SERCOM Enable synchronization busy */ while((SERCOM3->I2CM.SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_ENABLE)); /* bus state is forced into idle state */ SERCOM3->I2CM.STATUS.bit.BUSSTATE = 0x1; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* Both master on bus and slave on bus interrupt is enabled */ SERCOM3->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB; /* SERCOM2 handler enabled */ system_interrupt_enable(SERCOM3_IRQn); } /* I2C master Transaction */ void i2c_master_transact(void) { i = 0; mode = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* slave address with Write(0) */ SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done); i = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* slave address with read (1) */ BUFFER_SIZE = 1; tx_buf[0] = 0x72; mode = 1; tx_done = false; SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done); i = 0; SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; while(!rx_done); /*interrupts are cleared */ SERCOM3->I2CM.INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB; } int main (void) { system_init(); i2c_clock_init(); i2c_pin_init(); i2c_master_init_2(); // tx_buf[0] = MPU6050_RA_GYRO_CONFIG; // tx_buf[1] = 0x00; // Allocated_BUF_SIZE = 1; i2c_master_transact(); // tx_buf[0] = MPU6050_RA_ACCEL_CONFIG; // tx_buf[1] = 0x00; // Allocated_BUF_SIZE = 1; // i2c_master_transact(); // readmode = 1; // tx_buf[0] = 0x3B; // Allocated_BUF_SIZE = 0; // i2c_master_transact(); while(1); }
Behavior 1st Byte Config Sequence 2nd Byte Config Sequence
3rd Byte Config Sequence 1st Byte Read Sequence
2nd Byte Read Sequence 3rd Byte Read Sequence
ASF Tryout 6
Code
#include "asf.h" #define STANDARD_MODE_FAST_MODE 0x0 #define FAST_MODE_PLUS 0X01 #define HIGHSPEED_MODE 0X02 #define SLAVE_ADDR 0x68 #define BUF_SIZE 10 uint8_t BUFFER_SIZE = 2;
//Config Gyro #define MPU6050_GYRO_FS_250 0x00 #define MPU6050_RA_GYRO_CONFIG 0x1B #define MPU6050_GCONFIG_FS_SEL_BIT 4 #define MPU6050_GCONFIG_FS_SEL_LENGTH 2
//Config Accelerometer #define MPU6050_ACCEL_FS_2 0x00 #define MPU6050_RA_ACCEL_CONFIG 0x1C #define MPU6050_ACONFIG_AFS_SEL_BIT 4 #define MPU6050_ACONFIG_AFS_SEL_LENGTH 2
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
/* Function Prototype */ void i2c_clock_init(void); void i2c_pin_init(void); void i2c_master_init_2(void); void i2c_master_transact(void); uint32_t calculate_baud(uint32_t, uint32_t); uint8_t Allocated_BUF_SIZE;
uint8_t tx_Gyro_Config_buf[2] = {MPU6050_RA_GYRO_CONFIG, 0x00}; uint8_t tx_Acc_Config_buf[2] = {MPU6050_RA_ACCEL_CONFIG, 0x00}; uint8_t tx_buf[BUF_SIZE] = {MPU6050_RA_GYRO_CONFIG, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //uint8_t tx_buf[BUF_SIZE] = {0x43}; uint8_t rx_buf[BUF_SIZE] = {0xAA, 0xAA}; uint8_t i; uint8_t mode = 0; uint8_t readmode = 0; volatile bool tx_done = false, rx_done = false;
/* I2C handler */ void SERCOM3_Handler(void) {
/* Master on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.MB) { if (i == BUFFER_SIZE) { switch (mode) {
case 0: /* After transferring the last byte stop condition will be sent */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); tx_done = true; i = 0; break;
case 1: SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; tx_done = true; i = 0; break; } }
else { /* placing the data from transmitting buffer to DATA register*/ SERCOM3->I2CM.DATA.reg = tx_buf[i++]; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } } /* Slave on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.SB) { if (i == (BUFFER_SIZE-1)) { /* NACK should be sent before reading the last byte */ SERCOM3->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_done = true; } else { SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* sending ACK after reading each byte */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x2; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } // { /* placing the data from transmitting buffer to DATA register*/ // SERCOM3->I2CM.DATA.reg = tx_buf[i++]; // while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); // }
} }
/*Assigning pin to the alternate peripheral function*/ static inline void pin_set_peripheral_function(uint32_t pinmux) { uint8_t port = (uint8_t)((pinmux >> 16)/32); PORT->Group[port].PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1; PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >> 16) & 0x01u))); PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux & 0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u))); } /* calculating the BAUD value using Fgclk,Fscl,Trise FSCL =fGCLK / (10 + BAUD +BAUDLOW + fGCLKTRISE )*/ uint32_t calculate_baud(uint32_t fgclk, uint32_t fscl) { float f_temp, f_baud; f_temp = ((float)fgclk/(float)fscl) - (((float)fgclk/(float)1000000)*0.3); f_baud = (f_temp/2)-5; return ((uint32_t)f_baud); } /* SERCOM clock and peripheral bus clock initialization */ void i2c_clock_init() { struct system_gclk_chan_config gclk_chan_conf; uint32_t gclk_index = SERCOM3_GCLK_ID_CORE; /* Turn on module in PM */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_SERCOM3); /* Turn on Generic clock for I2C */ system_gclk_chan_get_config_defaults(&gclk_chan_conf); /* Default is generator 0. Other wise need to configure like below */ /* gclk_chan_conf.source_generator = GCLK_GENERATOR_1; */ system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); system_gclk_chan_enable(gclk_index); } /* I2C pin initialization */ void i2c_pin_init() { /* PA08 and PA09 set into peripheral function D*/ pin_set_peripheral_function(PINMUX_PA22C_SERCOM3_PAD0); // SDA pin_set_peripheral_function(PINMUX_PA23C_SERCOM3_PAD1); // SCL } /* I2C master initialization */ void i2c_master_init_2() { /* By setting the SPEED bit field as 0x01, I2C Master runs at Fast mode + - 1MHz, By setting the SDAHOLD bit field as 0x02, SDA hold time is configured for 300-600ns, By setting the RUNSTDBY bit as 0x01,Generic clock is enabled in all sleep modes,any interrupt can wake up the device, SERCOM2 is configured as an I2C Master by writing the MODE bitfield as 0x5 */ SERCOM3->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SPEED (STANDARD_MODE_FAST_MODE) | SERCOM_I2CM_CTRLA_SDAHOLD(0x2) | SERCOM_I2CM_CTRLA_RUNSTDBY | SERCOM_I2CM_CTRLA_MODE_I2C_MASTER; /* smart mode enabled by setting the bit SMEN as 1 */ SERCOM3->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP);
/* BAUDLOW is non-zero, and baud register is loaded */ SERCOM3->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(11) | SERCOM_I2CM_BAUD_BAUDLOW(22); /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* SERCOM2 peripheral enabled by setting the ENABLE bit as 1*/ SERCOM3->I2CM.CTRLA.reg |= SERCOM_I2CM_CTRLA_ENABLE; /* SERCOM Enable synchronization busy */ while((SERCOM3->I2CM.SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_ENABLE)); /* bus state is forced into idle state */ SERCOM3->I2CM.STATUS.bit.BUSSTATE = 0x1; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* Both master on bus and slave on bus interrupt is enabled */ SERCOM3->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB; /* SERCOM2 handler enabled */ system_interrupt_enable(SERCOM3_IRQn); } /* I2C master Transaction */ void i2c_master_transact(void) { i = 0; mode = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* slave address with Write(0) */ SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done); i = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* slave address with read (1) */ BUFFER_SIZE = 1; tx_buf[0] = 0x3B; mode = 1; tx_done = false; SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done); i = 0; SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; while(!rx_done); /*interrupts are cleared */ SERCOM3->I2CM.INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB; } int main (void) { system_init(); i2c_clock_init(); i2c_pin_init(); i2c_master_init_2(); i2c_master_transact(); while(1); }
Behavior
1st Byte first sequence 2nd Byte first sequence
3rd Byte first sequence 1st Byte Read sequence
1st and second byte read sequence 3rd and fourth byte read sequence
ASF Tryout 7
Code
#include "asf.h" //#include "MPU6050.h" #define STANDARD_MODE_FAST_MODE 0x0 #define FAST_MODE_PLUS 0X01 #define HIGHSPEED_MODE 0X02 #define SLAVE_ADDR 0x68 #define BUF_SIZE 10 uint8_t BUFFER_SIZE = 2;
//Config Gyro #define MPU6050_GYRO_FS_250 0x00 #define MPU6050_RA_GYRO_CONFIG 0x1B #define MPU6050_GCONFIG_FS_SEL_BIT 4 #define MPU6050_GCONFIG_FS_SEL_LENGTH 2
//Config Accelerometer #define MPU6050_ACCEL_FS_2 0x00 #define MPU6050_RA_ACCEL_CONFIG 0x1C #define MPU6050_ACONFIG_AFS_SEL_BIT 4 #define MPU6050_ACONFIG_AFS_SEL_LENGTH 2
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
#define MPU6050_RA_USER_CTRL 0x73 #define MPU6050_RA_FIFO_R_W 0x74
/* Function Prototype */ void i2c_clock_init(void); void i2c_pin_init(void); void i2c_master_init_2(void); void i2c_master_transact(void); uint32_t calculate_baud(uint32_t, uint32_t); uint8_t Allocated_BUF_SIZE;
uint8_t tx_Gyro_Config_buf[2] = {MPU6050_RA_GYRO_CONFIG, 0x00}; uint8_t tx_Acc_Config_buf[2] = {MPU6050_RA_ACCEL_CONFIG, 0x00}; uint8_t tx_buf[BUF_SIZE] = {MPU6050_RA_USER_CTRL, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //uint8_t tx_buf[BUF_SIZE] = {0x43}; uint8_t rx_buf[BUF_SIZE] = {0xAA, 0xAA}; uint8_t i; uint8_t mode = 0; uint8_t readmode = 0; volatile bool tx_done = false, rx_done = false;
/* I2C handler */ void SERCOM3_Handler(void) {
/* Master on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.MB) { if (i == BUFFER_SIZE) { switch (mode) {
case 0: /* After transferring the last byte stop condition will be sent */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); tx_done = true; i = 0; break;
case 1: //SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; // tx_done = true; //i = 0; SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); tx_done = true; i = 0;
break; } }
else { /* placing the data from transmitting buffer to DATA register*/ SERCOM3->I2CM.DATA.reg = tx_buf[i++]; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } } /* Slave on bus interrupt checking */ if (SERCOM3->I2CM.INTFLAG.bit.SB) { if (i == (BUFFER_SIZE-1)) { /* NACK should be sent before reading the last byte */ SERCOM3->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.CTRLB.bit.CMD = 0x3; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_done = true; } else { SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); rx_buf[i++] = SERCOM3->I2CM.DATA.reg; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* sending ACK after reading each byte */ SERCOM3->I2CM.CTRLB.bit.CMD = 0x2; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); } // { /* placing the data from transmitting buffer to DATA register*/ // SERCOM3->I2CM.DATA.reg = tx_buf[i++]; // while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); // }
} }
/*Assigning pin to the alternate peripheral function*/ static inline void pin_set_peripheral_function(uint32_t pinmux) { uint8_t port = (uint8_t)((pinmux >> 16)/32); PORT->Group[port].PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1; PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >> 16) & 0x01u))); PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux & 0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u))); } /* calculating the BAUD value using Fgclk,Fscl,Trise FSCL =fGCLK / (10 + BAUD +BAUDLOW + fGCLKTRISE )*/ uint32_t calculate_baud(uint32_t fgclk, uint32_t fscl) { float f_temp, f_baud; f_temp = ((float)fgclk/(float)fscl) - (((float)fgclk/(float)1000000)*0.3); f_baud = (f_temp/2)-5; return ((uint32_t)f_baud); } /* SERCOM clock and peripheral bus clock initialization */ void i2c_clock_init() { struct system_gclk_chan_config gclk_chan_conf; uint32_t gclk_index = SERCOM3_GCLK_ID_CORE; /* Turn on module in PM */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_SERCOM3); /* Turn on Generic clock for I2C */ system_gclk_chan_get_config_defaults(&gclk_chan_conf); /* Default is generator 0. Other wise need to configure like below */ /* gclk_chan_conf.source_generator = GCLK_GENERATOR_1; */ system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); system_gclk_chan_enable(gclk_index); } /* I2C pin initialization */ void i2c_pin_init() { /* PA08 and PA09 set into peripheral function D*/ pin_set_peripheral_function(PINMUX_PA22C_SERCOM3_PAD0); // SDA pin_set_peripheral_function(PINMUX_PA23C_SERCOM3_PAD1); // SCL } /* I2C master initialization */ void i2c_master_init_2() { /* By setting the SPEED bit field as 0x01, I2C Master runs at Fast mode + - 1MHz, By setting the SDAHOLD bit field as 0x02, SDA hold time is configured for 300-600ns, By setting the RUNSTDBY bit as 0x01,Generic clock is enabled in all sleep modes,any interrupt can wake up the device, SERCOM2 is configured as an I2C Master by writing the MODE bitfield as 0x5 */ SERCOM3->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SPEED (STANDARD_MODE_FAST_MODE) | SERCOM_I2CM_CTRLA_SDAHOLD(0x2) | SERCOM_I2CM_CTRLA_RUNSTDBY | SERCOM_I2CM_CTRLA_MODE_I2C_MASTER; /* smart mode enabled by setting the bit SMEN as 1 */ SERCOM3->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP);
/* BAUDLOW is non-zero, and baud register is loaded */ SERCOM3->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(11) | SERCOM_I2CM_BAUD_BAUDLOW(22); /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* SERCOM2 peripheral enabled by setting the ENABLE bit as 1*/ SERCOM3->I2CM.CTRLA.reg |= SERCOM_I2CM_CTRLA_ENABLE; /* SERCOM Enable synchronization busy */ while((SERCOM3->I2CM.SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_ENABLE)); /* bus state is forced into idle state */ SERCOM3->I2CM.STATUS.bit.BUSSTATE = 0x1; /* synchronization busy */ while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* Both master on bus and slave on bus interrupt is enabled */ SERCOM3->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB; /* SERCOM2 handler enabled */ system_interrupt_enable(SERCOM3_IRQn); } /* I2C master Transaction */ void i2c_master_transact(void) { i = 0; mode = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); /* slave address with Write(0) */ SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done); i = 0; /* Acknowledge section is set as ACK signal by writing 0 in ACKACT bit */ SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP);
uint8_t tx_buf[BUF_SIZE] = {MPU6050_RA_FIFO_R_W, 0xAA, 0x6F, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done);
/* slave address with read (1) */ BUFFER_SIZE = 1; tx_buf[0] = MPU6050_RA_FIFO_R_W; mode = 1; tx_done = false; SERCOM3->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; while(SERCOM3->I2CM.SYNCBUSY.bit.SYSOP); SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 0; while(!tx_done); i = 0; SERCOM3->I2CM.ADDR.reg = (SLAVE_ADDR << 1) | 1; while(!rx_done); /*interrupts are cleared */ SERCOM3->I2CM.INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB; } int main (void) { system_init(); i2c_clock_init(); i2c_pin_init(); i2c_master_init_2(); i2c_master_transact(); while(1); }
Behavior
Not comperable because FIFO Buffer shall be read