430 G2553 LAUNCHPAD 简单I2C通信,用TI官方的 using IIC MASTER(slaa382) 代码,改从器件地址后总是悬在while (UCB0CTL1 & UCTXSTP)语句过不去。
详细是这样的:
用430 G2553 LAUNCHPAD作简单I2C通信和BQ27441电源板通信。认真读了几百页的SLAU44J(2553用户手册)。认真读了飞利浦I2C协议原版(为理清基本概念)。用http://www.ti.com/general/docs/litabsmultiplefilelist.tsp?&literatureNumber=slaa382 中的标准官方代码,仅仅改动了头文件包含 为 2553,
I2C从器件地址55(7位地址,未加读写控制位) ,引脚从P3改P1,避开加LED的p1.6,用1.4和1.7管脚当 SLC 和 sda。
/*** USCI master library ************************************************************
In this file the usage of the USCI I2C master library without DMA support is
shown. This library uses pointers to specify what data is to be sent.
When calling the TI_USCI_I2C_receive or TI_USCI_I2C_transmit routines
the number of bytes, which are to be transmitted or received have to be passed as
well as a pointer to a data field, that contains(or stores) the data.
This code checks if there is a slave with address 0x50 is connected to the I2C
bus and if the slave device is present, bytes are received and transmitted.
Uli Kretzschmar
MSP430 Systems
Freising
*******************************************************************************/
#include <msp430G2553.h>
#include "TI_USCI_I2C_master.h"
unsigned char timercounter;
unsigned char array[40] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb };
unsigned char store[40] = { 13, 13, 13, 13, 13, 13, 13, 0, 0, 0};
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
_EINT();
TI_USCI_I2C_transmitinit(0x55,0x40); // init transmitting with USCI
while ( TI_USCI_I2C_notready() ); // wait for bus to be free
if ( TI_USCI_I2C_slave_present(0x55) ) // slave address may differ from initialization
{
TI_USCI_I2C_receiveinit(0x55,0x40); // init receiving with USCI
while ( TI_USCI_I2C_notready() ); // wait for bus to be free
TI_USCI_I2C_receive(1,store);
while ( TI_USCI_I2C_notready() ); // wait for bus to be free
TI_USCI_I2C_transmitinit(0x55,0x40); // init transmitting with
while ( TI_USCI_I2C_notready() ); // wait for bus to be free
TI_USCI_I2C_transmit(4,array); // start transmitting
}
LPM3;
}
下面是TI_USCI_I2C_master.h头文件
#ifndef USCI_LIB
#define USCI_LIB
#define SDA_PIN BIT7 // msp430x261x UCB0SDA pin
#define SCL_PIN BIT4 // msp430x261x UCB0SCL pin
void TI_USCI_I2C_receiveinit(unsigned char slave_address, unsigned char prescale);
void TI_USCI_I2C_transmitinit(unsigned char slave_address, unsigned char prescale);
void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field);
void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field);
unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address);
unsigned char TI_USCI_I2C_notready();
#endif
下面是 :TI_USCI_I2C_master.c
//******************************************************************************
// MSP430 USCI I2C Transmitter and Receiver
//
// Description: This code configures the MSP430's USCI module as
// I2C master capable of transmitting and receiving bytes.
//
// ***THIS IS THE MASTER CODE***
//
// Master
// MSP430F2619
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | |
// | |
// | SDA/P1.1|------->
// | SCL/P1.2|------->
//
// Note: External pull-ups are needed for SDA & SCL
//
// Uli Kretzschmar
// Texas Instruments Deutschland GmbH
// November 2007
// Built with IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include <msp430G2553.h> // device specific header
//#include "msp430x22x4.h"
//#include "msp430x23x0.h"
//#include "msp430xG46x.h"
// ... // more devices are possible
#include "TI_USCI_I2C_master.h"
signed char byteCtr;
unsigned char *TI_receive_field;
unsigned char *TI_transmit_field;
//------------------------------------------------------------------------------
// void TI_USCI_I2C_receiveinit(unsigned char slave_address,
// unsigned char prescale)
//
// This function initializes the USCI module for master-receive operation.
//
// IN: unsigned char slave_address => Slave Address
// unsigned char prescale => SCL clock adjustment
//-----------------------------------------------------------------------------
void TI_USCI_I2C_receiveinit(unsigned char slave_address,
unsigned char prescale){
P1SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0
UCB0CTL1 = UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = prescale; // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = slave_address; // set slave address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0I2CIE = UCNACKIE;
IE2 = UCB0RXIE; // Enable RX interrupt
}
//------------------------------------------------------------------------------
// void TI_USCI_I2C_transmitinit(unsigned char slave_address,
// unsigned char prescale)
//
// This function initializes the USCI module for master-transmit operation.
//
// IN: unsigned char slave_address => Slave Address
// unsigned char prescale => SCL clock adjustment
//------------------------------------------------------------------------------
void TI_USCI_I2C_transmitinit(unsigned char slave_address,
unsigned char prescale){
P1SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0
UCB0CTL1 = UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = prescale; // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = slave_address; // Set slave address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0I2CIE = UCNACKIE;
IE2 = UCB0TXIE; // Enable TX ready interrupt
}
//------------------------------------------------------------------------------
// void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field)
//
// This function is used to start an I2C commuincation in master-receiver mode.
//
// IN: unsigned char byteCount => number of bytes that should be read
// unsigned char *field => array variable used to store received data
//------------------------------------------------------------------------------
void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field){
TI_receive_field = field;
if ( byteCount == 1 ){
byteCtr = 0 ;
__disable_interrupt();
UCB0CTL1 |= UCTXSTT; // I2C start condition
while (UCB0CTL1 & UCTXSTT); // Start condition sent?
UCB0CTL1 |= UCTXSTP; // I2C stop condition
__enable_interrupt();
} else if ( byteCount > 1 ) {
byteCtr = byteCount - 2 ;
UCB0CTL1 |= UCTXSTT; // I2C start condition
} else
while (1); // illegal parameter
}
//------------------------------------------------------------------------------
// void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field)
//
// This function is used to start an I2C commuincation in master-transmit mode.
//
// IN: unsigned char byteCount => number of bytes that should be transmitted
// unsigned char *field => array variable. Its content will be sent.
//------------------------------------------------------------------------------
void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field){
TI_transmit_field = field;
byteCtr = byteCount;
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
}
//------------------------------------------------------------------------------
// unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address)
//
// This function is used to look for a slave address on the I2C bus.
//
// IN: unsigned char slave_address => Slave Address
// OUT: unsigned char => 0: address was not found,
// 1: address found
//------------------------------------------------------------------------------
unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address)
{
unsigned char ie2_bak, slaveadr_bak, ucb0i2cie, returnValue;
ucb0i2cie = UCB0I2CIE; // store old UCB0I2CIE
ie2_bak = IE2; // store IE2 register
slaveadr_bak = UCB0I2CSA; // store old slave address
UCB0I2CIE &= ~ UCNACKIE; // no NACK interrupt
UCB0I2CSA = slave_address; // set slave address
IE2 &= ~(UCB0TXIE + UCB0RXIE); // no RX or TX interrupts
__disable_interrupt();
UCB0CTL1 |= UCTR + UCTXSTT +UCTXSTP; // I2C TX, start condition
while (UCB0CTL1 & UCTXSTP); // wait for STOP condition
returnValue = !(UCB0STAT & UCNACKIFG);
__enable_interrupt();
IE2 = ie2_bak; // restore IE2
UCB0I2CSA = slaveadr_bak; // restore old slave address
UCB0I2CIE = ucb0i2cie; // restore old UCB0CTL1
return returnValue; // return whether or not
// a NACK occured
}
//------------------------------------------------------------------------------
// unsigned char TI_USCI_I2C_notready()
//
// This function is used to check if there is commuincation in progress.
//
// OUT: unsigned char => 0: I2C bus is idle,
// 1: communication is in progress
//------------------------------------------------------------------------------
unsigned char TI_USCI_I2C_notready(){
return (UCB0STAT & UCBBUSY);
}
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
if (UCB0STAT & UCNACKIFG){ // send STOP if slave sends NACK
UCB0CTL1 |= UCTXSTP;
UCB0STAT &= ~UCNACKIFG;
}
}
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (IFG2 & UCB0RXIFG){
if ( byteCtr == 0 ){
UCB0CTL1 |= UCTXSTP; // I2C stop condition
*TI_receive_field = UCB0RXBUF;
TI_receive_field++;
}
else {
*TI_receive_field = UCB0RXBUF;
TI_receive_field++;
byteCtr--;
}
}
else {
if (byteCtr == 0){
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
}
else {
UCB0TXBUF = *TI_transmit_field;
TI_transmit_field++;
byteCtr--;
}
}
}
总是走到TI_USCI_I2C_master.c的unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address)函数中
while (UCB0CTL1 & UCTXSTP); 语句死循环,查看watch是UCB0CTL1寄存器的UCTXSTP不清零,就是stop信号没发出去。
量 SCL SDA无电压,后加语句
P1REN|=0xFF;(目的是将P1口所有加上上下拉电阻)
P1DIR|=BIT4;(这句加上或者不加应该影响不大,目的是将时钟设为输出)
后,量SCL SDA均有3.5v电压。无示波器,对不起大家。
按理说官方例程不会有错误的,只能是我没调好,但就是卡在那一句while (UCB0CTL1 & UCTXSTP);
外部器件BQ27441板接智能电源I2C开发板EV2300良好,说明外部器件I2C工作正常,可为什么就是不能与我的LAUNCHPAD通讯呢?