This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28384D:I2C 卡在环路中、以检查是否设置了 I2C_STS_REG_ACCESS_RDY。

Guru**** 1460770 points
Other Parts Discussed in Thread: TMS320F28384D, SYSCONFIG, C2000WARE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1333443/tms320f28384d-i2c-is-stuck-in-a-loop-to-check-if-the-i2c_sts_reg_access_rdy-is-set

器件型号:TMS320F28384D
主题中讨论的其他器件: SysConfigC2000WARE

大家好、我正在尝试让 I2C 在我嵌入到输出板上的 TMS320F2838处理器上工作。  

请不要给出硬件建议、因为我已经验证了我的硬件设置、我能够让 USB 到在电路板上工作的 UART、并从我的笔记本电脑的 CMD 终端从电路板上读写文本。  

我想我配置的一些软件不正确。 我的目标是简单地从 VNCL4040距离传感器提取数据。 不过在我的 beginTransmission ()函数中,我被卡在 while 循环中,该循环检查是否 设置了 I2C_STS_REG_ACCESS_RDY。 我还被困在 while 环路中、以检查总线是否处于繁忙状态。  

更多信息:

-我在 TMS320F2837xd LaunchPad 上具有完全相同的代码,可以与我使用的相同传感器完美配合使用

-我在 TMS320F28384D 的定制分线板上对 I2C 线路使用 GIPO 0和1。  

我正在使用以下路径中的示例 sysconfig 文件: C:\ti\c2000\c2000\C2000Ware_5_01_00_00\driverlib\f2838x\examples\C28x\empty_projects。  

-我在主代码中编写的所有代码粘贴到下面,后面是从 SysConfig 生成的配置文件。 我还要运行一个简单的中断使 LED 闪烁、这是运行正常的。

-我以黄色突出显示了我的代码所处的函数。  

-我以橙色突出显示了我所停留的特定行。

当我为 I2C 总线调用"get status"时、得到的值为0x00001411  

//##########################################################################出################################出
//
//文件:empty_driverlib_main.c
//
//! \addtogroup driver_example_list
//!

空项目示例


//!
//! 此示例是用于 Driverlib 开发的空项目设置。
//!
//
//##########################################################################出################################出

//------------------
//
//全局变量
//
//------------------
uint32_t 状态;
uint16_t AvailableI2C_slaves [20];
uint16_t * Devices = AvailableI2C_slaves;//指向阵列的指针
uint8_t data[2];
uint16_t * k =数据;

//------------------
////
////I2C 帮助程序函数
////
//------------------
void releaseI2CBusFromBusyState(){
//禁用 I2C 模块
I2C_disableModule (VNCL_40_BASE);

//切换 SCL 线路(时钟)以释放总线
GPIO_togglePin (GPIO_PIN_I2CA_SDA);

//切换 SDA 线(数据)以释放总线
GPIO_togglePin (GPIO_PIN_I2CA_SCL);

//支持 Re 的 I2C 模块
I2C_enableModule (VNCL_40_BASE);

void I2CBUS_scan (uint16_t * AvailableDevices)
{
//禁用中断
I2C_disableInterrupt (I2CA_BASE、(I2C_INT_ADDR_SLAVE | I2C_INT_STOP_Condition | I2C_INT_ARB_LOSS| I2C_INT_NO_ACK));
uint16_t Slave_Address、I;
I = 0;
//最多可连接128个 I2C 设备,承载7位地址

对于(Slave_Address = 1;Slave_Address < 128;Slave_Address +)
{
//检查总线状态,成功时,它将返回0。 如果不等于0、则停止程序。

while (I2C_isBusy (I2CA_BASE);


//配置 I2C
I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE | I2C_REPEATE_MODE);
I2C_setAddressMode (I2CA_BASE、I2C_ADDR_MODE_7BITS);
I2C_setSlaveAddress (I2CA_BASE、Slave_Address);
I2C_sendStartCondition (I2CA_BASE);
//等待传输完成
//状态应为"register-access-ready"以继续

while (! (I2C_getStatus (I2CA_BASE)和 I2C_STS_REG_ACCESS_RDY);
I2C_sendStopCondition (I2CA_BASE);
//等待停止位被清零
while (I2C_getStopConditionStatus (I2CA_BASE));
///等待 BUSY 位被清零 总线不应处于忙状态
while (I2C_isBusy (I2CA_BASE));
//获取 I2C 状态以查看它是否已得到从机应答
状态= I2C_getStatus (I2CA_BASE);

如果(!(STATUS 和 I2C_STS_NO_ACK))
{
AvailableDevices[i]= Slave_Address;
I++;

I2C_clearStatus (I2CA_BASE、I2C_STS_NO_ACK | I2C_STS_ARB_LOST | I2C_STS_REG_ACCESS_RDY| I2C_STS_STOP_Condition);

I2C_setConfig (I2CA_BASE、(I2C_MASTER_SEND_MODE));
I2C_enableInterrupt (I2CA_BASE、(I2C_INT_ADDR_SLAVE | I2C_INT_STOP_Condition | I2C_INT_ARB_LOSS| I2C_INT_NO_ACK));


//用于显示 I2C 上连接的设备的功能
void printAvailable_I2C_Devices (){
uint8_t I = 0;
I2CBUS_SCAN (设备)
//只想密钥存储阵列的非空地址
for (i = 0;i <= 19;i++){//AvailbleDevices[]数组只有20个大容量,但可以在需要时进行扩展
//检查数组中的值是否为空
if (AvailableI2C_slaves [i]!= 0){
newline();//在屏幕上打印新行
sendMsg ((uint16_t*)"I2C Detected! 目标地址为:"、33);
printByte (AvailableI2C_slaves [i]);
newline();


空开始传输(uint16_t slaveAddr)
{
//检查地址是否有效
bool IsValid = I2C_isBaseValid (I2CA_BASE);

//检查总线是否繁忙,这可能是我们的问题
while (I2C_isBusy (I2CA_BASE));

while (I2C_getStopConditionStatus (I2CA_BASE));
I2C_setConfig (I2CA_BASE、(I2C_MASTER_SEND_MODE|I2C_REPEATE_MODE));
I2C_setSlaveAddress (I2CA_BASE、slaveAddr);
I2C_sendStartCondition (I2CA_BASE);
Status = I2C_getStatus (I2CA_BASE);//不断返回0x00001411
while (! (I2C_getStatus (I2CA_BASE)和 I2C_STS_REG_ACCESS_RDY);


空写入(uint16_t DATA)
{
while (! (I2C_getStatus (I2CA_BASE)和 I2C_STS_TX_DATA_RDY);
I2C_putData (I2CA_BASE、DATA);
// I2C_clearStatus (I2CA_BASE、I2C_STS_TX_DATA_RDY);

空 endTransmission ()
{
// while (! (I2C_getStatus (I2CA_BASE)和 I2C_STS_TX_DATA_RDY);
I2C_sendStopCondition (I2CA_BASE);


void read (uint16_t *数据、uint16_t count)
{
uint8_t I = 0;
对于(I = 0;I < count;I++)
{
while (! (I2C_getStatus (I2CA_BASE)和 I2C_STS_RX_DATA_RDY);
data[i]= I2C_getData (I2CA_BASE);
如果(i == count - 1){
//如果是最后一个数据字节,则清除接收标志
I2C_clearStatus (I2CA_BASE、I2C_STS_RX_DATA_RDY);



void requestFrom (uint16_t slaveAddr、uint16_t regAddr、uint16_t count)
{
while (I2C_getStopConditionStatus (I2CA_BASE));
I2C_setSlaveAddress (I2CA_BASE、slaveAddr);
I2C_setConfig (I2CA_BASE、(I2C_MASTER_SEND_MODE | I2C_REPEATE_MODE));
I2C_sendStartCondition (I2CA_BASE);

while (! (I2C_getStatus (I2CA_BASE)和 I2C_STS_REG_ACCESS_RDY);
I2C_putData (I2CA_BASE、regAddr);

while (! (I2C_getStatus (I2CA_BASE)和 I2C_STS_TX_DATA_RDY);

I2C_setSlaveAddress (I2CA_BASE、slaveAddr);
//设置要接收的字节数的数据计数
I2C_setDataCount (I2CA_BASE、count);
//设置接收模式的 I2C 配置
I2C_setConfig (I2CA_BASE、(I2C_MASTER_RECEIVE_MODE | I2C_REPEATE_MODE));
//发送重复启动条件
I2C_sendStartCondition (I2CA_BASE);

//------------------

//测试功能

//------------------
//进行实验以确保 I2C 正常工作
void prox_init()
开始传输(0x60);
写入(0x03);
写入(0xCE);
写入(0x08);
endTransmission ();
DEVICE_DELAY_US (300000);
开始传输(0x60);
写入(0x04);
写入(0x47);
写入(0x10);
endTransmission ();
DEVICE_DELAY_US (300000);

uint16_t read_proximity (){
uint16_t data_ret;

requestFrom (0x60、0x08、2);
读(k、2);
endTransmission ();

data_ret = data[0]<< 8;
data_ret +=数据[1];
返回 data_ret;



空 printPressure (){
uint16_t proxyData;


while (1){
proxyData = Read_Proximity ();
print_word (proxyData);
newline();
device_delay_us (500);


//------------------
//
//主要功能
//
//------------------

// MainMenu 将供用户选择要选择的选项
//这可以实现模块化测试功能,快速添加测试和使用其他
//测试以加快开发速度!
空 MainMenu()
{
//变量用于存储用户选择的内容。
uint8_t userChoice[1];

while (1)
{
// prox_init ();
// printPressure ();

newline();
sendMsg ("欢迎管理、到 WHSIP001 TMS320F28384D 测试板。"、52);
newline();
sendMsg ("请查看下面的菜单选项:"、34);
newline();
sendMsg ("1)向屏幕打印大气压力",42);
newline();
sendMsg ("2)将简单的消息打印到文本文件并保存在 SD 卡上"、60);
newline();
sendMsg ("3)扫描 I2C 总线以查找器件地址"、37);
newline();
DEVICE_DELAY_US (10000);

userChoice[0]= getChar();

if (userChoice[0]=='1'){
printPressure ();

if (userChoice[0]=='2'){


if (userChoice[0]=='3'){
printAvailable_I2C_Devices ();


//
//主菜单
//
空 main (void)
{

//
//初始化设备时钟和外设
//
device_init();

//
//禁用引脚锁定并启用内部上拉。
//
device_initGPIO();

//
//初始化 PIE 和清除 PIE 寄存器。 禁用 CPU 中断。
//
interrupt_initModule();

//
//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//
interrupt_initVectorTable();

//
// PinMux 和外设初始化
//
Board_init();

//
// C2000Ware 库初始化
//
// C2000Ware_libraries_init ();

//
//启用全局中断(INTM)和实时中断(DBGM)
//
EINT;
ERTM;

while (1)
{
prox_init();
MainMenu();

配置代码:

//*****
//
// I2C 配置
//
//*****
void I2C_init()
VNCL_4040_init ();

void VNCL_4040_init (){
I2C_disableModule (VNCL_40_BASE);
I2C_initController (VNCL_4040_BASE、DEVICE_SYSCLK_FREQ、200000、I2C_DUTYCYCLE_50);
I2C_setConfig (VNCL_4040_BASE、I2C_CONTROL_SEND_MODE);
I2C_setTargetAddress (VNCL_4040_BASE、96);
I2C_disableLoopback (VNCL_4040_BASE);
I2C_setBitCount (VNCL_4040_BASE、I2C_BITCOUNT_8);
I2C_setDataCount (VNCL_4040_BASE、1);
I2C_setAddressMode (VNCL_4040_BASE、I2C_ADDR_MODE_7BITS);
I2C_disableFIFO (VNCL_40_BASE);
I2C_clearInterruptStatus (VNCL_4040_BASE、I2C_INT_REG_ACCESS_RDY | I2C_INT_RX_DATA_RDY | I2C_INT_STOP_Condition | I2C_INT_TX_DATA_RDY);
I2C_enableInterrupt (VNCL_40_BASE、I2C_INT_REG_ACCESS_RDY | I2C_INT_RX_DATA_RDY | I2C_INT_STOP_Condition | I2C_INT_TX_DATA_RDY);
I2C_setEmulationMode (VNCL_4040_BASE、I2C_emulation_free_run);
I2C_enableModule (VNCL_40_BASE);

//*****
//
// PinMux 配置
//
//*****
//
// GPIO167 - GPIO 设置
//
#define myBoardLED0_GPIO_PIN_CONFIG GPIO_167_GPIO167

//
// I2CA -> VNCL_4040引脚多路复用
//
//
// I2CA_SDA - GPIO 设置
//
#define GPIO_PIN_I2CA_SDA 0
#define VNCL_4040_I2CSDA_GPIO 0
#define VNCL_4040_I2CSDA_PIN_CONFIG GPIO_0_I2CA_SDA
//
// I2CA_SCL - GPIO 设置
//
#define GPIO_PIN_I2CA_SCL 1
#define VNCL_4040_I2CSCL_GPIO 1
#define VNCL_4040_I2CSCL_PIN_CONFIG GPIO_1_I2CA_SCL

//
// SCIA -> mySCI0引脚多路复用
//
//
// SCIA_RX - GPIO 设置
//
#define GPIO_PIN_SCIA_RX 43
#define mySCI0_SCIRX_GPIO 43
#define mySCI0_SCIRX_PIN_CONFIG GPIO_43_SCIA_RX
//
// SCIA_TX - GPIO 设置
//
#define GPIO_PIN_SCIA_TX 42
#define mySCI0_SCITX_GPIO 42
#define mySCI0_SCITX_PIN_CONFIG GPIO_42_SCIA_TX

//*****
//
// CPUTIMER 配置
//
//*****
#define Led_Toggle_Timer_ CPUTIMER0_BASE
void Led_Toggle_Timer_();

//*****
//
// GPIO 配置
//
//*****
#define myBoardLED0_GPIO 167
void myBoardLED0_GPIO_init ();

//*****
//
// I2C 配置
//
//*****
#define VNCL_4040_BASE I2CA_BASE
#define VNCL_4040_bitrate 200000
#define VNCL_4040_TARGET_ADDRESS 96
#define VNCL_4040_own_target_address 0
void VNCL_4040_init ();

//*****
//
//中断配置
//
//*****

// Led_Toggle_Timer 的中断设置
#define INT_TIMER0 INT_TIMER0 Led_Toggle_Timer
#define INT_RUPT_ACK_GROUP Led_Toggle_Timer_ INTERRUPT_ACK_GROUP1
extern _interrupt void INT_402 Led_Toggle_Timer_(void);

//*****
//
// SCI 配置
//
//*****
#define mySCI0_BASE SCIA_BASE
#define mySCI0_BAUDRATE 115200
#define mySCI0_CONFIG_WLEN SCI_CONFIG_WLEN_8
#define mySCI0_CONFIG_STOP SCI_CONFIG_STOP_ONE
#define mySCI0_CONFIG_PAR SCI_CONFIG_PAR_NONE
void mySCI0_init ();

//*****
//
//板配置
//
//*****
void Board_init();
void CPUTIME_INIT();
void GPIO_init();
void I2C_init();
void interrupt_init();
void sci_init();
void PinMux_init ();

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    很抱歉对该线程的响应出现延迟。  

    您提到同样的代码适用于 F2837xD 设备。  这表明软件没有问题。  

    您是否能够在示波器上监控 I2C 引脚以监控 I2C SDA 引脚?  

    此致

    西达尔特

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我同意、您一瞥可能会说软件没有问题、但是我的电路板硬件设计实际上只是芯片的简单分接板、 我只能将这些 I2C GPIO0和1引脚拔出到接头并将其连接到传感器、而不执行任何操作。 我在 SysConfig 工具中也启用了内部上拉。  

    测试板确实运行 LED 闪烁以及 SCI 转 USB 程序并正确打印到终端、因此我非常怀疑这是一个硬件问题、除非芯片有缺陷。

    以下是"扫描地址函数"期间的示波器屏幕截图。  


    void I2CBUS_scan (uint16_t * AvailableDevices)
    {
    //禁用中断
    I2C_disableInterrupt (I2CA_BASE、(I2C_INT_ADDR_SLAVE | I2C_INT_STOP_Condition | I2C_INT_ARB_LOSS| I2C_INT_NO_ACK));
    uint16_t Slave_Address、I;
    I = 0;
    //最多可连接128个 I2C 设备,承载7位地址

    对于(Slave_Address = 1;Slave_Address < 128;Slave_Address +)
    {
    //检查总线状态,成功时,它将返回0。 如果不等于0、则停止程序。
    状态= I2C_getStatus (I2CA_BASE);
    while (I2C_isBusy (I2CA_BASE);


    //配置 I2C
    I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE | I2C_REPEATE_MODE);
    I2C_setAddressMode (I2CA_BASE、I2C_ADDR_MODE_7BITS);
    I2C_setSlaveAddress (I2CA_BASE、Slave_Address);
    I2C_sendStartCondition (I2CA_BASE);
    //等待传输完成
    //状态应为"register-access-ready"以继续

    while (! (I2C_getStatus (I2CA_BASE)和 I2C_STS_REG_ACCESS_RDY);
    I2C_sendStopCondition (I2CA_BASE);
    //等待停止位被清零
    while (I2C_getStopConditionStatus (I2CA_BASE));
    ///等待 BUSY 位被清零 总线不应处于忙状态
    while (I2C_isBusy (I2CA_BASE));
    //获取 I2C 状态以查看它是否已得到从机应答
    状态= I2C_getStatus (I2CA_BASE);

    如果(!(STATUS 和 I2C_STS_NO_ACK))
    {
    AvailableDevices[i]= Slave_Address;
    I++;

    I2C_clearStatus (I2CA_BASE、I2C_STS_NO_ACK | I2C_STS_ARB_LOST | I2C_STS_REG_ACCESS_RDY| I2C_STS_STOP_Condition);

    I2C_setConfig (I2CA_BASE、(I2C_MASTER_SEND_MODE));
    I2C_enableInterrupt (I2CA_BASE、(I2C_INT_ADDR_SLAVE | I2C_INT_STOP_Condition | I2C_INT_ARB_LOSS| I2C_INT_NO_ACK));


    我突出显示了卡住的线条。 在执行此函数之前、范围如下所示:
    在我在主函数中执行此行之前、SDA 和 SCL 行为高电平:

    Board_init();

    这里是我的 board_init 文件:
    特别是 PIN_muxinit 功能、因为这是 SDA 和 SCL 线路变为低电平的位置。  

    void PinMux_init ()
    {
    //
    //分配给 CPU1的模块的 PinMux
    //

    // GPIO167 -> myBoardLED0_GPIO 引脚多路复用器
    GPIO_setPinConfig (GPIO_167_GPIO167);
    //
    // I2CA -> VNCL_4040引脚多路复用
    //
    GPIO_setPinConfig (VNCL_4040_I2CSDA_PIN_CONFIG);
    GPIO_setPadConfig (VNCL_4040_I2CSDA_GPIO、GPIO_PIN_TYPE_OD | GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (VNCL_4040_I2CSDA_GPIO、GPIO_QUAL_ASYNC);

    GPIO_setPinConfig (VNCL_4040_I2CSCL_PIN_CONFIG);
    GPIO_setPadConfig (VNCL_4040_I2CSCL_GPIO、GPIO_PIN_TYPE_OD | GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (VNCL_4040_I2CSCL_GPIO、GPIO_QUAL_ASYNC);

    //
    // SCIA -> mySCI0引脚多路复用
    //
    GPIO_setPinConfig (mySCI0_SCIRX_PIN_CONFIG);
    GPIO_setPadConfig (mySCI0_SCIRX_GPIO、GPIO_PIN_TYPE_STD | GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (mySCI0_SCIRX_GPIO、GPIO_QUAL_ASYNC);

    GPIO_setPinConfig (mySCI0_SCITX_PIN_CONFIG);
    GPIO_setPadConfig (mySCI0_SCITX_GPIO、GPIO_PIN_TYPE_STD | GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (mySCI0_SCITX_GPIO、GPIO_QUAL_ASYNC);




    此函数中的突出显示行分别为 SDA 和 SCL 变为低电平时的行。 一旦执行这些行、它们绝不会从低电平状态发生变化。