整个框架是: 定时器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 addressEUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, SlaveAddr);//Set Master in receive modeEUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);//Enable I2C Module to start operationsEUSCI_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)
初入硬件,调了好几天了。。很惆怅,希望大家能够提供一点帮助蛤。
Shawn Hsiia:
这个是我工程文件,希望大家能给点指点。
灰小子:
mspware里有iic相关的例程,楼主可以参考下
Shawn Hsiia:
回复 灰小子:
您好,
我参考的确实是mspware里的程序,它里面提供的例程都是用中断的方式,而且也没有读写特定寄存器,特别的不实用。
这是driverlib里的库函数,都是这种没有读写特定寄存器的函数。
还请前辈指教。