Hi everyone, I need help!
im working with mpu6050 and my TM4C123GH6PM but it doesn't work
- when i use a osciloscope, my "clock" (SCL) looks like a glitch, maybe the PB2 has a wrong configuration
- I have no idea if i have to use Fifos.
- I know just a little bit about I2C, so... actually i dont have idea what i write in my code :(
PSD. There are some parts in spanish because im from Peru
#include "tm4c123gh6pm.h"
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
#include "hw_memmap.h"
#include "hw_i2c.h"
#include "hw_types.h"
#include "hw_gpio.h"
#include "i2c.h"
#include "gpio.h"
#include "sysctl.h"
#include "pin_map.h"
//*******************************************************
// Register names according to the datasheet.
// According to the InvenSense document
// "MPU-6000 and MPU-6050 Register Map
// and Descriptions Revision 4.2"
//Register Names ending in _H and _L
//contain the high and low bytes, respectively,
//of an internal register value
#define MPU6050_SELF_TEST_X 0x0D // R/W
#define MPU6050_SELF_TEST_Y 0x0E // R/W
#define MPU6050_SELF_TEST_Z 0x0F // R/W
#define MPU6050_SELF_TEST_A 0x10 // R/W
#define MPU6050_SMPLRT_DIV 0x19 // R/W
#define MPU6050_CONFIG 0x1A // R/W
#define MPU6050_GYRO_CONFIG 0x1B // R/W
#define MPU6050_ACCEL_CONFIG 0x1C // R/W
#define MPU6050_FIFO_EN 0x23 // R/W
#define MPU6050_I2C_MST_CTRL 0x24 // R/W
#define MPU6050_I2C_SLV0_ADDR 0x25 // R/W
#define MPU6050_I2C_SLV0_REG 0x26 // R/W
#define MPU6050_I2C_SLV0_CTRL 0x27 // R/W
#define MPU6050_I2C_SLV1_ADDR 0x28 // R/W
#define MPU6050_I2C_SLV1_REG 0x29 // R/W
#define MPU6050_I2C_SLV1_CTRL 0x2A // R/W
#define MPU6050_I2C_SLV2_ADDR 0x2B // R/W
#define MPU6050_I2C_SLV2_REG 0x2C // R/W
#define MPU6050_I2C_SLV2_CTRL 0x2D // R/W
#define MPU6050_I2C_SLV3_ADDR 0x2E // R/W
#define MPU6050_I2C_SLV3_REG 0x2F // R/W
#define MPU6050_I2C_SLV3_CTRL 0x30 // R/W
#define MPU6050_I2C_SLV4_ADDR 0x31 // R/W
#define MPU6050_I2C_SLV4_REG 0x32 // R/W
#define MPU6050_I2C_SLV4_DO 0x33 // R/W
#define MPU6050_I2C_SLV4_CTRL 0x34 // R/W
#define MPU6050_I2C_SLV4_DI 0x35 // R
#define MPU6050_I2C_MST_STATUS 0x36 // R
#define MPU6050_INT_PIN_CFG 0x37 // R/W
#define MPU6050_INT_ENABLE 0x38 // R/W
#define MPU6050_INT_STATUS 0x3A // R
#define MPU6050_ACCEL_XOUT_H 0x3B // R
#define MPU6050_ACCEL_XOUT_L 0x3C // R
#define MPU6050_ACCEL_YOUT_H 0x3D // R
#define MPU6050_ACCEL_YOUT_L 0x3E // R
#define MPU6050_ACCEL_ZOUT_H 0x3F // R
#define MPU6050_ACCEL_ZOUT_L 0x40 // R
#define MPU6050_TEMP_OUT_H 0x41 // R
#define MPU6050_TEMP_OUT_L 0x42 // R
#define MPU6050_GYRO_XOUT_H 0x43 // R
#define MPU6050_GYRO_XOUT_L 0x44 // R
#define MPU6050_GYRO_YOUT_H 0x45 // R
#define MPU6050_GYRO_YOUT_L 0x46 // R
#define MPU6050_GYRO_ZOUT_H 0x47 // R
#define MPU6050_GYRO_ZOUT_L 0x48 // R
#define MPU6050_EXT_SENS_DATA_00 0x49 // R
#define MPU6050_EXT_SENS_DATA_01 0x4A // R
#define MPU6050_EXT_SENS_DATA_02 0x4B // R
#define MPU6050_EXT_SENS_DATA_03 0x4C // R
#define MPU6050_EXT_SENS_DATA_04 0x4D // R
#define MPU6050_EXT_SENS_DATA_05 0x4E // R
#define MPU6050_EXT_SENS_DATA_06 0x4F // R
#define MPU6050_EXT_SENS_DATA_07 0x50 // R
#define MPU6050_EXT_SENS_DATA_08 0x51 // R
#define MPU6050_EXT_SENS_DATA_09 0x52 // R
#define MPU6050_EXT_SENS_DATA_10 0x53 // R
#define MPU6050_EXT_SENS_DATA_11 0x54 // R
#define MPU6050_EXT_SENS_DATA_12 0x55 // R
#define MPU6050_EXT_SENS_DATA_13 0x56 // R
#define MPU6050_EXT_SENS_DATA_14 0x57 // R
#define MPU6050_EXT_SENS_DATA_15 0x58 // R
#define MPU6050_EXT_SENS_DATA_16 0x59 // R
#define MPU6050_EXT_SENS_DATA_17 0x5A // R
#define MPU6050_EXT_SENS_DATA_18 0x5B // R
#define MPU6050_EXT_SENS_DATA_19 0x5C // R
#define MPU6050_EXT_SENS_DATA_20 0x5D // R
#define MPU6050_EXT_SENS_DATA_21 0x5E // R
#define MPU6050_EXT_SENS_DATA_22 0x5F // R
#define MPU6050_EXT_SENS_DATA_23 0x60 // R
#define MPU6050_I2C_SLV0_DO 0x63 // R/W
#define MPU6050_I2C_SLV1_DO 0x64 // R/W
#define MPU6050_I2C_SLV2_DO 0x65 // R/W
#define MPU6050_I2C_SLV3_DO 0x66 // R/W
#define MPU6050_I2C_MST_DELAY_CTRL 0x67 // R/W
#define MPU6050_SIGNAL_PATH_RESET 0x68 // R/W
#define MPU6050_USER_CTRL 0x6A // R/W
#define MPU6050_PWR_MGMT_1 0x6B // R/W
#define MPU6050_PWR_MGMT_2 0x6C // R/W
#define MPU6050_FIFO_COUNTH 0x72 // R/W
#define MPU6050_FIFO_COUNTL 0x73 // R/W
#define MPU6050_FIFO_R_W 0x74 // R/W
#define MPU6050_WHO_AM_I 0x75 // R
//*******************************************************
//***********************************************************************
//initialize I2C module 0
//Slightly modified version of TI's example code
void InitI2C0(void){
//enable I2C module 0
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
//reset module
SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
//enable GPIO peripheral that contains I2C0
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
//Configure the pin muxing for I2C0 functions on port B2 and B3
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
//Select the I2C function for these pins
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
//Enable and initialize the I2C0 master module. Use the system clock for
//the I2C0 module. The last parameter sets the I2C data transfer rate.
//If false the data rate is set to 100kbps and if true the data rate will
//be set to 400kbps
I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
//Clear I2C FIFOs
HWREG(I2C0_BASE + I2C_O_FIFOCTL) = 80008000;
}
void I2CWrite(uint16_t device_address, uint16_t device_register, uint8_t device_data){
//specify that we want to communicate to device address with an intended write to bus
I2CMasterSlaveAddrSet(I2C0_BASE, device_address, false);
//register to be read
I2CMasterDataPut(I2C0_BASE, device_register);
//send control byte and register address byte to slave device
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C0_BASE));
I2CMasterSlaveAddrSet(I2C0_BASE, device_address, true);
//specify data to be written to the above mentioned device_register
I2CMasterDataPut(I2C0_BASE, device_data);
//wait while checking for MCU to complete the transaction
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
//wait for MCU & device to complete transaction
while(I2CMasterBusy(I2C0_BASE));
}
//This function receives (or reads) data on the I2C bus.
//The I2C_MASTER_CMD_BURST_RECEIVE_START/CONT/FINISH
//can be used to modify the function to read multiple registers on the slave device (if it supports doing so).
//read specified register on slave device
uint32_t I2CRead(uint32_t slave_addr, uint8_t reg){
//specify that we are writing (a register address) to the
//slave device
I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, false);
//specify register to be read
I2CMasterDataPut(I2C0_BASE, reg);
//send control byte and register address byte to slave device
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C0_BASE));
//specify that we are going to read from slave device
I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, true);
//send control byte and read from the register we
//specified
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C0_BASE));
//return data pulled from the specified register
return I2CMasterDataGet(I2C0_BASE);
}
void ConfiguraMPU(void){
I2CWrite(0x68 , MPU6050_PWR_MGMT_1, 0x00); //NO wakeup mode
I2CWrite(0x68 , MPU6050_GYRO_CONFIG, 0x80); //gyro-eje X
I2CWrite(0x68 , MPU6050_USER_CTRL, 0x40); //YES FIFOS
I2CWrite(0x68 , MPU6050_FIFO_EN, 0x41); // YES FIFOS
I2CWrite(0x68 , MPU6050_I2C_SLV0_ADDR, 0xE8);
I2CWrite(0x68 , MPU6050_I2C_SLV0_REG, MPU6050_GYRO_XOUT_H);
I2CWrite(0x68 , MPU6050_I2C_SLV0_CTRL, 0xA2);
}
//THIS FUNCTION IS FOR DELAYS
//***********************************************************************
/* Configuracion del temporizador del reloj del sistema */
void retardo_systick (uint32_t tiempo) {//TIEMPO EN SEGUNDOS!!!!
NVIC_ST_CTRL_R &= ~NVIC_ST_CTRL_ENABLE; // Deshabilita el Systick
NVIC_ST_RELOAD_R = (NVIC_ST_RELOAD_R & ~0xFFFFFF) | (16000000/tiempo - 1); //Cuenta programable
NVIC_ST_CURRENT_R = (NVIC_ST_CURRENT_R & ~0xFFFFFF); // Renicia la cuenta actual
NVIC_ST_CTRL_R |= NVIC_ST_CTRL_ENABLE + NVIC_ST_CTRL_CLK_SRC; // Habilitar el Systick y la señal de reloj
while ((NVIC_ST_CTRL_R & NVIC_ST_CTRL_COUNT) == 0); //RETRASO
} //fin retardo_systick
//THESE FUNCTION CONFIGURE UART0
void ConfiguraUART0(uint32_t velocidad){
uint16_t Divint;
uint8_t Divfrac;
SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOA;
SYSCTL_RCGC1_R |= SYSCTL_RCGC1_UART0;
while((SYSCTL_PRUART_R & SYSCTL_PRUART_R0) == 0);
GPIO_PORTA_AMSEL_R &= ~(0x03);
GPIO_PORTA_DEN_R |= 0x03;
GPIO_PORTA_AFSEL_R |= 0x03;
GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R&0xFFFFFF00)|0x00000011;
UART0_CTL_R &= ~UART_CTL_UARTEN; // Inhabilitamos el UART0
Divint = 1000000/velocidad;
Divfrac = round((1000000.00/velocidad - Divint) * 64);
//Fsysclk = 16MHz
UART0_IBRD_R = (UART0_IBRD_R & 0xFFFF0000) | Divint;
UART0_FBRD_R = (UART0_FBRD_R & 0xFFFFFFC0) | Divfrac;
// 8, N, 1
UART0_LCRH_R = (UART0_LCRH_R & 0xFFFFFF00) | 0x70; // 0 11 (1) * 0 0 0 (0)
UART0_CTL_R |= UART_CTL_UARTEN; // Habilitamos el UART0
}//fin configuraUART0
//*****************Funciones para la comunicacion*************************
void txcar(uint32_t car){
while ((UART0_FR_R & UART_FR_TXFF)!=0); //ESPERAMOS QUE ESTE LISTO
UART0_DR_R = car;
}//fin txcar
uint8_t rxcar(void){
uint8_t temp;
while ((UART0_FR_R & UART_FR_RXFE)!=0); //ESPERAMOS EL DATO
temp= UART0_DR_R&0xFF; //8 bits
return temp;
}//fin rxcar
void txmens(uint8_t mens[]){
uint8_t letra;
uint8_t i=0;
letra= mens[i++];
while (letra != '\0'){
txcar(letra);
letra= mens[i++];
}
}//fin txmens_uart0
//************************************************************************
//MAIN
void main(void){
uint32_t GyroTotal = 0;
uint32_t GyroL = 5, GyroH = 5;
ConfiguraUART0(9600);
InitI2C0();
ConfiguraMPU();
while(1){
GyroL = I2CRead(0x68 , MPU6050_EXT_SENS_DATA_00);
GyroH = I2CRead(0x68 , MPU6050_EXT_SENS_DATA_01);
GyroTotal = (GyroH << 8) + GyroL;
txcar(GyroTotal);
retardo_systick (2);
}//FIN WHILE(1)
}//FIN MAIN