主题中讨论的其他部件: INA260, MSPWARE, MSP430F2619, ENERGIA
工具/软件:Code Composer Studio
团队,
我 是一个应用程序旋转器,正在为客户启动和运行新的传感器演示。 该传感器需要i2c,我们正在对MSP430F5529进行降级。 目前,我正努力让i2c工作,以便我可以在寄存器中写入和读取数据。 我不确定应该降级的传感器是否正常工作,因此目前我只是尝试通过i2c对INA260 EVM进行读写操作。 到目前为止,我尝试了多种方法。 我尝试将代码从USBIB0基址读取和写入多个字节的“示例”。 我还尝试将其他人的I2C代码从其他微控制器移植到5529,但没有成功。 我认为我的主要问题是编写ISR,我没有找到这方面的好例子。
问题1:
TI是否有任何良好的I2C示例用于读/写器件?
问题2:
我在下面列出了我的3种方法。 如果其中任何一个看起来很接近,我将非常感谢您对我如何开始使用I2C的意见。 我以前在微芯片控制器上使用过I2C,并阅读了我可以找到的所有TI文献(用户指南,数据表,如何使用I2C,I2C基础知识和mspware)。 我现在也熟悉了USCI图书馆。
方法1:根据 MSP430F2619的示例代码编写i2c。
主要c
#include <stdio.h>
#include <msp430f5529.h>
#include <lib5529i2c.h>
unsigned char array[5]={ 0x00, 0x07, 0x27};
unsigned char array2[5];
signed char byteCtr;
unsigned char *TI_receive字段;
unsigned char *TI_transmit_field;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;//禁用看门狗
P1DIR |= 0x01;
p1out= 0x00;//将WFP 1.0 配置为输出
_EINT();//启用中断
__enable_interrupit();
TI_USI_I2C_TEXINIT (0x40,0x12);//初始化USCI
同时( TI_USI_I2C_NOREADY());
TI_USI_I2C_Transmit (3,array);//传输数组的前3个字节
//LPM0;//在通信期间将CPU置于休眠状态
TI_USI_I2C_receiveinit(0x40,0x12);
同时( TI_USI_I2C_NOREADY());
TI_USI_I2C_receive (3,array2);
}
lib5529i2c.h
/* * lib5529i2c.h * *创建时间:2018年2月9日 * 作者:a22.6654万 */ #ifndef LIB5529I2C_H_ #define LIB5529I2C_H_ #define SDA_PIN BIT0 // msp430x261x UCB0SDA引脚 #define SCL_PIN BIT1 // msp430x261x UCB.S引脚 void TI_USI_I2C_receiveinit(unsigned char slaver_address, unsigned char presale); void TI_USI_I2C_transmitinit(unsigned char slaver_address, unsigned char presale); void TI_I2C_unsigned char (i2C_dich_present (i2C_unsigned char ;#I2I2C_unsigned char /uchar未签名char 55_unsigned char i2I2I2I2I2_unsigned char *
lib5529i2c.c
//************************************************************************************************
// MSP430 USCI I2C发送器和接收器
////
说明:此代码将MSP430的USCI模块配置为
// I2C主模块,能够发送和接收字节。
////***
这是主代码***////
母版
// MSP430F2619
// --------
// /|\\| Xin|-
// || |//
--|RST XOUT|-
// | |//
| |//
| |//
| SDA/WFP 3.1 >//
| SCL/WFP 3.2 (SCL/WFP设置)|----------- >///
注:SDA和SCL需要外部拉拔
//
Uli Kretzschmar
// Texas Instruments Deutschland GmbH
// 2007年11月
//使用IAR嵌入式工作台版本:3.42A
//************************************************************************************************构建
包含"msp430f5529.h" //器件特定标头
//#include "msp430x22x4.h"
//#include "msp430x23x0.h"
//#include "msp430xG46x.h"
//... //可能有更多的设备
#include "lib5529i2c.h"
signed char byteCtr;
unsigned char *TI_receive_field;
unsigned char *TI_transmit_field;
int q=0;
//------------
// void TI_USI_I2C_receiveinit (unsigned char slaver_address
,// unsigned char prescale)
////
此函数初始化主接收操作的USCI模块。
////
in:unsigned char slaver_address => Slave Address
// 无符号字符预分页 => SCL时钟调整
//------------------
void TI_USI_I2C_receiveinit(unsigned char slaver_address,
unsigned char prescale){
P3SEL || SDA_PIN + SCL_PIN; //将I2C引脚分配给USI_B0
UCB0CTL1 = UCSWRST; //启用软件重置
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C主控,同步模式
UCB0CTL1 = UCSSEL_2 + UCSSWRST; //使用SMCLK,保持软件重置
UCB0BR0 =预分页; // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = slaver_address; //设置从属地址
UCB0CTL1 &=~UCSWRST; //清除软件重置,恢复操作
UCB0IE = UCNACKIE;
UCB0IE = UCRXIE; //启用RX中断
}//------------------
// void TI_USI_I2C_TRANSLINIT (unsigned char slaver_address
,// unsigned char prescale)
////
此函数初始化主传输操作的USCI模块。
////
in:unsigned char slaver_address => Slave Address
// 无符号字符预分页 => SCL时钟调整
//------------------
void TI_USI_I2C_TRANSLINIT (unsigned char slaver_address,
unsigned char prescale){
P3SEL || SDA_PIN + SCL_PIN; //将I2C引脚分配给USI_B0
UCB0CTL1 |= UCSWRST; //启用软件重置
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C主控,同步模式
UCB0CTL1 = UCSSEL_2 + UCSSWRST; //使用SMCLK,保持软件重置
UCB0BR0 =预分页; // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = slaver_address; //设置从属地址
UCB0CTL1 &=~UCSWRST; //清除软件重置,恢复操作
UCB0IE = UCNACKIE;
UCB0IE |= UCTXIE; //启用TX就绪中断
}//------------------
// void TI_USI_I2C_RECEIVE(unsigned char byteCount, unsigned char *field)
////
此函数用于在主接收器模式下启动I2C通信。
////
in:unsigned char byteCount =>应该读取的字节数
// 无符号字符*field =>用于存储收到的数据的数组变量
//------------------
void TI_USI_I2C_receive (unsigned char byteCount,unsigned char *field){
TI_receive_field = field;
if ( byteCount ==1).
byteCtr =0;
__disable_interrupt ();
UCB0CTL1 || UCTXSTT; // I2C启动条件
期间(UCB0CTL1和UCTXSTT); //开始条件已发送?
UCB0CTL1 || UCTXSTP; // I2C停止条件
__enable_interrupt ();
}如果(byteCount > 1),则为其它项{
byteCtr = byteCount -2;
UCB0CTL1 || UCTXSTT; // I2C启动条件
} else
同时(1); //非法参数
}//------------------
// void TI_USI_I2C_Transmit (unsigned char byteCount,unsigned char *field)
////
此函数用于在主传输模式下启动I2C通信。
////
in:unsigned char byteCount =>应该传输的字节数
// 无符号字符*field =>数组变量。 其内容将被发送。
//------------------
void TI_USI_I2C_Transmit (unsigned char byteCount,unsigned char *field){
TI_Transmit_field = field;
byteCtr = byteCount;
UCB0CTL1 || UCTR + UCTXSTT; // I2C TX,启动条件
}//------------------
// unsigned char TI_USI_I2C_SLAVE_Present (unsigned char slaver_address)
////
此函数用于查找I2C总线上的从属地址。
////
in:unsigned char slaver_address => Slave Address
// out:unsigned char => 0:未找到地址,
// 1:找到的地址
//------------------
unsigned char TI_USCI_I2C_SLAVER_present (unsigned char slaver_address){
unsigned char IE2_bak,slaveadr_Bak,ucb0i2cie,returnValue;
ucb0i2cie = UCB0IE; //恢复旧的UCB0I2CIE
IE2_BAK = UCB0IE; // store IE2 register
slaveadr_Bak = UCB0I2CSA; //存储旧的从属地址
UCB0IE &=~ UCNACKIE; // no nack interrupt
UCB0I2CSA = slaver_address; //设置从属地址
UCB0IE &=~(UCTXIE + UCRXIE); // NO RX或TX中断
__disable_interrupt();
UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP; // I2C TX,启动条件
while (UCB0CTL1和UCTXSTP); //等待停止条件
returnValue =!(UCB0STAT & UCNACKIFG);
__ENable_INTERRUC();
UCB0IE = IE2_BAK; //恢复IE2
UCB0I2CSA = slaveadr_Bak; //恢复旧的从属地址
UCB0IE = ucb0i2cie; //恢复旧的UCB0CTL1
返回值; //无论是否返回
//发生了一个nack
}//------------------
// unsigned char TI_USI_I2C_NOREADY()////
此函数用于检查是否正在进行通信。
//
//输出:unsigned char => 0:I2C总线空闲
,// 1:通信正在进行
中//----------------------------------
unsigned char TI_USSCI_I2C_NOFLEY(){
RETURN (UCB0STAT & UCBBUSY);
}
#pragma vector = USSCI_B0_Vector
__interrupt void USI_B0_ISR(void){
开关(__偶 数_IN_RANGE (UCB0IV,12))
{
案例10:
Q=10;//引导程序10:RXIFG --我还没有使用它(但我需要它)
IF (UCB0STAT和UCNACKIFG){ //如果从设备发送nack,则发送停止
UCB0CTL1 || UCTXSTP;
UCB0STAT &=~UCNACKIFG;
}
中断;
案例12:
Q=12;//矢量12:TXIFG
IF (P2IFG和UCRXIFG){
如果( byteCtr == 0){
UCB0CTL1 || UCTXSTP; // I2C停止条件
*TI_RECETE_FIELD = UCB0RXBUF;
TI_Receive_field+;
}
否则{
*TI_RECETE_FIELD = UCB0RXBUF;
TI_Receive_field++;
byteCtr --;
}
}
否则{
如果(byteCtr ==0){
UCB0CTL1 || UCTXSTP; // I2C停止条件
P2IFG &=~UCTXIFG; //清除USI_B0 TX int标志
}
否则{
UCB0TXBUF =*TI_Transmit_field;
TI_Transmit_field++;
byteCtr --;
}
}
中断;
默认:
中断;
}
}
方法2:根据5529读/写示例代码编写库
包含"msp430f5529.h" //器件特定标头
//#include "msp430x22x4.h"
//#include "msp430x23x0.h"
//#include "msp430xG46x.h"
//... //可能有更多设备
#include "lib5529i2c.h"
带符号char byteCtr;
unsigned char *TI_receive_field;
unsigned char *TI_transmit_field;
unsigned char TXByteCtr =0;
unsigned char RXByteCtr =0;
void TI_USI_I2C_receiveinit(unsigned char slaver_address,
unsigned char prescale){
P3SEL || SDA_PIN + SCL_PIN; //将I2C引脚分配给USI_B0
UCB0CTL1 = UCSWRST; //启用软件重置
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C主控,同步模式
UCB0CTL1 = UCSSEL_2 + UCSSWRST; //使用SMCLK,保持软件重置
UCB0BR0 =预分页; // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = slaver_address; //设置从属地址
UCB0CTL1 &=~UCSWRST; //清除软件重置,恢复操作
UCB0IE = UCNACKIE;
UCB0IE = UCRXIE; //启用RX中断
}
void TI_USI_I2C_TRANSLINIT (unsigned char slaver_address,
unsigned char prescale){
P3SEL || SDA_PIN + SCL_PIN; //将I2C引脚分配给USI_B0
UCB0CTL1 |= UCSWRST; //启用软件重置
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C主控,同步模式
UCB0CTL1 = UCSSEL_2 + UCSSWRST; //使用SMCLK,保持软件重置
UCB0BR0 =预分页; // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = slaver_address; //设置从属地址
UCB0CTL1 &=~UCSWRST; //清除软件重置,恢复操作
UCB0IE = UCNACKIE;
UCB0IE |= UCTXIE; //启用TX就绪中断
}
void TI_USI_I2C_receive(unsigned char byteCount, unsigned char *field){
TI_receive_field = field;
if ( byteCount ==1){
RXByteCtr = 0;
__disable_interrupt ();
UCB0CTL1 || UCTXSTT; // I2C启动条件
期间(UCB0CTL1和UCTXSTT); //开始条件已发送?
UCB0CTL1 || UCTXSTP; // I2C停止条件
__enable_interrupt ();
}如果(byteCount > 1),则为其它项{
RXByteCtr =字节计数-2;
UCB0CTL1 || UCTXSTT; // I2C启动条件
} else
同时(1); //非法参数
}
void TI_USI_I2C_Transmit (unsigned char byteCount,unsigned char *field){
TI_Transmit_field = field;
TXByteCtr = byteCount;
UCB0CTL1 ||= UCTR + UCTXSTT; // I2C tx,起始条件
}
unsigned char TI_USI_I2C_SLAVE_Present (unsigned char slaver_address){
unsigned char IE2_bak,slaveadr_Bak,ucb0i2cie,returnValue;
ucb0i2cie = UCB0IE; //恢复旧的UCB0I2CIE
IE2_BAK = UCB0IE; // store IE2 register
slaveadr_Bak = UCB0I2CSA; //存储旧的从属地址
UCB0IE &=~ UCNACKIE; // no nack interrupt
UCB0I2CSA = slaver_address; //设置从属地址
UCB0IE &=~(UCTXIE + UCRXIE); // NO RX或TX中断
__disable_interrupt();
UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP; // I2C TX,启动条件
while (UCB0CTL1和UCTXSTP); //等待停止条件
returnValue =!(UCB0STAT & UCNACKIFG);
__ENable_INTERRUC();
UCB0IE = IE2_BAK; //恢复IE2
UCB0I2CSA = slaveadr_Bak; //恢复旧的从属地址
UCB0IE = ucb0i2cie; //恢复旧的UCB0CTL1
返回值; //无论是否返回
//出现一个nack
}
unsigned char TI_USSCI_I2C_nofedy(){
Return (UCB0STAT & UCBBUSY);
}
#pragma vector = USSCI_B0_vector
__interrupt void USSCI_B0_ISR(void){
开关(__偶 数_IN_RANGE (UCB0IV,12))
{
案例10:
RXByteCtr --; // Decrement RX字节计数器
IF (RXByteCtr)
{
*TI_RECETE_FIELD = UCB0RXBUF; //将RX数据移动到PRxData地址
IF (RXByteCtr == 1) //只剩下一个字节?
UCB0CTL1 || UCTXSTP; //生成I2C停止条件
}
否则
{
*TI_RECETE_FIELD = UCB0RXBUF; //将最终RX数据移至PRxData
__BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出活动CPU
}
案例12:
IF (TXByteCtr) //检查TX字节计数器
{
UCB0TXBUF =*TI_Transmit_field; //加载TX缓冲区
TXByteCtr // Decrement TX字节计数
器}
否则
{
UCB0CTL1 || UCTXSTP; // I2C停止条件
UCB0IFG &=~UCTXIFG; //清除USI_B0 TX int标志
__BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出LPM0
}
默认:
中断;
}
}
/*
*以下是使用MSP430G2553对24LC512和DS3231 RTC进行读/写的示例。
*提供两种读写功能。
*
*该代码避免了任何while循环,并完全依赖于MSP430的中断和低功耗模式,将功耗降低到
*最低。
*
作者:Ahmed Talaat (aa_talaat@yahoo.com)
*日期:2012年10月19日
*
包含"msp430f5529.h"
#define ONEBYTEADDR 1.
#define TWOBYTEADDR 2.
#定义写入 0 // ISR模式写入或读取
#定义读取 1.
#define NOACK 二
#define EEPROM_ADDR 0x40
#define DS3231_ADDR 0x00
unsigned char txdataeepro[2];
unsigned char txdataDS3231[7]={0x20, 0x30, 0x20, 0x04, 0x17, 0x10,0x12};
unsigned char rxdata[150];
typedef结构{
volatile unsigned char *data_buf; // TX或Rx数据缓冲区的地址
volatile unsigned char buf_size; //缓冲区的大小
volatile unsigned char buf_index; //缓冲区中的索引
volatile unsigned char addr_index; //字节地址索引(0,1)
volatile unsigned char ISR_MODE; // Tx或Rx影响中断逻辑
要读/写的地址的volatile unsigned char addr_high字节;//高字节
要读/写的地址的volatile unsigned char addr_low_bytes;//低字节
volatile unsigned char addr_type; //两个字节(如EEPROM)或1个字节(如RTC
)} I2C_t;
I2c_t i2c_packet;
void i2c_init(void);
void i2c_tx (unsigned char,unsigned char *,unsigned char,unsigned char,unsigned char, unsigned char);
void i2c_rx (unsigned char,unsigned char *,unsigned char,unsigned char,unsigned char, unsigned char);
作废usdelay (int);
Void主(void)
{
WDTCTL = WDTPW + WDTHOLD; //停止WDT
I2C_INIT(); //初始化I2C
txdataeeproem[0]=0x61;
txdataeepro[1]=0x3F;
I2C_TX (EEPROM_ADDR,txdataeeprom,sizeof(txdataeeprom)-1,ONEBYTEADDR,0x00,0x00);//i2c TX 115字节起始地址@ 01:00
I2C_Rx (EEPROM_ADDR,rxdata,2,ONEBYTEADDR,0x00,0x00);//i2c从EEPROM起始值@地址01:00接收115字节
LPM0; //输入LPM0 w/ interrupts
}
void i2c_init(void){
P3SEL || BIT0 + BIT1; //设置I2C引脚
//P1SEL2|= BIT6 + BIT7;
UCB0CTL1 |= UCSWRST; //启用软件重置
UCB0CTL0 = UCMST + UCMODE_3 + UCWYNC;//I2C主控,同步模式
UCB0CTL1 = UCSSEL_2 + UCSSWRST; //使用SMCLK,保持软件重置
UCB0BR0 = 10; //fSCL = SMCLK/11 =~100kHz
UCB0BR1 = 0;
UCB0CTL1 &=~UCSWRST; //清除软件重置,恢复操作
UCB0IE |= UCTXIE; //启用TX中断
UCB0IE |= UCRXIE; //启用RX中断
UCB0IE |= UCNACKIE; //需要启用状态更改中断
__enable_interrupit(); //启用全局中断
}
void i2c_tx (unsigned char slaver_addr,unsigned char *txdata,unsigned char bufSize,unsigned char addr_size,
unsigned char high byte_addr,unsigned char low byte_addr){
I2C_PACKGE.ISR_MODE=写入;
I2c_packet.data_buf=txdata;
I2c_packet.buf_size=bufSize;
I2c_packet.buf_index=0;
I2c_packet.addr_type=addr_size;
I2c_packet.addr_high字节=高字节地址;
I2c_packet.addr_low_byte=low_byte_addr;
I2c_packet.addr_index=0;
UCB0I2CSA = slaver_addr; //从属地址
而(1){
UCB0CTL1 || UCTR + UCTXSTT; // I2C TX,启动条件
LPM0; //输入LPM0
//并保留,直到所有数据都已发送
如果(i2c_packet.isR_mode == NOACK){//如果没有收到ACK,则休眠0.5毫秒并重试
I2C_PACKGE.ISR_MODE =写入;
I2c_packet.addr_index=0; //为下一个写入操作重置地址索引
usdelay(500);
} 否则{
中断; //写入成功,然后退出
}
}
}
/*
*此函数从任何I2C设备读取。 它将作为参数:
*-从属地址(7位)
*-指向数据缓冲区的指针,以填充读取的数据。
*-缓冲区的大小
*-开始写入的地址位置的大小。 某些EEPROM为2个字节,而单字节
*适用于其他设备。 请注意,此函数的ISR假定地址字节写得高
先是*字节,然后是低字节秒。
*如果是单字节地址设备,则只使用高位字节来设置地址。
*-开始读取位置的高字节和低字节地址。
*
*函数以写入操作开始,以指定带有start的读取操作的地址
*如果写入操作的启动条件不是ack (例如,EEPROM正忙于前一个写入周期),
*相应的中断会检测此情况,生成停止信号和计时器A1 (非计时器A0)
对于0.5 ms,*被激活,然后重复尝试写入。
*
*一旦写入地址成功,功能将切换到读取模式,并填充提供的缓冲区
*
*/
void i2c_rx(unsigned char slaver_addr, unsigned char *rxdata, unsigned char bufSize, unsigned char addr_size,
unsigned char high byte_addr,unsigned char low byte_addr){
I2C_PACKGE.ISR_MODE=读; // ISR将发送地址字节,然后唤醒CPU。
I2c_packet.addr_type=addr_size;
I2c_packet.addr_high字节=高字节地址;
I2c_packet.addr_low_byte=low_byte_addr;
I2c_packet.addr_index=0;
UCB0I2CSA = slaver_addr; //从属地址
而(1){
UCB0CTL1 || UCTR + UCTXSTT; // I2C TX,启动条件
LPM0; //输入LPM0
//并保留,直到所有数据都已发送
如果(i2c_packet.isR_mode == NOACK){//如果没有收到ACK,则休眠0.5毫秒并重试
I2C_PACKGE.ISR_MODE =读取;
I2c_packet.addr_index=0; //为下一个写入操作重置地址索引
usdelay(500);
} 否则{
中断; //写入成功,然后退出
}
}
//我们已经编写了地址,因此现在只读数据。
I2c_packet.addr_index=i2c_packet.addr_type;
I2c_packet.data_buf=rxdata;
I2c_packet.buf_size=bufSize;
I2c_packet.buf_index=0;
UCB0CTL1 &=~UCTR; // I2C RX
UCB0CTL1 || UCTXSTT; // I2C重新启动条件
LPM0; //输入LPM0
//并一直保留,直到收到所有数据
}
//interrupt (USCIAB0RX_vector)状态更改,从从实例
/*中捕获NO_Ack
*每次UCSI_B模块准备好在UCB0TXBUF中获取新字节以发送到I2C设备时,都会调用此中断。 或者
*将新字节读取到UCB0RXBUF中,我们应该将其拾取。
*当启用UCB0TXIE和UCB0RXIE时,调用中断。 要无限期停止调用此中断,应
清除相应的*中断标志。
*如果UCB0XXBUF是访问,则USI_B模块会自动清楚地显示这些标志。 但是,如果我们要执行的操作与读取
*或向UCB0XXBUF写入字节不同,我们需要自己清除相应的标志,否则ISR将被调用
*,整个程序将挂起。
*/
#pragma vector = USI_B0_Vector
__interrupt void USI_B0_ISR(void)
{
开关(__偶 数_IN_RANGE (UCB0IV,12))
{
案例10:
RXByteCtr --; // Decrement RX字节计数器
IF (RXByteCtr)
{
*PRxData++= UCB0RXBUF; //将RX数据移动到PRxData地址
IF (RXByteCtr == 1) //只剩下一个字节?
UCB0CTL1 || UCTXSTP; //生成I2C停止条件
}
否则
{
*PRxData = UCB0RXBUF; //将最终RX数据移至PRxData
__BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出活动CPU
}
案例12:
//无论发送或接收模式如何,发送地址字节均不受限制。*/
如果(i2c_packet.addr_index=0){
UCB0TXBUF = i2c_packet.addr_high字节;
I2c_packet.addr_index+;
}
否则,如果(i2c_packet.addr_index=1 && i2c_packet.addr_type=TWOBYTEADDR){
UCB0TXBUF = i2c_packet.addr_low_byte;
I2c_packet.addr_index+;
}
否则,如果(UCTXIFG & P2IFG && i2c_packet.ISR_MODE=read){
// USI_B已准备好获取新的数据字节来传输它,我们处于读取模式。
//因此,我们不应继续编写,而应退出调用函数
//将USI_B切换为读模式
P2IFG &=~UCTXIFG; //手动清除USI_B0 TX int标志,因为我们没有写入UCB0TXBUF
LPM0_EXIT; //退出LPM0
}
否则,如果(UCTXIFG & P2IFG && i2c_packet.ISR_MODE=WRITE){// USSCI_B准备获取新的数据字节以进行传输,并且我们处于写入模式。
IF (i2c_packet.buf_index == i2c_packet.buf_size){//如果没有更多数据要传输,则发出停止条件并唤醒CPU。
P2IFG &=~UCTXIFG; //手动清除USI_B0 TX int标志,因为我们没有写入UCB0TXBUF
UCB0CTL1 || UCTXSTP; // I2C停止条件
LPM0_EXIT; //退出LPM0
} 否则{
UCB0TXBUF = i2c_packet.data_buf[i2c_packet.buf_index];
I2c_packet.buf_index++; //增量TX字节计数
器}
}
否则,如果(UCRXIFG & P2IFG && i2c_packet.addr_index=i2c_packet.addr_type){
//读取模式,我们已经完成了地址的写入
I2c_packet.data_buf[i2c_packet.buf_index]= UCB0RXBUF;
I2c_packet.buf_index++; //增量RX字节计数器
IF (i2c_packet.buf_index == i2c_packet.buf_size){//如果接收最后一个字节,则发出停止条件并唤醒CPU。
P2IFG &=~UCRXIFG; //清除USI_B0 RX int标志
UCB0CTL1 || UCTXSTP; //此处的I2C停止条件是避免读取任何额外的字节
LPM0_EXIT; //退出LPM0
}
}/*
中断;
默认:
中断;
*/
}
}
//------------------
//微秒延迟
//
void usdelay (int interval){
//设置时间A
TA1CCTL0 = CCIE; //中断已启用
TA1CCR0 = TA1R +间隔;//微秒@ 1MHz时钟
TA1CTL = tassel_2 + MC_2;// SMCLK,连续模式。
LPM0; //暂停CPU
}
//计时器A1中断服务例程。 TIMERx_AY_VECTOR。(x是计时器的索引,y是此计时器的矢量)
#pragma vector=Timer1_A0_vector
__interrupt void Timer1_A0 (void)
{
TA1CTL = 0; //停止计时器_A1
LPM0_EXIT; //返回活动
}
//************************************************************************************************ // MSP430 USCI I2C发送器和接收器//// 说明:此代码将MSP430的USCI模块配置为// I2C主控器,能够发送和接收字节。/// ***这是主代码***/// 主// MSP430F2619// -------- // /|\\| Xin|-// || |// --|RST XOUT|-// | |// | |// | |// | SDA/WFP 3.1 >// | SCL/WFP 3.2 (SCL/WFP设置)|----------- >///注:SDA和SCL///Uli Kretzschmar// Texas Instruments Deutschland GmbH// 2007年11月//使用IAR嵌入式工作台版本:3.42A/************************************************************************************************************************构建外部拉线 /*#包括"msp430f5529.h" //器件特定标头//#include "msp430x22x4.h"//#include "msp430x23x0.h"//#include "msp430xG46x.h"/... //可以使用更多设备
#include "lib5529i2c.h"
signed char byteCtr;unsigned char *TI_receive字段;unsigned char *TI_transmit_field;int q=0;//------------------ // void TI_USI_I2C_receiveinit(unsigned char slaver_address,// unsigned char prescale)////此函数初始化主接收操作的USCI模块。//// in: unsigned char slaver_address => Slave Address// unsigned char prescale => SCL时钟调整//------------------ void TI_USI_I2C_receiveinit(unsigned char slaver_address, unsigned char prescale){ P3SEL || SDA_PIN + SCL_PIN; //将I2C引脚分配给USI_B0 UCB0CTL1 = UCSWRST; //启用软件重置 UCB0CTL0 = UMST + UCMODE_3 + UCSYNC; // I2C主控,同步模式 UCB0CTL1 = UCSSEL_2 + UCSWRST; //使用SMCLK,保持软件重置 UCB0BR0 =预分页; // set prescaler UCB0BR1 = 0; UCB0I2CSA = slaver_address; //设置从属地址 UCB0CTL1 &=~UCSWRST; //清除软件重置,恢复操作 UCB0IE = UCNACKIE; UCB0IE = UCRXIE; //启用RX中断}
//------------------ // void TI_USI_I2C_TRANSLINIT (unsigned char slaver_address,// unsigned char prescale)////此函数初始化主传输操作的USCI模块。//// in: unsigned char slaver_address => Slave Address// unsigned char prescale => SCL时钟调整//------------------ void TI_USI_I2C_TRANSLINIT (unsigned char slaver_address, unsigned char prescale){ P3SEL || SDA_PIN + SCL_PIN; //将I2C引脚分配给USI_B0 UCB0CTL1 |= UCSWRST; //启用软件重置 UCB0CTL0 = UMST + UCMODE_3 + UCSYNC; // I2C主控,同步模式 UCB0CTL1 = UCSSEL_2 + UCSWRST; //使用SMCLK,保持软件重置 UCB0BR0 =预分页; // set prescaler UCB0BR1 = 0; UCB0I2CSA = slaver_address; //设置从属地址 UCB0CTL1 &=~UCSWRST; //清除软件重置,恢复操作 UCB0IE = UCNACKIE; UCB0IE |= UCTXIE; //启用TX就绪中断}
//------------------ // void TI_USI_I2C_RECEIVE(unsigned char byteCount, unsigned char *field)////此函数用于在主接收器模式下启动I2C通信。//// in: unsigned char byteCount => 应该读取的字节数/ 未签名的char *field => 数组变量,用于存储接收的数据//------- void TI_USI_I2C_receive (unsigned char byteCount,unsigned char *field){ TI_receive_field = field; if ( byteCount ==1){ byteCtr =0; __disable_interrupti(); UCB0CTL1 || UCTXSTT; // I2C启动条件 while (UCB0CTL1和UCTXSTT); //开始条件已发送? UCB0CTL1 || UCTXSTP; // I2C停止条件 __enable_interrupt(); }否则,如果( byteCount >1){ byteCtr = byteCount -2; UCB0CTL1 |= UCTXSTT; // I2C启动条件 }其他 ,同时(1); //非法参数}
//------------------ // void TI_USI_I2C_Transmit (unsigned char byteCount,unsigned char *field)////此函数用于在主传输模式下启动I2C通信。//// in: unsigned char byteCount => 应传输的字节数// unsigned char *field => 数组变量。 它的内容将被发送。//------------------ void TI_USI_I2C_Transmit (unsigned char byteCount,unsigned char *field){ TI_Transmit_field = field; byteCtr = byteCount; UCB0CTL1 || UCTR + UCTXSTT; // I2C TX,启动条件}
//------------------ // unsigned char TI_USI_I2C_SLAVE_Present (unsigned char slaver_address)////此函数用于查找I2C总线上的从属地址。//// in: unsigned char slaver_address => SlaverAddress// out: unsigned char => 0:未找到地址,// 1:地址已找到//-------------------------------------------------- unsigned char TI_USCI_I2C_SLAVER_present (unsigned char slaver_address){ unsigned char IE2_bak,slaveadr_Bak,ucb0i2cie,returnValue; ucb0i2cie = UCB0IE; //恢复旧的UCB0I2CIE IE2_BAK = UCB0IE; // store IE2 register slaveadr_Bak = UCB0I2CSA; //存储旧的从属地址 UCB0IE &=~ UCNACKIE; // no nack interrupt UCB0I2CSA = slaver_address; //设置从属地址 UCB0IE &=~(UCTXIE + UCRXIE); // NO RX或TX中断 __disable_interrupt(); UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP; // I2C TX,启动条件 while (UCB0CTL1和UCTXSTP); //等待停止条件
returnValue =!(UCB0STAT & UCNACKIFG); __enable_interrupt(); UCB0IE = IE2_BAK; //恢复IE2 UCB0I2CSA = slaveadr_Bak; //恢复旧的从属地址 UCB0IE = ucb0i2cie; //恢复旧的UCB0CTL1 返回值; //无论是否返回 //发生了一个nack}
//------------------ // unsigned char TI_USI_I2C_NOREADY()///此函数用于检查是否正在进行通信。////输出: unsigned char => 0:I2C总线空闲,// 1:通信正在进行中//------------------ unsigned char TI_USSCI_I2C_NOREADY(){ Return (UCB0STAT & UCBBUSY);}
#pragma vector = USI_B0_vector__interrupt void USI_B0_ISR(void){ switch (__偶 数_in_range(UCB0IV, 12)) {
案例10: Q=10;//引导程序10:RXIFG --我还没有使用它(但我需要它) IF (UCB0STAT和UCNACKIFG){ //如果从设备发送nack,则发送停止 UCB0CTL1 || UCTXSTP; UCB0STAT &=~UCNACKIFG; } 中断; 案例12: Q=12;//矢量12:TXIFG IF (P2IFG和UCRXIFG){ 如果( byteCtr == 0){ UCB0CTL1 || UCTXSTP; // I2C停止条件 *TI_RECETE_FIELD = UCB0RXBUF; TI_Receive_field+; } 否则{ *TI_RECETE_FIELD = UCB0RXBUF; TI_Receive_field++; byteCtr --; } } 否则{ 如果(byteCtr ==0){ UCB0CTL1 || UCTXSTP; // I2C停止条件 P2IFG &=~UCTXIFG; //清除USI_B0 TX int标志 } 否则{ UCB0TXBUF =*TI_Transmit_field; TI_Transmit_field++; byteCtr --; } } 中断; 默认: 中断;
}
}
*/