主题中讨论的其他器件: MSP430FR2475
我通过使用 RF430CL331H_Host_Firmware (sloc320.zip)中提供的通信堆栈、使用 RF430CL331H 实现了 NDEF 4类标签。
RF430CL331H 连接到 MSP430FR2475 eUSCI_B1接口。 代码已从 eUSCI_B0迁移到 eUSCI_B1。
总线上没有其他 I2C 外设。 MSP430FR2475以16MHz 运行。
如果我们使用100kBit/s 的 I2C 接口运行、通信工作正常、我可以从标签读取所有数据。
但是、如果我们希望与400kBits 进行通信、那么通信将在 MSP 向 RF430写入命令以从3读取数据时停止。 NDEF 文件。
SCL 线路被永久拉低、任何事件都不会将 MSP430从睡眠状态唤醒。
RF430CL331H 数据表指定如果主控器件支持时钟扩展、则支持400kBit/s、如所示、eUSCI_B 就是这种情况
MSP430FR4xx 和 MSP430FR2xx 系列数据表。
TI 的示例应用配置为在400kBits /秒上运行
UCB0BRW = 20; //波特率= SMLK/20 = 400kHz
有一些令人恼火的东西:为什么在示例实现中没有检查 RF430_I2C_Write 函数中的 UCSCLLOW?
我还不清楚的是:MSP430FR2xx 系列数据表规定了应避免时钟拉伸的情况。
这些情况是否适用于主模式? 如果是、在示例代码中在何处处理它们?
感谢您的支持!
/*
* RF430_Comm.c
* Polarion ID:ISM_CU-2171
*
* RF430CL331H 主机示例项目
*
*版权所有(C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 以源代码和二进制形式重新分发和使用、有无
* 如果满足以下条件、则允许进行修改
符合*:
*
* 源代码的重新分发必须保留上述版权
* 注意、此条件列表和以下免责声明。
*
* 二进制形式的再发行必须复制上述版权
* 请注意、中的此条件列表和以下免责声明
* 随提供的文档和/或其他材料
*分发。
*
* 德州仪器公司的名称和名称均不相同
* 其贡献者可用于认可或推广衍生产品
* 未经特定的事先书面许可。
*
* 本软件由版权所有者和贡献者提供
* "按原样"以及任何明示或暗示的保证、包括但不包括
* 仅限于对适销性和适用性的暗示保证
* 一项特定目的不予承认。 在任何情况下、版权均不得
* 所有者或贡献者应对任何直接、间接、偶然或
* 特殊、惩戒性或后果性损害(包括但不包括)
* 仅限于采购替代货物或服务;丧失使用、
* 数据或利润;或业务中断)
* 责任理论、无论是合同责任、严格责任还是侵权行为
* (包括疏忽或其他)因使用而以任何方式产生
* 、即使被告知可能会发生此类损坏。
*
*
#include "config.h"
#if CONFIG_IMPLET_NFC
//#include "msp430.h"
#include "RF430_example.h"
#include "RF430_Comm.h"
#include
#include
#define START 1.
#define 继续 0
#define 失败 0
define PASS 1
#define SET 1
#define CLEAR 0
#define I2C_Nack_RCVD 2.
#define I2C_Transmit 3.
#define LPM_MODE LPM0_BITS
uint8_t * PTxData; //指向 TX 数据的指针
uint8_t * PRxData; //指向 RX 数据的指针
uint16_t TXByteCtr;
uint16_t RXByteCtr;
uint8_t RF430_I2C_STATE;
uint8_t RF430_I2C_Start = 0;
//#define I2C_DELAY 600
//#define PULSEL_OUT P1SEL &=~BIT4;P1DIR |= BIT4;P1OUT|= BIT4 //范围中断
#define I2C_DELAY 0
#define I2C_allow (I2C_READY_IN 和 I2C_READY_PIN)
/
* Read_Register
(三
*
*简介:在 reg_addr 读取寄存器,返回结果
*
* param[in]: reg_addr:从中读取数据的地址
*
* param[out]: 无
*
* return: uint16_t:寄存器的结果
(二 /
uint16_t READ_Register (uint16_t REG_addr)
{
uint8_t TxAddr[2]={0、0};
uint8_t RxBuffer[2]={0、0};
TxAddr[0]= reg_addr >> 8; //地址的 MSB
TxAddr[1]= reg_addr & 0xFF; //地址 LSB
while (!I2C_allow); //等待、直到它可以安全地传输
if (RF430_I2C_Write_Restart_Read (((uint8_t *) TxAddr、2、(uint8_t *) RxBuffer、2)!=失败)
返回 RxBuffer[1]<< 8 | RxBuffer[0];
其他
__no_operation();
while (UCB1CTL1 & UCTXSTP); //确保发送了 STOP 条件
返回 RxBuffer[1]<< 8 | RxBuffer[0];
}
/
* Read_Continuous
(三
*
*简介:连续读取 data_length 字节并存储在"read_data"区域
*
* param[in]: reg_addr:从中读取数据的地址
* data_length:要读出的数据量
*
* param[out]: read_data:存储读出数据的数组
*
*返回: 无
(二 /
void read_continuous (uint16_t reg_addr、uint8_t* read_data、uint16_t data_length)
{
uint8_t TxAddr[2]={0、0};
TxAddr[0]= reg_addr >> 8; //地址的 MSB
TxAddr[1]= reg_addr & 0xFF; //地址 LSB
while (!I2C_allow); //等待、直到它可以安全地传输
RF430_I2C_Write_Restart_Read (((uint8_t *) TxAddr、2、(uint8_t *) Read_data、data_length);
while (UCB1CTL1 & UCTXSTP); //确保发送了 STOP 条件
}
/
* Write_Register
(三
*
*简介:在 reg_addr 写入寄存器的值
*
* param[in]: reg_addr:要将数据写入的地址
* value:要写入 reg_addr 的值
*
* param[out]: 无
*
*返回: 无
(二 /
空 Write_Register (uint16_t reg_addr、uint16_t value)
{
uint8_t TxData[4]={0、0、0};
TxData[0]= reg_addr >> 8; //地址的 MSB
TxData[1]= reg_addr & 0xFF; //地址 LSB
TxData[2]=值& 0xFF;
TxData[3]=值>> 8;
while (!I2C_allow); //等待、直到它可以安全地传输
RF430_I2C_Write ((uint8_t *) TxData、4、start);
RF430_I2C_Send_Stop ();
{
uint16_t delay = 10;
while (((UCB1CTL1 & UCTXSTP)&& DELAY) //确保发送停止条件,添加了由于无限循环而导致的超时时间(不应为 AK 10-27-2013)
{
_DELAY_CYCLES (10);
延迟;
}
}
}
/
* Write_Continuous
(三
*
*简介:在 reg_addr 写入寄存器,并使用长度为 data_length 的"write_data"中的数据递增地址
*
* param[in]: reg_addr:写入数据的起始地址
* write_data:要写入的数据数组
* data_length:要写入的数据量
*
* param[out]: 无
*
*返回: 无
(二 /
void Write_Continuous (uint16_t reg_addr、uint8_t * write_data、uint16_t data_length)
{
uint8_t TxAddr[2]={0、0};
while (!I2C_allow); //等待、直到它可以安全地传输
TxAddr[0]= reg_addr >> 8; //地址的 MSB
TxAddr[1]= reg_addr & 0xFF; 地址的//LSB
RF430_I2C_Write ((uint8_t *) TxAddr、2、start);
RF430_I2C_Write (((uint8_t *) write_data、data_length、continue);
RF430_I2C_Send_Stop ();
while (UCB1CTL1 & UCTXSTP); //确保发送了 STOP 条件
}
/
* RF430_I2C_Write
(三
*
*简介:通过 I2C 写入数据
*
* param[in]: data:要写入的数据数组
* length:要写入的数据量
* CONT:如果设置为 START,则会在 I2C 总线上发出 START 条件。 另一个选项是继续(不带 Start 的数据写入)
*
* param[out]: 无
*
*返回: 无
(二 /
void RF430_I2C_Write (uint8_t *数据、uint16_t 长度、uint16_t 续)
{
_DELAY_CYCLES (I2C_DELAY); //事务之间需要延迟
PTxData =(uint8_t *) data; // TX 数组起始地址
TXByteCtr =长度;
/*检查 SCL 是否被外部拉低*/
while (((UCB1STATW 和 UCSCLLOW)!=0)
{}
如果(CONT== START){
RF430_I2C_Start =设置; //需要一种了解 ISR AK 10-23-2013中何时设置了启动条件的方法
UCB1CTL1 |= UCTR + UCTXSTT; // I2C TX、启动条件
}
否则{
UCB1CTL1 |= UCTR; // I2C TX
UCB1IFG |= UCTXIFG; //自起不发送 Kickoff IFG
}
_bis_SR_register (LPM_MODE + GIE); //输入 LPM、启用中断
__no_operation(); //保持在 LPM 中直到所有数据
//是 TX
RF430_I2C_Start =清除; //这应该在中断中清除、但为了确保也在这里清除、AK-1023-2013
如果(!(RF430_I2C_STATE = I2C_NACK_RCVD))
{
while (TXByteCtr!= 0); //确保发送了 STOP 条件
}
}
/
* RF430_I2C_READ
(三
*
*简介:通过 I2C 读取数据
*
* param[in]: data:存储读出数据的数组
* length:要读取的数据量
*
* param[out]: 无
*
*返回: 无
(二 /
void RF430_I2C_Read (uint8_t*数据、uint16_t 长度)
{
_DELAY_CYCLES (I2C_DELAY); //事务之间需要延迟
PRxData =(uint8_t *) data; // RX 缓冲区开始
RXByteCtr =长度; //加载 RX 字节计数器
UCB1CTL1 &=~UCTR; // I2C 读取
UCB1CTL1 |= UCTXSTT; // I2C 启动条件
_bis_SR_register (LPM_MODE + GIE); //输入 LPM、启用中断
//保持在 LPM 中直到所有数据
//是 RX
__no_operation(); //在此处设置断点<<和
//读取 RxBuffer 缓冲区
}
/
* RF430_I2C_Write_Restart_Read
(三
*
*简介:首先发送一部分数据(TX_DATA),然后接收 RF430CL331H 发送的数据
*
* param[in]: TX_DATA:要传输的数据数组
* TX_LENGTH:要传输的数据量
* RX_DATA:要接收的数据数组(在发送之后)
* rx_length:要接收的数据量
*
* param[out]: 无
*
*返回: 无
(二 /
uint8_t RF430_I2C_Write_Restart_Read (uint8_t * TX_data、uint16_t TX_length、uint8_t* Rx_data、uint16_t Rx_length)
{
RF430_I2C_STATE = I2C_Transmit;
PTxData =(uint8_t *) TX_DATA; // TX 阵列起始地址
TXByteCtr = TX_LENGTH;
RF430_I2C_Start =设置; //需要一种了解 ISR AK 10-23-2013中何时设置了启动条件的方法
UCB1CTL1 |= UCTR + UCTXSTT; // I2C 主发送器模式、生成启动条件
if (RF430_I2C_STATE = I2C_NACK_RCVD) //如果 RF430为 NACK
{
//Debug_Print ("RF430 NACK!!!!!!!! \n");
退货失败;
}
_bis_SR_register (LPM_MODE + GIE); //输入 LPM、启用中断
__no_operation(); //保持在 LPM 中直到所有数据
RF430_I2C_Start =清除; //这应该在中断中清除、但为了确保也在这里清除、AK-1023-2013
if (RF430_I2C_STATE = I2C_NACK_RCVD) //如果 RF430为 NACK
{
//Debug_Print ("RF430 NACK!!!!!!!! \n");
退货失败;
}
PRxData =(uint8_t *) Rx_DATA; // RX 缓冲区开始
RXByteCtr = rx_length; //加载 RX 字节计数器
UCB1CTL1 &=~UCTR; // I2C 读取
RF430_I2C_Start =清除; //仅在发送和启动条件-AK 10-23-2013上需要
UCB1CTL1 |= UCTXSTT; // I2C 启动条件
_bis_SR_register (LPM_MODE + GIE); //输入 LPM、启用中断
//保持在 LPM 中直到所有数据
//是 RX
RF430_I2C_Start =清除; //这应该在中断中清除、但为了确保也在这里清除、AK-1023-2013
__no_operation(); //在此处设置断点<<和
//读取 RxBuffer 缓冲区
回程通行证;
}
/
* RF430_I2C_Send_Stop
(三
*
*简介:发出停止条件以终止数据包
*
* param[in]: 无
*
* param[out]: 无
*
*返回: 无
(二 /
void RF430_I2C_Send_Stop ()
{
_DELAY_CYCLES (100);
UCB1CTL1 |= UCTXSTP; // I2C 停止条件
_enable_interrupt ();
while (!(UCB1CTL1 & UCTXSTP)); //确保发送停止条件
_disable_interrupt ();
}
/
* USCI_B1_ISR
(三
*
*简介:处理通过 I2C 发送和接收数据包。 由上述功能控制。
*
* param[in]: 无
*
* param[out]: 无
*
*返回: 无
(二 /
#pragma vector = USCI_B1_Vector
_interrupt void USCI_B1_ISR (void)
{
switch (__evo_in_range (UCB1IV、12))
{
USCI_NONE 案例 :
中断; //无中断
案例 USCI_I2C_UCALIFG: // UCALIFG 中断
中断;
案例 USCI_I2C_UCNACKIFG: //收到 NACK
RF430_I2C_STATE = I2C_NACK_RCVD;
UCB1CTL1 |= UCTXSTP; // I2C 停止条件
UCB1IFG = 0; //清除所有 USCI_B0标志
_BIC_SR_REGISTER_ON_EXIT (LPM_MODE); //退出 LPM
中断;
案例 USCI_I2C_UCSTTIFG: //开始条件
中断;
案例 USCI_I2C_UCSTPIFG: //停止条件
中断;
案例 USCI_I2C_UCRXIFG0: //处理 RX 数据
RXByteCtr --; //递减 RX 字节计数器
IF (RXByteCtr)
{
* PRxData++= UCB1RXBUF; //将 RX 数据移动到地址 PRxData
IF (RXByteCtr = 1)
UCB1CTL1 |= UCTXSTP; //在下一个 RX 上生成 I2C 停止条件
}
其他
{
* PRxData = UCB1RXBUF; //将最终 RX 数据移动到 PRxData
_BIC_SR_REGISTER_ON_EXIT (LPM_MODE);//退出活动 CPU
}
中断;
案例 USCI_I2C_UCTXIFG0: //处理 TX 数据
if (TXByteCtr) //检查 TX 字节计数器
{
unsigned int delay = 0;
UCB1TXBUF =* PTxData++; //加载 TX 缓冲区
TXByteCtr -; //减量 TX 字节计数器
if (TXByteCtr = 1)
{
while ((延迟< 9000)&&(UCB1CTL1 & UCTXSTT)&&(RF430_I2C_Start = SET)//仅在请求启动条件时进入此循环
{
_DELAY_CYCLES (40);
延迟+=40;
}
if (((UCB1CTL1 & UCTXSTT)&&(RF430_I2C_Start = SET)// 仍在等待? --仅当需要启动条件时,
{
RF430_I2C_STATE = I2C_NACK_RCVD;
_BIC_SR_REGISTER_ON_EXIT (LPM_MODE);//退出 LPM
}
}
}
其他
{
//UCB1CTL1 |= UCTXSTP; // I2C 停止条件
UCB1IFG &=~UCTXIFG; //清除 USCI_B0 TX 内部标志
_BIC_SR_REGISTER_ON_EXIT (LPM_MODE);//退出 LPM
}
RF430_I2C_Start =清除; //清除在第一个 TX、开始已经通过
中断;
默认值:
__no_operation();
中断;
}
}
#endif