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.

[参考译文] TM4C123GH6PM:步骤调试和运行程序之间 I2C 上的不同结果

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/573802/tm4c123gh6pm-different-results-on-i2c-between-step-debugging-and-running-the-program

器件型号:TM4C123GH6PM

您好, 我有一个 Tiva C 微控制器、我正在进行一个使用 I2C 将 adxl 345加速计传感器与其连接的项目、我设法使用80MHz 的时钟并使用 PLL 将 I2C 模块的时钟设置为 100并且如果我使用分步调试是非常好的,但是,如果我运行程序,我会在 MDR 寄存器和从 MDR 寄存器读取数据的变量上得到零  

分步调试提供了清晰正确的结果我的问题是让程序运行时会给出全部零

如果我在调试之后尝试执行步骤,它将保持零,并且我必须断开传感器的电源并重新连接,以便它再次工作,我不知道为什么会发生这种情况? 时钟在80 MHz 时过大还是什么?  

我尝试过的内容:

我已经尝试添加一些软件延迟、作为每个读取和写入操作之间的分步调试、但它仍然不起作用、再次为我提供了零。  

这是我需要的代码

#include "tm4c123ghp6.h"
#include "stdint.h"

void EnableI2CModule0 (void);
uint8_t ReadRegister (uint8_t RegisterAddress);
void PLL_Init (void);
void WriteRegister (uint8_t RegisterAddress、uint8_t ReadRegister (uint8_t Data);void PLL_InAxis








(0x2);volatile inuint2 (0xax_ax_ax_ax2、in2);inuint2、inuint2、inuax_inuax_inis2 (0xax2);volatile inuint2、inuax_ax_inuint2、inisis register in2、in2、inuint2)
temp=ReadRegister (0x2D);
WriteRegister (0x31、0x0B);
temp=ReadRegister (0x31);
while (1)
{
X_Axis1=ReadRegister (0x32);
X_Axis2=ReadRegister (0x33);
Y_Axis1=ReadRegister (0x34);
Y_Axis2=ReadRegister (0x35);
Z_Axis1=ReadRegister (0x36);
Z_Axis2=ReadRegister (0x37);
}

void PLL_Init (void){
// 0)使用 RCC2
SYSCTL_RCC2_R |
在初始化

时、Z_AXIS2=ReadRegister (0x37);0 = SYSCTAL_RCC0002
~/ SYSCRCC2 / SYSCRCC0 = 0 = 0;0 = SYSCRCC00RCC2 / SYSCRCC2 / SYSCRCC2 / SYSCRCC0 = SYSCR0 = 0 / SYSCRCC0 / SYSCRCC2 / SYSCRCC2 / SYSCTRY/ SYSCRCC0 / SYSCRCC0 = SYSCRCC0 / RCC0 / SYSCRCC
+ 0x00000540;// 10101、配置16MHz 晶体
SYSCTL_RCC2_R &&~0x00000070;//配置主振荡器源
// 3)通过清除 PWRDN
SYSCTL_RCC2_R &&~0x00002000来激活 PLL;
// 4)设置所需的系统分频
器 sctL_RCC2_SY00000 |= 0x00002000;// 4) //使用400MHz PLL
SYSCTL_RCC2_R =(SYSCTL_RCC2_R&~ 0x1FC00000)//清除系统时钟分频器
+(4<<22); //配置80MHz 时钟
// 5)等待 PLL 通过轮询 PLLLRIS 锁定
while ((SYSCTL_RIS_R&0x00000040)=0){};//等待 PLLRIS 位
// 6)通过清除 BYPASS
SYSCTL_RCC2_R &&~0x00000800;



// RCGC0 =
0 = SYSCTl EMPTY
0 = SYSCTRC 0;SYSCTRC 0 = SYSCTLET 0 = 0 = SYSCTRI 0 = 0 = SYSCTRI 0 = SYSCTRI 0 = 0 = 0 = 0;SYSCTRI 0 = 0 = 0 = 0 = 0 = 0 = 0 = 0 = 0 = 0 = 0 = 0 = 0 = 0 = 0 =空
//延迟允许时钟稳定
SYSCTL_RCGCGPIO_R |=0x00000002;//i2c 模块0是端口 B、因此激活端口 B 的时钟
DELAY = SYSCTL_RCGCGPIO_R;//延迟允许时钟稳定
GPIO_PORTB_AFSEL_R|= 0x0000000C;//启用 PB2和 PBCF_DR_8的备用功能
| GPIO_SET
= 0xTB_DR_8;//设置 GPIO_DR_DR_8 //启用端口 B
GPIO_PORTB_PCTL_R 上的数字|=0x03;
I2C0_PP_R |= 0x01;
I2C0_MTPR_R |= 0x00000027;//设置 SCL 时钟
I2C0_MCR_R |= 0x00000010;//将 MCR





寄存器与数据表中给出的值进行初始化};{=uint8_uint8_r 读写操作;/uint8 = I2cr 读写寄存器0xu_u_u_A6; //将数据放置到发送 MDR 寄存器
I2C0_MCS-78_R = 0x00000007;//停止运行
while ((I2C0_MCS-78= 0x00000040)=1);//轮询忙位
I2C0_MSC_R = 0x000000A7;//读取操作
I2C0_MCS-78_R = 0x00000007;//轮
询停止
/
中断= 0x00000040;
//结果= CMS_REST= 0x0000000;//结束

void WriteRegister (uint8_t RegisterAddress、uint8_t Data)
{
I2C0_MSA_R = 0x000000A6;//写入操作
I2C0_MDR_R = RegisterAddress;//将寄存器地址放置到 MDR 寄存器
I2C0_MCS-78_R = 0x00000003;//
轮询发送(多个字节)= 0x2C0_MCS = 0x00000003;
// while (I2C0_I2C0_EMC=0xBQ_0=0x0000_E= 0x0000.0_MFR=0x0000.000= 0x0000.000= 0x0000.000= 0x0000.000= 0x0000. //将要发送的数据放置在 MDR 寄存器
I2C0_MCS-78_R = 0x00000005;//发送后紧跟停止状态
while ((I2C0_MCS-78_R &= 0x00000040)=1);//轮询忙位
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    更新,我尝试在同一个时钟上更改分频值,但它给出了相同的错误! 所以我猜这是除数的问题,但是我看到这些值是正确的,它们是不是正确的?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Step by step debugging 提供了清晰正确的结果我的问题是让程序运行时会得到全零

    我的猜测是存在时序问题、因此代码不会等待 I2C 总线事务完成。

    我没有尝试完全理解代码、因为它是在直接寄存器模式(DRM)中写入的、具有寄存器字段的魔法编号、而不是更容易理解 TivaWare API。

    如果您想将 DRM 用于"学习"目的、建议您至少将 Tivaware hw_i2c.h 头文件中的宏用于寄存器字段。 例如、使用 I2C_MCS-78_BUSBY 而不 是0x00000040。

    代码中的一个错误是使用以下语句轮询忙位的结构:

    while ((I2C0_MCS-78_R &= 0x00000040)=1);//轮询忙位 

    使用&= 意味着代码会尝试修改只读 I2C 主控/状态寄存器、然后检查寄存器的值是否不是您想要的值、这意味着循环不会等到 I2C 总线空闲。

    尝试用以下方法替换总线忙时的轮询:

    while (((I2C0_MCS-78R & I2C_MCS-78_BUSBY)!=0);//轮询忙位 

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

    如果您在 while (I2C0_MCS-78_R&= 0x00000040)= 1之前放置了一个延迟循环100、那么它是否按预期工作?