玩智能车的可以参考
#include
#include"mpu6050.h"
#include "USCI_A0.h"
#include "IMU.h "
/*
* ======== BCSplus_graceInit ========
* Initialize MSP430 Basic Clock System
*/
void BCSplus_graceInit(void)
{
/* USER CODE START (section: BCSplus_graceInit_prologue) */
/* User initialization code */
/* USER CODE END (section: BCSplus_graceInit_prologue) */
/*
* Basic Clock System Control 2
*
* SELM_0 -- DCOCLK
* DIVM_0 -- Divide by 1
* ~SELS -- DCOCLK
* DIVS_1 -- Divide by 2
* ~DCOR -- DCO uses internal resistor
*
* Note: ~ indicates that has value zero
*/
BCSCTL2 = SELM_0 | DIVM_0 | DIVS_1;
if (CALBC1_16MHZ != 0xFF) {
/* Adjust this accordingly to your VCC rise time */
__delay_cycles(100000);
/* Follow recommended flow. First, clear all DCOx and MODx bits. Then
* apply new RSELx values. Finally, apply new DCOx and MODx bit values.
*/
DCOCTL = 0x00;
BCSCTL1 = CALBC1_16MHZ; /* Set DCO to 16MHz */
DCOCTL = CALDCO_16MHZ;
}
/*
* Basic Clock System Control 1
*
* XT2OFF -- Disable XT2CLK
* ~XTS -- Low Frequency
* DIVA_0 -- Divide by 1
*
* Note: ~XTS indicates that XTS has value zero
*/
BCSCTL1 |= XT2OFF | DIVA_0;
/*
* Basic Clock System Control 3
*
* XT2S_0 -- 0.4 - 1 MHz
* LFXT1S_0 -- If XTS = 0, XT1 = 32768kHz Crystal ; If XTS = 1, XT1 = 0.4 - 1-MHz crystal or resonator
* XCAP_1 -- ~6 pF
*/
BCSCTL3 = XT2S_0 | LFXT1S_0 | XCAP_1;
/* USER CODE START (section: BCSplus_graceInit_epilogue) */
/* User code */
/* USER CODE END (section: BCSplus_graceInit_epilogue) */
}/*
* main.c
*/
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
BCSplus_graceInit(); //MCLK = 16M,SMCLK = 8M,ack =32.768k
WDTCTL = WDTPW | WDTTMSEL | WDTIS0;
IE1 |= WDTIE;
USCI_A0_init(); //uart 38400bps
P1DIR |= BIT0; //initialize led control PIN
_EINT();
MPU6050_Init(); //initialize mpu6050
while(1)
{
/*
Get_Attitude();
//MPU6050_Dataanl();
// ReadMPU6050All();
//Prepare_Data(); //耗时6.15ms
//Uart1_Send_AF(); //耗时8.42ms
P1OUT ^= BIT0;
Get_Attitude();
//ReadMPU6050All();
//MPU6050_Dataanl(); //未使用多字节读取,耗时6ms,使用多字节读取,耗时3.6ms
//Prepare_Data();
// Uart1_Send_AF();
P1OUT ^= BIT0;
*/
}
}
//watchdog interrupt server program per 1ms
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR_HOOK(void)
{
/* USER CODE START (section: WDT_ISR_HOOK) */
/* replace this comment with your code */
static unsigned int count=0;
static unsigned char ms2 = 0,ms5 = 0,ms10 = 0;
count++;
ms2++;
ms5++;
ms10++;
if(ms2 == 2)
{
ms2 = 0;
Prepare_Data();
//MPU6050_Dataanl();
}
if(ms5 >= 4)
{
ms5 = 0;
Get_Attitude();
}
if(ms10 >= 10)
{
ms10 = 0;
Uart1_Send_AF();
}
if(count== 200)
{
count=0;
P1OUT ^= BIT0;
}
/* USER CODE END (section: WDT_ISR_HOOK) */
}
/*
* This file contains some mpu6050 operation.
* By IC爬虫 ([email protected])
* 2014-4-13 v1.0
*/
#include "mpu6050.h"
unsigned char mpu6050_buffer[14]; //I2C读取后存放数据
int ACC_OFFSET_X,ACC_OFFSET_Y,ACC_OFFSET_Z;
int GYRO_OFFSET_X,GYRO_OFFSET_Y,GYRO_OFFSET_Z;
unsigned char GYRO_OFFSET_OK = 1;
unsigned char ACC_OFFSET_OK = 1;
int MPU6050_ACC_LAST_X,MPU6050_ACC_LAST_Y,MPU6050_ACC_LAST_Z; //final accelerate speed
int MPU6050_GYRO_LAST_X,MPU6050_GYRO_LAST_Y,MPU6050_GYRO_LAST_Z; //final gyro speed
/**********************************************************/
//函数名称:void MPU6050_Dataanl
//入口参数:无
//出口参数:无
//函数功能:MPU6050数据读取并处理
/**********************************************************/
void MPU6050_Dataanl(void)
{
#ifndef READALL
MPU6050_ACC_LAST_X = GetAccelX() - ACC_OFFSET_X;
MPU6050_ACC_LAST_Y = GetAccelY() - ACC_OFFSET_Y;
MPU6050_ACC_LAST_Z = GetAccelZ() - ACC_OFFSET_Z;
MPU6050_GYRO_LAST_X = GetAnguX() - GYRO_OFFSET_X;
MPU6050_GYRO_LAST_Y = GetAnguY() - GYRO_OFFSET_Y;
MPU6050_GYRO_LAST_Z = GetAnguZ() - GYRO_OFFSET_Z;
//------------------------------------------------------------------//
//补偿偏移
if(!GYRO_OFFSET_OK)
{
static long int tempgx=0,tempgy=0,tempgz=0;
static unsigned char cnt_g=0;
if(cnt_g==0)
{
GYRO_OFFSET_X=0;
GYRO_OFFSET_Y=0;
GYRO_OFFSET_Z=0;
tempgx = 0;
tempgy = 0;
tempgz = 0;
cnt_g = 1;
}
tempgx+= MPU6050_GYRO_LAST_X;
tempgy+= MPU6050_GYRO_LAST_Y;
tempgz+= MPU6050_GYRO_LAST_Z;
if(cnt_g==200)
{
GYRO_OFFSET_X=tempgx/cnt_g;
GYRO_OFFSET_Y=tempgy/cnt_g;
GYRO_OFFSET_Z=tempgz/cnt_g;
cnt_g = 0;
GYRO_OFFSET_OK = 1;
}
cnt_g++;
}
if(!ACC_OFFSET_OK)
{
static long int tempax=0,tempay=0,tempaz=0;
static unsigned char cnt_a=0;
if(cnt_a==0)
{
ACC_OFFSET_X = 0;
ACC_OFFSET_Y = 0;
ACC_OFFSET_Z = 0;
tempax = 0;
tempay = 0;
tempaz = 0;
cnt_a = 1;
}
tempax += MPU6050_ACC_LAST_X;//累加
tempay += MPU6050_ACC_LAST_Y;
tempaz += MPU6050_ACC_LAST_Z;
if(cnt_a==200)
{
ACC_OFFSET_X = tempax/cnt_a;
ACC_OFFSET_Y = tempay/cnt_a;
ACC_OFFSET_Z = tempaz/cnt_a;
cnt_a = 0;
ACC_OFFSET_OK = 1;
}
cnt_a++;
}
//--------------------------------------------//
#else
struct MPU6050Struct *MPU6050WORK;
MPU6050WORK = ReadMPU6050All();
MPU6050_ACC_LAST_X = (MPU6050WORK ->MPU6050_ACC_X) - ACC_OFFSET_X;
MPU6050_ACC_LAST_Y = (MPU6050WORK ->MPU6050_ACC_Y) - ACC_OFFSET_Y;
MPU6050_ACC_LAST_Z = (MPU6050WORK ->MPU6050_ACC_Z) - ACC_OFFSET_Z;
MPU6050_GYRO_LAST_X = (MPU6050WORK ->MPU6050_GYRO_X) - GYRO_OFFSET_X;
MPU6050_GYRO_LAST_Y = (MPU6050WORK ->MPU6050_GYRO_Y) - GYRO_OFFSET_Y;
MPU6050_GYRO_LAST_Z = (MPU6050WORK ->MPU6050_GYRO_Z) - GYRO_OFFSET_Z;
if(!GYRO_OFFSET_OK)
{
static long int tempgx=0,tempgy=0,tempgz=0;
static unsigned char cnt_g=0;
if(cnt_g==0)
{
GYRO_OFFSET_X=0;
GYRO_OFFSET_Y=0;
GYRO_OFFSET_Z=0;
tempgx = 0;
tempgy = 0;
tempgz = 0;
cnt_g = 1;
}
tempgx+= MPU6050_GYRO_LAST_X;
tempgy+= MPU6050_GYRO_LAST_Y;
tempgz+= MPU6050_GYRO_LAST_Z;
if(cnt_g==200)
{
GYRO_OFFSET_X=tempgx/cnt_g;
GYRO_OFFSET_Y=tempgy/cnt_g;
GYRO_OFFSET_Z=tempgz/cnt_g;
cnt_g = 0;
GYRO_OFFSET_OK = 1;
}
cnt_g++;
}
if(!ACC_OFFSET_OK)
{
static long int tempax=0,tempay=0,tempaz=0;
static unsigned char cnt_a=0;
if(cnt_a==0)
{
ACC_OFFSET_X = 0;
ACC_OFFSET_Y = 0;
ACC_OFFSET_Z = 0;
tempax = 0;
tempay = 0;
tempaz = 0;
cnt_a = 1;
}
tempax += MPU6050_ACC_LAST_X;//累加
tempay += MPU6050_ACC_LAST_Y;
tempaz += MPU6050_ACC_LAST_Z;
if(cnt_a==200)
{
ACC_OFFSET_X = tempax/cnt_a;
ACC_OFFSET_Y = tempay/cnt_a;
ACC_OFFSET_Z = tempaz/cnt_a;
cnt_a = 0;
ACC_OFFSET_OK = 1;
}
cnt_a++;
}
#endif
}
/**********************************************************/
//函数名称:void MPU6050Init
//入口参数:无
//出口参数:无
//函数功能:MPU6050初始化
/**********************************************************/
void MPU6050_Init()
{
#ifdef IMITATEIIC
InitImitateIICPort();
#else
I2C_Init(SlaveAddr);
#endif
I2C_Write(PWR_MGMT_1,0x00); //resume from sleep.
I2C_Write(SMPLRT_DIV, 0x07);
I2C_Write(CONFIG, 0x06);
I2C_Write(GYRO_CONFIG, 0x18);
I2C_Write(ACCEL_CONFIG, 0x01);
}
/**********************************************************/
//函数名称:int Get16Bit
//入口参数:address:读取数据的地址
//出口参数:无
//函数功能:获取MPU6050相应地址上的数据
/**********************************************************/
int Get16Bit (unsigned char address)
{
#ifndef MULTIREAD
unsigned char ho,lo;
int temp ;
ho = I2C_Read(address);
lo = I2C_Read(address+1);
temp=ho;
temp<<=8;
temp+=lo;
return temp ;
#else
return( Double_Read_ADXL345(address));
#endif
}
/**********************************************************/
//函数名称:
//入口参数:无
//出口参数:无
//函数功能:获取MPU6050相应轴上的加速度数据
/**********************************************************/
// X/Y/Z-Axis Acceleration
int GetAccelX ()
{
return Get16Bit(ACCEL_XOUT_H);
}
int GetAccelY ()
{
return Get16Bit(ACCEL_YOUT_H);
}
int GetAccelZ ()
{
return Get16Bit(ACCEL_ZOUT_H);
}
/**********************************************************/
//函数名称:
//入口参数:无
//出口参数:无
//函数功能:获取MPU6050相应轴上的角速度数据
/**********************************************************/
// X/Y/Z-Axis Angular velocity
int GetAnguX ()
{
return Get16Bit(GYRO_XOUT_H);
}
int GetAnguY ()
{
return Get16Bit(GYRO_YOUT_H);
}
int GetAnguZ ()
{
return Get16Bit(GYRO_ZOUT_H);
}
#include"msp430iic.h"
struct MPU6050Struct MPU6050Data;
void InitImitateIICPort(void)
{
SET_SDA_OUT; //set SDA PIN is out mode
SDA_HIGH; // set SDA PIN out is high
SCL_HIGH; //set SCL PIN is input mode ,pull up register to SCL PIN high
}
/**************************************
起始信号
**************************************/
void ADXL345_Start(void)
{
SET_SDA_OUT;
SDA_HIGH; //拉高数据线
SCL_HIGH; //拉高时钟线
Delay5us(); //延时
SDA_LOW; //产生下降沿
Delay5us(); //延时
SCL_LOW; //拉低时钟线
}
/**************************************
停止信号
**************************************/
void ADXL345_Stop(void)
{
SET_SDA_OUT;
SDA_LOW; //拉低数据线
SCL_HIGH; //拉高时钟线
Delay5us(); //延时
SDA_HIGH; //产生上升沿
Delay5us(); //延时
}
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void ADXL345_SendACK(unsigned char ack)
{
SET_SDA_OUT;
if(ack)
SDA_HIGH; //写NACK应答信号
else
SDA_LOW; //写ACK应答信号
SCL_HIGH; //拉高时钟线
Delay5us(); //延时
SCL_LOW; //拉低时钟线
Delay5us(); //延时
}
/**************************************
接收应答信号
**************************************/
unsigned char ADXL345_RecvACK(void)
{
unsigned char ack;
//------------------//
//一下两句切不可调换顺序,否则会导致时序错误
SET_SDA_IN;
SCL_HIGH; //拉高时钟线
//-----------------//
Delay5us(); //延时
ack = SDA_IN; //读应答信号
SCL_LOW; //拉低时钟线
Delay5us(); //延时
return ack;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void ADXL345_Senduchar(unsigned char dat)
{
unsigned char i,m;
SET_SDA_OUT;
for (i=8; i!=0; i--) //8位计数器
{
m=dat & 0x80; //移出数据的最高位
if(m == 0x80)
SDA_HIGH;
else
SDA_LOW;
SCL_HIGH; //拉高时钟线
Delay5us(); //延时
SCL_LOW; //拉低时钟线
dat=dat<<1;
Delay5us(); //延时
}
ADXL345_RecvACK();
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
unsigned char ADXL345_Recvuchar(void)
{
unsigned char i;
unsigned char dat = 0;
unsigned char m;
SDA_HIGH; //使能内部上拉,准备读取数据,
SET_SDA_IN;
for (i=8; i!=0; i--) //8位计数器
{
dat <<= 1;
SCL_HIGH; //拉高时钟线
SET_SDA_IN;
m = SDA_IN;
if(m == I2C_SDA)
dat = dat|0x01;
Delay5us(); //延时
SCL_LOW; //拉低时钟线
Delay5us(); //延时
}
return dat;
}
//******单字节写入*******************************************
void Single_Write_ADXL345(unsigned char REG_Address,unsigned char REG_data)
{
ADXL345_Start(); //起始信号
ADXL345_Senduchar(SlaveAddress); //发送设备地址+写信号
ADXL345_Senduchar(REG_Address); //内部寄存器地址,请参考中文pdf22页
ADXL345_Senduchar(REG_data); //内部寄存器数据,请参考中文pdf22页
ADXL345_Stop(); //发送停止信号
}
//********单字节读取*****************************************
unsigned char Single_Read_ADXL345(unsigned char REG_Address)
{ unsigned char REG_data=0;
ADXL345_Start(); //起始信号
ADXL345_Senduchar(SlaveAddress); //发送设备地址+写信号
ADXL345_Senduchar(REG_Address); //发送存储单元地址,从0开始
ADXL345_Start(); //起始信号
ADXL345_Senduchar(SlaveAddress+1); //发送设备地址+读信号
REG_data=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(1); //NACK
ADXL345_Stop(); //停止信号
return REG_data;
}
//********多字节读取*****************************************
int Double_Read_ADXL345(unsigned char REG_Address)
{
unsigned char ValueL=0;
int Value=0;
ADXL345_Start(); //起始信号
ADXL345_Senduchar(SlaveAddress); //发送设备地址+写信号
ADXL345_Senduchar(REG_Address); //发送存储单元地址,从0开始
ADXL345_Start(); //起始信号
ADXL345_Senduchar(SlaveAddress+1); //发送设备地址+读信号
Value=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
ValueL=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(1); //NACK
ADXL345_Stop(); //停止信号
Value=(Value<<8)+ValueL;
return Value;
}
struct MPU6050Struct *ReadMPU6050All()
{
unsigned char TempAcc1=0,TempAcc2=0,TempAcc3=0,TempAcc4=0,TempAcc5=0,TempAcc6=0;
unsigned char TempGyro1=0,TempGyro2=0,TempGyro3=0,TempGyro4=0,TempGyro5=0,TempGyro6=0;
ADXL345_Start(); //起始信号
ADXL345_Senduchar(SlaveAddress); //发送设备地址+写信号
ADXL345_Senduchar(0x3B); //发送存储单元地址,从0x3b开始
ADXL345_Start(); //起始信号
ADXL345_Senduchar(SlaveAddress+1); //发送设备地址+读信号
TempAcc2=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
TempAcc1=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
TempAcc4=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
TempAcc3=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
TempAcc6=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
TempAcc5=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
ADXL345_Recvuchar(); //丢弃不连续地址的数据
ADXL345_SendACK(0); //ACK
ADXL345_Recvuchar(); //丢弃不连续地址的数据
ADXL345_SendACK(0);
TempGyro2=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
TempGyro1=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0);
TempGyro4=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
TempGyro3=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0);
TempGyro6=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(0); //ACK
TempGyro5=ADXL345_Recvuchar(); //读出寄存器数据
ADXL345_SendACK(1); //NACK
ADXL345_Stop();
MPU6050Data.MPU6050_ACC_X=(TempAcc2<<8) + TempAcc1;
MPU6050Data.MPU6050_ACC_Y=(TempAcc4<<8) + TempAcc3;
MPU6050Data.MPU6050_ACC_Z=(TempAcc6<<8) + TempAcc5;
MPU6050Data.MPU6050_GYRO_X=(TempGyro2<<8) + TempGyro1;
MPU6050Data.MPU6050_GYRO_Y=(TempGyro4<<8) + TempGyro3;
MPU6050Data.MPU6050_GYRO_Z=(TempGyro6<<8) + TempGyro5;
return (&MPU6050Data);
}
/*
* This file contains some uSCI_A0 operation.
* By IC爬虫 ([email protected])
* 2014-4-28 v1.0
*/
//#include "msp430g2553.h"
#include "USCI_A0.h"
//#include "stdio.h"
#include "mpu6050.h"
#include "IMU.h"
#define uchar unsigned char
#define uint unsigned int
//将“int”类型的数据分成两个单字节的数据
#define BYTE0(dwTemp) (*(char *)(&dwTemp))
#define BYTE1(dwTemp) (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp) (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp) (*((char *)(&dwTemp) + 3))
/*********************************************************
*名称:USCI_A0_init
*功能:串口初始化
*入口参数:无
*出口参数:无
*说明:设置为P1.1和P1.2为串口通信端口
**********************************************************/
void USCI_A0_init(void)
{
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2;
UCA0CTL1 |= UCSSEL_2; // SMCLK
/*
UCA0BR0 = 0x45; // 8MHz 115200
UCA0BR1 = 0; // 8MHz 115200
UCA0MCTL = 0x4a; // 8MHz 115200 */
/*
UCA0BR0 = 0x68;
UCA0BR1 = 0;
UCA0MCTL = 0x40;
*/
UCA0MCTL = UCBRF_0 | UCBRS_4;
/* Baud rate control register 0 */
UCA0BR0 = 69;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
//IE2 |= UCA0RXIE + UCA0TXIE; // Enable USCI_A0 TX/RX interrupt
//IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
//__bis_SR_register(GIE); // Enter LPM3 w/ interrupts enabled
}
/*********************************************************
*名称:UartTX_Send_String
*功能:串口发送字符串函数
*入口参数:*data:数据指针 len :数据长度
*出口参数:无
*说明:
**********************************************************/
void UartTX_Send_String(unsigned char *Data,int len)
{
int j;
for(j=0;jSCL ,P1.7->SDA
/**********************************************************/
void I2C_Init (unsigned char SlaveAddr)
{
P1SEL |= BIT6+BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6+BIT7; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST+UCMODE_3+UCSYNC; // I2C Master, synchronous mode
UCB0CTL0 &= ~(UCSLA10+UCA10); //7 bit add of slave and master
UCB0CTL1 = UCSSEL_2+UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 80; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2COA = 0x01A5; //set own address
UCB0I2CSA = SlaveAddr; // Set slave address
IE2 &= ~(UCB0RXIE+UCB0TXIE); // disenable TX&RX interrupt
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
}
/**********************************************************/
//函数名称:void I2C_WriteInit
//入口参数:无
//出口参数:无
//函数功能:I2C写数据初始化,发送模式,接收中断关闭,发送中断关闭
/**********************************************************/
void I2C_WriteInit()
{
UCB0CTL1 |= UCTR; // UCTR=1 => Transmit Mode (R/W bit = 0)
IFG2 &= ~UCB0TXIFG; //clean TX interrupt sign
IE2 &= ~UCB0RXIE; // disable Receive ready interrupt
IE2 &= ~UCB0TXIE; // disable Transmit ready interrupt
}
/**********************************************************/
//函数名称:void I2C_ReadInit
//入口参数:无
//出口参数:无
//函数功能:I2C读数据初始化,接收模式,接收中断关闭,发送中断关闭
/**********************************************************/
void I2C_ReadInit()
{
UCB0CTL1 &= ~UCTR; // UCTR=0 => Receive Mode (R/W bit = 1)
IFG2 &= ~UCB0RXIFG;
IE2 &= ~UCB0TXIE; // disable Transmit ready interrupt
IE2 &= ~UCB0RXIE; // disable Receive ready interrupt
}
/**********************************************************/
//函数名称:I2C_Write
//入口参数:address:需要写入数据的设备的地址
// data:发送的数据
//出口参数:无
//函数功能:I2C发送数据
/**********************************************************/
void I2C_Write(uchar address,uchar data)
{
I2C_WriteInit();
UCB0CTL1 |= UCTXSTT; //generate start condition
//while(UCB0CTL1 & UCTXSTT); //generate start condition ,and transmit slave address and write bit
while(!(IFG2 & UCB0TXIFG)); //wait start condition and equipment address transmitted
IFG2 &= ~UCB0TXIFG; //clean UCB0TXIFG
while(UCB0CTL1 & UCTXSTT); //wait slave acknowledge
UCB0TXBUF=address; //send address code
while(!(IFG2 & UCB0TXIFG )); //wait sending over
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
UCB0TXBUF=data; //send data
while(!(IFG2 & UCB0TXIFG )); //wait sending over
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
UCB0CTL1 |= UCTXSTP; // I2C stop condition
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
}
/**********************************************************/
//函数名称:uchar I2C_Read
//入口参数:address:需要读数据的设备的地址
//出口参数:无
//函数功能:I2C接收数据
/**********************************************************/
uchar I2C_Read(uchar address)
{
unsigned char data;
while (UCB0STAT & UCBUSY); // wait until I2C module has finished all operations
I2C_WriteInit();
UCB0CTL1 |= UCTXSTT; // start condition generation
while(UCB0CTL1 & UCTXSTT);
UCB0TXBUF=address; //send address code
while(!(IFG2 & UCB0TXIFG )); //wait sending over
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
// __disable_interrupt();
I2C_ReadInit();
while(UCB0RXIFG & IFG2);
IFG2 &= ~UCB0RXIFG;
data = UCB0RXBUF;
UCB0CTL1 |= UCTXSTP; // I2C stop condition
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
return data;
}
/*----------------------------------------------------------------------------*/
// Description:
// Acknowledge Polling. The EEPROM will not acknowledge if a write cycle is
// in progress. It can be used to determine when a write cycle is completed.
/*----------------------------------------------------------------------------*/
void I2C_AckPolling(void)
{
while (UCB0STAT & UCBUSY)
{
;// wait until I2C module has
} // finished all operations
do
{
UCB0STAT = 0x00; // clear I2C interrupt flags
UCB0CTL1 |= UCTR; // I2CTRX=1 => Transmit Mode (R/W bit = 0)
UCB0CTL1 &= ~UCTXSTT;
UCB0CTL1 |= UCTXSTT; // start condition is generated
while (UCB0CTL1 & UCTXSTT) // wait till I2CSTT bit was cleared
{
if (!(UCNACKIFG & UCB0STAT))
{
break;// Break out if ACK received
}
}
UCB0CTL1 |= UCTXSTP; // stop condition is generated after
// slave address was sent => I2C communication is started
while (UCB0CTL1 & UCTXSTP)
{
;// wait till stop bit is reset
}
__delay_cycles(500); // Software delay
} while (UCNACKIFG & UCB0STAT);
}
// USCI_B0 Data ISR
// Notice : UCSIAB0RX_ISR should be handle with UCSIAB0TX_ISR
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (UCB0TXIFG & IFG2) // TX
{
UCB0TXBUF = I2CSendBuffer[I2CSendPtr]; // Load TX buffer
I2CSendPtr--; // Decrement TX byte counter
if (I2CSendPtr < 0)
{
while (!(IFG2 & UCB0TXIFG)); // wait for tx complete
IE2 &= ~UCB0TXIE; // disable interrupts.
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(LPM0_bits);// Exit LPM0
}
}
else if (UCB0RXIFG & IFG2) // RX
{
I2CRecvBuffer = UCB0RXBUF; // store received data in buffer
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
}
}