From 86c4e0e7128da03a11328514520ecf7039ce6e4c Mon Sep 17 00:00:00 2001 From: Daichou Date: Wed, 5 Apr 2017 00:02:52 +0800 Subject: [PATCH] Fix I2C Read Sequence extra unused byte transmission error Due to extra unused byte transmission in the Read Sequence,causing I2C cannot successfully pass test_connection function. Bug discription: Predicted Reading Sequence Master |S|AD+W| |RA| |S|AD+R| | |NACK|P| Slave | | |ACK| |ACK| | |ACK|DATA| | | But,in the second Start condition,original code could cause extra byte(because using RestartI2C() function). Using StopI2C() and then StartI2C() can fix this error --- .../nbproject/Makefile-genesis.properties | 2 +- .../Examples/MPU6050_example.X/I2Cdev.c | 43 ++-- .../Examples/MPU6050_example.X/MPU6050.c | 15 +- .../MPU6050_example.X/MPU6050_example_main.c | 220 ++++++++++++------ .../nbproject/Makefile-genesis.properties | 2 +- 5 files changed, 184 insertions(+), 98 deletions(-) diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties index 249d7262..d1044901 100644 --- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties @@ -1,5 +1,5 @@ # -#Tue Apr 04 10:56:56 CST 2017 +#Tue Apr 04 21:56:23 CST 2017 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin configurations-xml=e23099a44127c530cab293bfc5554ec5 diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c index 27909fee..a51d9766 100644 --- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c +++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c @@ -101,7 +101,7 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle IFS0bits.MI2CIF = 0; // Clear interrupt flag //while(I2CSTATbits.ACKSTAT); - //delay_ms_I2C(10); + //delay_us_I2C(100); /*Master send RA*/ /* Write Register Address */ MasterWriteI2C(regAddr); @@ -114,15 +114,22 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ IFS0bits.MI2CIF = 0; // Clear interrupt flag while(I2CSTATbits.ACKSTAT); - //delay_ms_I2C(10); + //delay_us_I2C(100); + + /*Master Pause*/ + StopI2C(); + /* Wait till stop sequence is completed */ + while(I2CCONbits.PEN); + /*Master Start*/ - RestartI2C(); + StartI2C(); /* Wait till Start sequence is completed */ while(I2CCONbits.SEN); /*Master send AD+R*/ /* Write Slave Address (Read)*/ MasterWriteI2C(devAddr << 1 | 0x01); + //while(!MasterWriteI2C(devAddr << 1 | 0x01)); /* Wait until address is transmitted */ while(I2CSTATbits.TBF); // 8 clock cycles @@ -130,12 +137,13 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle IFS0bits.MI2CIF = 0; // Clear interrupt flag while(I2CSTATbits.ACKSTAT); - //delay_ms_I2C(10); + //delay_us_I2C(100); /*Slave send DATA*/ //uint16_t flag = MastergetsI2C(length,data,I2C_DATA_WAIT); /*Slave send NACK*/ + //MastergetsI2C(length,data,100); //NotAckI2C(); data[0] = MasterReadI2C(); @@ -143,7 +151,6 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ for (i = 1 ; i < length ; i++ ){ AckI2C(); while(I2CCONbits.ACKEN == 1); - //delay_ms_I2C(10); data[i] = MasterReadI2C(); } NotAckI2C(); @@ -153,8 +160,8 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ /* Wait till stop sequence is completed */ while(I2CCONbits.PEN); //CloseI2C(); - IdleI2C(); - return true; + //IdleI2C(); + return length; } /** Read single byte from an 8-bit device register. @@ -290,7 +297,6 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t while(I2CCONbits.SEN); /* Clear interrupt flag */ IFS0bits.MI2CIF = 0; - //delay_ms_I2C(10); /*Master send AD+W*/ /* Write Slave address (Write)*/ @@ -302,7 +308,7 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle IFS0bits.MI2CIF = 0; // Clear interrupt flag while(I2CSTATbits.ACKSTAT); - //delay_ms_I2C(10); + //delay_us_I2C(100); /*Master send RA*/ /* Write Slave address (Write)*/ @@ -313,20 +319,31 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t /*Slave send ACK*/ while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle IFS0bits.MI2CIF = 0; // Clear interrupt flag - //delay_ms_I2C(10); + //delay_us_I2C(100); while(I2CSTATbits.ACKSTAT); /*Master send data*/ /* Transmit string of data */ MasterputsI2C(data); + //uint8_t i; + //for (i = 0 ; i < length ; i++){ + // MasterWriteI2C(data[i]); + /* Wait till address is transmitted */ + // while(I2CSTATbits.TBF); // 8 clock cycles + + /*Slave send ACK*/ + // while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle + // IFS0bits.MI2CIF = 0; // Clear interrupt flag + //delay_us_I2C(100); + //} while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle IFS0bits.MI2CIF = 0; // Clear interrupt flag - + StopI2C(); /* Wait till stop sequence is completed */ while(I2CCONbits.PEN); //CloseI2C(); - IdleI2C(); + //IdleI2C(); return true; } @@ -419,7 +436,7 @@ bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_ 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 - delay_ms_I2C(10); + //delay_ms_I2C(10); return I2Cdev_writeByte(devAddr, regAddr, b); } else { return false; diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c index fb0abb47..bb31b001 100644 --- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c +++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c @@ -90,17 +90,10 @@ void MPU6050(uint8_t address) */ void MPU6050_initialize() { - - - MPU6050_setSleepEnabled( - false); // thanks to Jack Elston for pointing this one out! - delay_ms(20); - MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO); - delay_ms(20); - MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2); - delay_ms(20); - MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250); - delay_ms(100); + MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO); + MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250); + MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + MPU6050_setSleepEnabled(false); } /** Verify the I2C connection. diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c index 34064fec..3bab9908 100644 --- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c +++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c @@ -6,12 +6,13 @@ */ + // DSPIC30F4013 Configuration Bit Settings // 'C' source line config statements // FOSC -#pragma config FOSFPR = XT_PLL8 // Oscillator (XT w/PLL 8x) +#pragma config FOSFPR = ECIO_PLL8 // Oscillator (ECIO w/PLL 8x) #pragma config FCKSMEN = CSW_FSCM_OFF // Clock Switching and Monitor (Sw Disabled, Mon Disabled) // FWDT @@ -20,7 +21,7 @@ #pragma config WDT = WDT_OFF // Watchdog Timer (Disabled) // FBORPOR -#pragma config FPWRT = PWRT_64 // POR Timer Value (64ms) +#pragma config FPWRT = PWRT_OFF // POR Timer Value (Timer Disabled) #pragma config BODENV = BORV20 // Brown Out Voltage (Reserved) #pragma config BOREN = PBOR_OFF // PBOR Enable (Disabled) #pragma config MCLRE = MCLR_EN // Master Clear Enable (Enabled) @@ -35,7 +36,10 @@ // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. -#include +#include + + + #include #include #include @@ -44,6 +48,7 @@ /* Received data is stored in array Buf */ char Buf[80]; char* Receivedddata = Buf; +int16_t ax, ay, az, gx, gy, gz; /* This is UART1 transmit ISR */ void __attribute__((__interrupt__)) _U2TXInterrupt(void) { @@ -62,79 +67,150 @@ void __attribute__((__interrupt__)) _U2TXInterrupt(void) int main(void) { + delay_ms(1000); TRISCbits.TRISC14 = 0; LATCbits.LATC14 = 1; while(1){ - /* Data to be transmitted using UART communication module */ - //TRISFbits.TRISF3 = 0; - //PORTFbits.RF3 = 0; - //delay_ms(10); - //PORTFbits.RF3 = 1; - TRISFbits.TRISF3 = 1; - char Buffer[80]; - //char - /* Holds the value of baud register */ - unsigned int baudvalue; - /* Holds the value of uart config reg */ - unsigned int U2MODEvalue; - /* Holds the information regarding uart - TX & RX interrupt modes */ - unsigned int U2STAvalue; - CloseI2C(); - /* Turn off UART1module */ - CloseUART2(); - /* Configure uart1 transmit interrupt */ - ConfigIntUART2( UART_TX_INT_DIS & UART_TX_INT_PR2); - /* Configure UART1 module to transmit 8 bit data with one stopbit. Also Enable loopback mode */ - baudvalue = 129; //9600 - U2MODEvalue = UART_EN & UART_IDLE_CON & - UART_DIS_WAKE & UART_DIS_LOOPBACK & - UART_EN_ABAUD & UART_NO_PAR_8BIT & - UART_1STOPBIT; - U2STAvalue = UART_INT_TX_BUF_EMPTY & - UART_TX_PIN_NORMAL & - UART_TX_ENABLE & UART_INT_RX_3_4_FUL & - UART_ADR_DETECT_DIS & - UART_RX_OVERRUN_CLEAR; - unsigned int I2C_config1,I2C_config2; - I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_REL & - I2C_IPMI_DIS & I2C_7BIT_ADD & - I2C_SLW_EN & I2C_SM_DIS & - I2C_GCALL_DIS & I2C_STR_DIS & - I2C_ACK & I2C_ACK_EN & I2C_RCV_EN & - I2C_STOP_DIS & I2C_RESTART_EN & - I2C_START_DIS); - I2C_config2 = 181; - ConfigIntI2C(MI2C_INT_OFF & SI2C_INT_OFF); - OpenI2C(I2C_config1,I2C_config2); - OpenUART2(U2MODEvalue, U2STAvalue, baudvalue); - - MPU6050(MPU6050_ADDRESS_AD0_LOW); - sprintf(Buf,"Initialize MPU6050\n\0"); - /* Load transmit buffer and transmit the same till null character is encountered */ - putsUART2 ((unsigned int *)Buf); - /* Wait for transmission to complete */ - while(BusyUART2()); - - MPU6050_initialize(); - - sprintf(Buf,"Testing device connections...\n\0"); - putsUART2 ((unsigned int *)Buf); - /* Wait for transmission to complete */ - while(BusyUART2()); - - sprintf(Buf,MPU6050_testConnection() ? "MPU6050 connection successful\r\n" : - "MPU6050 connection failed\r\n"); - putsUART2 ((unsigned int *)Buf); - /* Wait for transmission to complete */ - while(BusyUART2()); - - - - - //CloseUART2(); - + HEAD: + /* Data to be transmitted using UART communication module */ + //TRISFbits.TRISF3 = 0; + //PORTFbits.RF3 = 0; + //delay_ms(10); + //PORTFbits.RF3 = 1; + TRISFbits.TRISF3 = 0; + TRISFbits.TRISF2 = 0; + char Buffer[80]; + //char + /* Holds the value of baud register */ + unsigned int baudvalue; + /* Holds the value of uart config reg */ + unsigned int U2MODEvalue; + /* Holds the information regarding uart + TX & RX interrupt modes */ + unsigned int U2STAvalue; + CloseI2C(); + /* Turn off UART1module */ + CloseUART2(); + /* Configure uart1 transmit interrupt */ + ConfigIntUART2( UART_TX_INT_DIS & UART_TX_INT_PR2); + /* Configure UART1 module to transmit 8 bit data with one stopbit. Also Enable loopback mode */ + baudvalue = 129; //9600 + U2MODEvalue = UART_EN & UART_IDLE_CON & + UART_DIS_WAKE & UART_DIS_LOOPBACK & + UART_EN_ABAUD & UART_NO_PAR_8BIT & + UART_1STOPBIT; + U2STAvalue = UART_INT_TX_BUF_EMPTY & + UART_TX_PIN_NORMAL & + UART_TX_ENABLE & UART_INT_RX_3_4_FUL & + UART_ADR_DETECT_DIS & + UART_RX_OVERRUN_CLEAR; + unsigned int I2C_config1,I2C_config2; + I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_REL & + I2C_IPMI_DIS & I2C_7BIT_ADD & + I2C_SLW_DIS & I2C_SM_DIS & + I2C_GCALL_DIS & I2C_STR_EN & + I2C_ACK & I2C_ACK_EN & I2C_RCV_EN & + I2C_STOP_DIS & I2C_RESTART_EN & + I2C_START_DIS); + I2C_config2 = 381; + ConfigIntI2C(MI2C_INT_OFF & SI2C_INT_OFF); + OpenI2C(I2C_config1,I2C_config2); + OpenUART2(U2MODEvalue, U2STAvalue, baudvalue); + + MPU6050(MPU6050_ADDRESS_AD0_LOW); + sprintf(Buf,"Initialize MPU6050\n\0"); + /* Load transmit buffer and transmit the same till null character is encountered */ + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + //MPU6050_reset(); + //delay_ms(100); + //MPU6050_resetGyroscopePath(); + //MPU6050_resetAccelerometerPath(); + //MPU6050_resetTemperaturePath(); + //delay_ms(100); + MPU6050_initialize(); + MPU6050_setSleepEnabled(false); + unsigned char MPU6050_ID = MPU6050_getDeviceID(); + + sprintf(Buf,"Testing device connections...\n\0"); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + + + sprintf(Buf,"MPU6050_ID = 0x%X\n",MPU6050_ID); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + + sprintf(Buf,MPU6050_testConnection() ? "MPU6050 connection successful\r\n" : + "MPU6050 connection failed\r\n"); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + if (!MPU6050_testConnection()) + goto HEAD; + + sprintf(Buf,"Reading offset\n"); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + sprintf(Buf,"Xaccel= %d\n",MPU6050_getXAccelOffset()); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + sprintf(Buf,"Yaccel= %d\n",MPU6050_getYAccelOffset()); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + sprintf(Buf,"Zaccel= %d\n",MPU6050_getZAccelOffset()); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + sprintf(Buf,"Xgyro= %d\n",MPU6050_getXGyroOffset()); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + sprintf(Buf,"Ygyro= %d\n",MPU6050_getYGyroOffset()); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + sprintf(Buf,"Zgyro= %d\n",MPU6050_getZGyroOffset()); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + + while (true) { + // Read raw accel/gyro measurements from device + MPU6050_getMotion6(&ax, &ay, &az, &gx, &gy, &gz); + + // Display tab-separated accel/gyro x/y/z values + sprintf(Buf,"a/g:\t%d\t%d\t%d\t%d\t%d\t%d\r\n", ax, ay, az, gx, gy, gz); + putsUART2 ((unsigned int *)Buf); + /* Wait for transmission to complete */ + while(BusyUART2()); + + // Blink LED to indicate activity + LATCbits.LATC14 ^= 1; + + delay_ms(25); + delay_ms(25); + } + + //CloseUART2(); + } return 0; } diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties index a5eb6e5c..59fffcfc 100644 --- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties +++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties @@ -1,5 +1,5 @@ # -#Tue Apr 04 10:56:56 CST 2017 +#Tue Apr 04 21:56:22 CST 2017 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin configurations-xml=390e761992510ba6b77d8cf6d2379168