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.

[参考译文] EK-TM4C123GXL:I2C 忙位有问题

Guru**** 2548230 points
Other Parts Discussed in Thread: EK-TM4C123GXL

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1374433/ek-tm4c123gxl-problem-with-i2c-busy-bit

器件型号:EK-TM4C123GXL

工具与软件:

我是嵌入式编程新手、并且在 通过 I2C 连接两个 EK-TM4C123GXL 板来使 LED 闪烁时遇到问题。 I2C0引脚上连接了两个电路板、并且初始化已完成。 为了确认主板发送横截面、代码正在检查 BUSY 位的状态(而环路代码行) 98 )。 在调试时、我发现繁忙位永远不会变为0、因此代码停留在无限 while 循环中。 有人能帮忙吗?

主代码-

#include "TM4C123.h"                    // Device header
#include <stdio.h>


void I2C_Init(void);
void I2C0_Send(uint8_t slave_addr, char data);
void PORTF_Init(void);
void delay(void);
char I2C0_Recieve(uint8_t slave_addr);

#define RCGCI2C (((volatile unsigned long)(0x400FE000+0x620)))
#define RCGCGPIO (((volatile unsigned long)(0x400FE000+0x608)))
	
//PB2->SCL AND PB3->SDA
#define PORTB_BASE  0x40005000
#define PORTB_AFSEL_R  (((volatile unsigned long) (PORTB_BASE + 0x420)))
#define PORTB_PCTL_R   (((volatile unsigned long) (PORTB_BASE + 0x52C)))
#define PORTB_DIR_R    (((volatile unsigned long) (PORTB_BASE + 0x400)))
#define PORTB_DEN_R    (((volatile unsigned long) (PORTB_BASE + 0x51C)))
#define PORTB_DATA_R   (((volatile unsigned long) (PORTB_BASE + 0x3FC)))
#define PORTB_AMSEL_R  (((volatile unsigned long) (PORTB_BASE + 0x528)))
#define PORTB_ODR_R    (((volatile unsigned long) (PORTB_BASE + 0x50C)))


#define I2C0_BASE      (0x40020000)
#define I2C_MSA_R      (((volatile unsigned long) (I2C0_BASE + 0x00)))
#define I2C_MCS_R_R     (((volatile unsigned long) (I2C0_BASE + 0x004)))
#define  I2C_MCS_W_R    (((volatile unsigned long) (I2C0_BASE + 0x004)))
#define I2C_MDR_R        (((volatile unsigned long) (I2C0_BASE + 0x008)))
#define I2C_MTPR_R       (((volatile unsigned long) (I2C0_BASE + 0x00C)))
#define I2C_MCR_R       (((volatile unsigned long) (I2C0_BASE + 0x020)))
#define I2C_MBMON_R       (((volatile unsigned long) (I2C0_BASE + 0x02C)))

//#define I2C_SOAR_R       (((volatile unsigned long) (I2C0_BASE + 0x00C)))
#define PORTF_BASE    0x40025000
#define PORTF_DIR_R   (((volatile unsigned long) (PORTF_BASE + 0x400)))
#define PORTF_DEN_R   (((volatile unsigned long) (PORTF_BASE + 0x51C)))
#define PORTF_DATA_R  (((volatile unsigned long) (PORTF_BASE + 0x3FC)))
#define PORTF_AFSEL_R (((volatile unsigned long) (PORTF_BASE + 0x420)))
#define PORTF_PCTL_R  (((volatile unsigned long) (PORTF_BASE + 0x52C)))
#define PORTF_AMSEL_R (((volatile unsigned long) (PORTF_BASE + 0x528)))


int main(){
char arr[3]={'G','B','G'};
I2C_Init();
PORTF_Init();
uint8_t ad=0x2C;
int i=0;
while(1){
	
      I2C0_Send(ad,arr[i]);
     char data=I2C0_Recieve(ad);
        if (data == 'R') {
            PORTF_DATA_R = 0x02; // Red LED on PF1
        } else if (data == 'G') {
            PORTF_DATA_R = 0x08; // Green LED on PF3
        } else if (data == 'B') {
            PORTF_DATA_R = 0x04; // Blue LED on PF2
        }
        i =i+1;
				if(i==3)
					i=0;
        delay();
}

} 

void I2C_Init(void){
  RCGCI2C|=0x01;
  RCGCGPIO|=0x02;

	PORTB_AFSEL_R|=0x0C;
	PORTB_ODR_R|=0x08;//open drain for data line
	PORTB_DEN_R|=0x0C;
	PORTB_PCTL_R|=0x3300;
	PORTB_AMSEL_R&=~0x0C;
	I2C_MCR_R=0x10;
	I2C_MTPR_R=7;//SET CLOCK 100KBPS
}
void PORTF_Init(void) {
    RCGCGPIO |= 0x20; // enable GPIO Port F clock
    PORTF_DIR_R = 0x0E; // PF1, PF2, and PF3 as output (LEDs)
    PORTF_DEN_R |= 0x0E; // digital enable PF1, PF2, and PF3
    PORTF_AFSEL_R &=~0x0E; // disable alternate function
    PORTF_PCTL_R &=~0xFFF0; // configure as GPIO
    PORTF_AMSEL_R &= ~0x0E; // disable analog function
	  
}

void I2C0_Send(uint8_t  slave_addr,  char data) {
	  while(I2C_MCS_R_R&0x01){};//wait unitt i2c0 is busy
    I2C_MSA_R = (slave_addr<<1)&0xFE;			// Set slave address 
			I2C_MSA_R&=~0x01;//specify a write operation
    I2C_MDR_R = data&0xFF; 
    I2C_MCS_W_R = 0x07; // Start, Run, and Stop conditions

    while (I2C_MCS_R_R& 0x01==1) {}; // Wait for the transmission to complete
		// I2C_MCS_R_R&(0x0D);
}

char I2C0_Recieve(uint8_t slave_addr){
    while(I2C_MCS_R_R&0x01){};//wait unitt i2c0 is busy
		 I2C_MSA_R = (slave_addr<<1)&0xFE;			// Set slave address 
			I2C_MSA_R|=0x01;//specify a read operation
		I2C_MCS_W_R = 0x07; // Start, Run, and Stop conditions
		while (I2C_MCS_R_R& 0x01) {};//busy bit
		return (char)I2C_MDR_R & (0xFF);
}

void delay(void) {
    unsigned long i = 8000000;
    while (i > 0) {
        i--;
    }
}

从机代码-

#include "TM4C123.h"                    // Device header
#include <stdio.h>


void I2C_Init(void);
void slave_Send(char data);
void PORTF_Init(void);
void delay(void);
char slave_Recieve(void);

#define RCGCI2C (((volatile unsigned long)(0x400FE000+0x620)))
#define RCGCGPIO (((volatile unsigned long)(0x400FE000+0x608)))
	
//PB2->SCL AND PB3->SDA
#define PORTB_BASE  0x40005000
#define PORTB_AFSEL_R  (((volatile unsigned long) (PORTB_BASE + 0x420)))
#define PORTB_PCTL_R   (((volatile unsigned long) (PORTB_BASE + 0x52C)))
#define PORTB_DIR_R    (((volatile unsigned long) (PORTB_BASE + 0x400)))
#define PORTB_DEN_R    (((volatile unsigned long) (PORTB_BASE + 0x51C)))
#define PORTB_DATA_R   (((volatile unsigned long) (PORTB_BASE + 0x3FC)))
#define PORTB_AMSEL_R  (((volatile unsigned long) (PORTB_BASE + 0x528)))
#define PORTB_ODR_R    (((volatile unsigned long) (PORTB_BASE + 0x50C)))


#define I2C0_BASE      (0x40020000)
#define I2C_SOAR_R      (((volatile unsigned long) (I2C0_BASE + 0x800)))
#define I2C_SCS_R_R     (((volatile unsigned long) (I2C0_BASE + 0x804)))
#define  I2C_SCS_W_R    (((volatile unsigned long) (I2C0_BASE + 0x804)))
#define I2C_SDR_R        (((volatile unsigned long) (I2C0_BASE + 0x808)))
#define I2C_MCR_R       (((volatile unsigned long) (I2C0_BASE + 0x020)))
	
#define PORTF_BASE    0x40025000
#define PORTF_DIR_R   (((volatile unsigned long) (PORTF_BASE + 0x400)))
#define PORTF_DEN_R   (((volatile unsigned long) (PORTF_BASE + 0x51C)))
#define PORTF_DATA_R  (((volatile unsigned long) (PORTF_BASE + 0x3FC)))
#define PORTF_AFSEL_R (((volatile unsigned long) (PORTF_BASE + 0x420)))
#define PORTF_PCTL_R  (((volatile unsigned long) (PORTF_BASE + 0x52C)))
#define PORTF_AMSEL_R (((volatile unsigned long) (PORTF_BASE + 0x528)))


int main(){
char arr[3]={'G','B','R'};
I2C_Init();
PORTF_Init();
int i=0;
PORTF_DATA_R=0;
while(1){
     
     char data=slave_Recieve();
        if (data == 'R') {
            PORTF_DATA_R = 0x02; // Red LED on PF1
        } else if (data == 'G') {
            PORTF_DATA_R = 0x08; // Green LED on PF3
        } else if (data == 'B') {
            PORTF_DATA_R = 0x04; // Blue LED on PF2
        }
		  slave_Send(arr[i]);
        i =i+1;
				if(i==3)
					i=0;
}

} 

void I2C_Init(void){
   RCGCI2C|=0x01;
   RCGCGPIO|=0x02;

	PORTB_AFSEL_R|=0x0C;
	PORTB_ODR_R|=0x08;
	PORTB_DEN_R|=0x0C;
	PORTB_PCTL_R|=0x3300;
	
	I2C_MCR_R=0x20;//slave mode is on
	I2C_SOAR_R=0x2C;//setting its address
	I2C_SCS_W_R=0x01;//enable slave
}
void PORTF_Init(void) {
    RCGCGPIO |= 0x20; // enable GPIO Port F clock
    PORTF_DIR_R = 0x0E; // PF1, PF2, and PF3 as output (LEDs)
    PORTF_DEN_R |= 0x0E; // digital enable PF1, PF2, and PF3
    PORTF_AFSEL_R &=~0x0E; // disable alternate function
    PORTF_PCTL_R &=~0xFFF0; // configure as GPIO
    PORTF_AMSEL_R &= ~0x0E; // disable analog function
	  
}

void slave_Send( char data) {
	  while(I2C_SCS_R_R&0x02==0){}//wait unittl MASTER IS NOT READY
	  I2C_SDR_R=data;		
}

char slave_Recieve(void){
	while(I2C_SCS_R_R&0x01==0){}//wait while data is not sned
		return (char) I2C_SDR_R&0xFF;
}

void delay(void) {
    unsigned long i = 8000000;
    while (i > 0) {
        i--;
    }
}

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

    您好!

     我有三条评论。

     首先、有没有充分的理由可以说明您为什么不使用 TivaWare SDK?  您正在使用 DRM (直接寄存器操作)代码。 TivaWare SDK 包含具有 API 的 I2C 驱动程序、可显著简化软件开发。 此外、还有一些您可以参考的示例。 您可以在以下目录中找到示例。 如常见问题解答#4 https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/695568/faq-faqs-for-tm4c-arm-cortex-m4f-microcontrollers 中所示、 我们不支持 DRM 编码样式。 如果您必须使用 DRM、请至少参考 TivaWare API 源代码以查看寄存器的配置和初始化方式。  

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c123gxl-boostxl-sensub\humidity_sht21_simple

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripherals\i2c

     其次、当您将两个板连接在一起时、您必须在 SDA 和 SCL 总线上都有外部上拉电阻器(例如4.7k Ω)。 如果没有上拉电阻器、它们将无法工作、因为这是 I2C 协议的一项要求。  

     第三、我强烈建议您使用逻辑分析仪或至少使用示波器来探测信号。 逻辑分析仪可轻松显示总线上输出的内容并揭示哪些内容不起作用。