整个框架是: 定时器1ms 中断一次,ISR里采集AD, 采集加速度计9轴(iic),并发送给串口。
AD和串口部分都是没有问题的,但是硬件iic的部分一直没有调通。
(备注: 如果按照iic 400kb/s 的情况算,1ms的时间里是可以完成这些动作的)
由于,库函数中没有直接读写slave中的特定寄存器的代码,我根据自己的需求写了如下i2c.c的代码:
#include "driverlib.h" uint8_t myI2CRxData[14]; void myI2C_Init(uint16_t SlaveAddr){ GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,GPIO_PIN6 + GPIO_PIN7,GPIO_TERNARY_MODULE_FUNCTION); EUSCI_B_I2C_initMasterParam param = {0}; param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK; param.i2cClk = 16384000 ; param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS; param.byteCounterThreshold = 1; param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, ¶m); //Specify slave address EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, SlaveAddr); //Set Master in receive mode EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE); //Enable I2C Module to start operations EUSCI_B_I2C_enable(EUSCI_B0_BASE); // EUSCI_B_I2C_disableInterrupt(EUSCI_B0_BASE, // EUSCI_B_I2C_RECEIVE_INTERRUPT0 + // EUSCI_B_I2C_BYTE_COUNTER_INTERRUPT // ); // // EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, // EUSCI_B_I2C_RECEIVE_INTERRUPT0 + // EUSCI_B_I2C_BYTE_COUNTER_INTERRUPT // ); } //1> EUSCI_B_I2C_masterSendMultiByteStart ----> start + data(slave address(W)) //2> EUSCI_B_I2C_masterSendMultiByteNext ----> data(REG address) //3> EUSCI_B_I2C_masterSendMultiByteFinish ----> data + stop void myI2C_WriteSingleByte(uint16_t baseAddress, uint8_t SlaveAddress,uint8_t RegAddress, uint8_t TxData){ SlaveAddress = SlaveAddress << 1; SlaveAddress += 1; // 最低位w操作1 , r操作0 EUSCI_B_I2C_masterSendMultiByteStart(baseAddress,SlaveAddress);//send start + data(slave address(W)) EUSCI_B_I2C_masterSendMultiByteNext(baseAddress,RegAddress);// send data(REG address) EUSCI_B_I2C_masterSendMultiByteFinish(baseAddress,TxData);//send data + stop } //1> EUSCI_B_I2C_masterSendMultiByteStart ----> start + data(slave address(W)) //2> EUSCI_B_I2C_masterSendMultiByteNext ----> data(REG address) //3> EUSCI_B_I2C_masterSendMultiByteStart ----> start + data(slave address(R)) //4> EUSCI_B_I2C_masterReceiveMultiByteNext ----> data(重复此函数,读取n-1个) //5> EUSCI_B_I2C_masterReceiveMultiByteFinish ----> data + stop void myI2C_ReadContinueBytes(uint16_t baseAddress, uint8_t SlaveAddress,uint8_t RegAddress, int REGnum){ SlaveAddress = SlaveAddress << 1; SlaveAddress |= 1; // 最低位w操作1 , r操作0 EUSCI_B_I2C_masterSendMultiByteStart(baseAddress,SlaveAddress);//send start + data(slave address(W)) EUSCI_B_I2C_masterSendMultiByteNext(baseAddress,RegAddress);// send data(REG address) SlaveAddress &= 0; // 最低位w操作1 , r操作0 EUSCI_B_I2C_masterSendMultiByteStart(baseAddress,SlaveAddress);//send start + data(slave address(R)) int i; for(i=0; i<REGnum-1;i++){ myI2CRxData[i] = EUSCI_B_I2C_masterReceiveMultiByteNext(baseAddress); //receive data(重复此函数,读取n-1个) } myI2CRxData[REGnum-1] = EUSCI_B_I2C_masterReceiveMultiByteFinish(baseAddress); //receive data + stop }
以及用到该函数的MPU9255部分的代码:
/* * myMPU9255.c * * Created on: 2017年7月17日 * Author: ShawnX */ #include "driverlib.h" #include "myI2C.h" #include "myMPU9255.h" extern uint8_t myI2CRxData[14]; void myMPU9255_Init(void){ myI2C_Init(SLAVE_ADDRESS); myI2C_WriteSingleByte(EUSCI_B0_BASE, SLAVE_ADDRESS, PWR_MGMT_1,0x00); //resume from sleep. myI2C_WriteSingleByte(EUSCI_B0_BASE, SLAVE_ADDRESS, SMPLRT_DIV, 0x07); myI2C_WriteSingleByte(EUSCI_B0_BASE, SLAVE_ADDRESS, CONFIG, 0x06); myI2C_WriteSingleByte(EUSCI_B0_BASE, SLAVE_ADDRESS, GYRO_CONFIG, 0x18); myI2C_WriteSingleByte(EUSCI_B0_BASE, SLAVE_ADDRESS, ACCEL_CONFIG, 0x01); } void myAccelGyro_Read(void){ myI2C_ReadContinueBytes(EUSCI_B0_BASE, SLAVE_ADDRESS, 0x3B,14); }
但是程序运行后,一直卡在库函数中这句话上
//Poll for transmit interrupt flag. while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) { ; }
总结一下我的问题:
1. 程序出错在什么地方呢?
2. 是否能够提供可以直接读写slave特定寄存器的库函数呢?或者相关硬件iic的参考函数呢?(ps,由于使用了定时器中断,所以为了避免中断嵌套,最好是不用中断方式的iic)
初入硬件,调了好几天了。。很惆怅,希望大家能够提供一点帮助蛤。