【问题标题】:Communucation between 2 stm322个stm32之间的通信
【发布时间】:2019-03-23 13:51:40
【问题描述】:

我正在尝试用 I2C 通信 2 个 STM32。我的配置如下:

7位寻址模式(无双地址,只有OAR1)

100khz 速度

ACK 启用(在从机上)

ACK 禁用(在主机上,因为任何时候在主机/从机之间只传输 1 个字节)

在主/从机上,使用 GPIOB (PB6) 作为 SCL 作为 AF,使用 GPIOB (PB7) 作为 SDA 作为 AF。问题出在哪里?

主码:

#include "stm32f10x.h" // Device header #include "delay.h"

void pinConfig(void);

void i2c_Master_Config(void);

void sendData(uint8_t data);

int main() {

    delay_init();
    pinConfig();
    i2c_Master_Config();

    while(1)
    {
        uint8_t butonState=GPIOA->IDR & 0x00001000; 
        sendData(0x68,butonState);
        delay_ms(10);
    }
}

void pinConfig() {

    RCC->APB1ENR |=1<<21;//Enable I2C 1 clock
    RCC->APB2ENR   |=1<<2;//Enable GPIOA clock
    RCC->APB2ENR   |=1<<3;//Enable GPIOB clock 
    RCC->APB2ENR   |=1<<0;//Enable AFIO clock

    GPIOA->CRL |= 0x00008000; //PA3 button pull-down 
    GPIOB->CRL = 0xFF000000; //SCL and SDA  AF Open Drain  SCL => PB6  SDA     =>PB7
}

void i2c_Master_Config() {

    I2C1->CR2    |=1<<5; //36 Mhz peripheral clock.
    I2C1->CR2    |=1<<2; //36 Mhz peripheral clock.
    I2C1->CCR     =0x28;//100 khz clock  
    I2C1->TRISE   =9;//1/8MHZ= 125 ns  => 1000ns/125ns =8  => 8+1 =9
    I2C1->CR1     |=(1<<0);//Peripheral enable..
}

void sendData(uint8_t data) {
    volatile int temp;

    while(I2C1->SR2 &(1<<1));//BUSY bit.
    I2C1->CR1  |=1<<8;//START bit.
    while(!(I2C1->SR1 & (1<<0))); //wait until start flag is set

    I2C1->DR  = slaveAdres<<1;//7 bit adress.

    while(!(I2C1->SR1 &(1<<1)));//wait until addr flag is set
    gecici=I2C1->SR2;//clear addr flag.

    I2C1->DR = data; 
    while (!(I2C1->SR1 & (1<<7))){} //wait until txe is set

    while (!(I2C1->SR1 & (1<<2)));//BTF(Byte transfer finished)=1 . 
    I2C1->CR1 |= 1<<9;//STOP bit.
    I2C1->CR1     &=~(1<<0);//Peripheral disable.
}

从机代码:

#include "stm32f10x.h" // Device header

void pinConfig(void);

void i2c_Slave_Config(void);

uint8_t readData(void);

uint8_t data;

int main()
{

    pinConfig();
    i2c_Slave_Config();

    while(1)
    {
        data=readData();

        if(data==0)
            GPIOB->BSRR |=1<<3;
        else if(data==1)
            GPIOB->BRR  |=1<<3;
    }
}

void pinConfig()
{

    RCC->APB1ENR |=1<<21;//I2C 1 Clock Aktif.
    RCC->APB2ENR   |=1<<2;//Enable GPIOA clock
    RCC->APB2ENR   |=1<<3;//Enable GPIOB clock 
    RCC->APB2ENR   |=1<<0;//Enable AFIO clock

    GPIOA->CRL |= 0x00002000; //PA3 led.
    GPIOB->CRL = 0xFF000000; //SCL and SDA  AF Open Drain  SCL => PB6  SDA   =>PB7
    GPIOA->BSRR |=1<<3;//Turn off the led.
}

void i2c_Slave_Config() {

    RCC->APB1ENR |=1<<21;//I2C 1 Clock Enable.
    I2C1->CR2    |=1<<5; //36 Mhz peripheral clock.
    I2C1->CR2    |=1<<2; //36 Mhz peripheral clock.
    I2C1->CCR     =0x28;//100 khz clock  
    I2C1->OAR1    &=~(1<<15);//7-bit slave adress.
    I2C1 ->CR1     |= 1<<10;//ACK enable.

    //0x68 Slave Adress Configured.    
    I2C1 ->OAR1   &=~(1<<1);
    I2C1 ->OAR1   &=~(1<<2);
    I2C1 ->OAR1   &=~(1<<3);
    I2C1 ->OAR1   &=~(1<<5);
    I2C1 ->OAR1   |=(1<<4);
    I2C1 ->OAR1   |=(1<<6);
    I2C1 ->OAR1   |=(1<<7);
    //0x68 Slave Adress Configured.
}

uint8_t readData()
{
    volatile int temp;
    uint8_t data;

    I2C1->CR1     |=(1<<0);//Peripheral enable.

    while(I2C1->SR2 &(1<<1));//BUSY bit.
    I2C1->CR1  |=1<<8;//START bit.
    while(!(I2C1->SR1 & (1<<0))); // wait until start flag is set.

    while(!(I2C1->SR1 &(1<<1)));// wait until addr flag is set
    temp=I2C1->SR2;//clear addr .

    while (!(I2C1->SR1 & (1<<6))){} // wait until rxne is set
    data=I2C1->DR;

    while (!(I2C1->SR1 & (1<<4))){} // wait until STOPF is set
    gecici=I2C1->SR1;

    I2C1->SR1 |=1<<9;

    I2C1->CR1     &=~(1<<0);//Peripheral disable.
    return data;
}

地址不匹配。我没有看到示波器上的 SDA 和 SCL 信号有任何响应。我使用 4.7kohms 将 SCL 和 SDA 都拉到 3.3v 每一行。(STM32F103C6)。

【问题讨论】:

  • 请注意编码。逐位设置地址不方便且繁琐。只需分配寄存器I2C1-&gt;OAR1 = (0x68 &lt;&lt; 1);,包括I2C_OAR1_ADDMODE 在内的所有其他位都将被自动清除。

标签: stm32 i2c


【解决方案1】:

目前主 I2C 模块在 i2c_Master_Config() 的主启动时启用,然后在 sendData() 结束时禁用,并且再也不会启用。

从 I2C 模块在readData() 开始时启用并在结束时禁用。

这对于中断的通信来说已经足够了。 I2C 外围模块应该一直启用(直到你明白什么时候应该禁用它)。

附言抱歉,我没有深入分析您的代码——大量“幻数”而不是助记符位名称使分析变得困难。也许,还有其他错误。

【讨论】:

  • 你好,我已经按照你说的做了。但是没有用。你能帮帮我吗?
  • @IlkerAykut 抱歉,我使用 STM32F103 和 I2C,但我从未在 STM32F 上使用 I2C,所以我的回答只是“常识”。请使用当前代码状态更新您的帖子。也许,我会在周末找点时间来回答这个问题。
  • 我正在研究 Proteus,但地址不匹配。会不会是因为 Proteus?
  • 有什么帮助吗?
猜你喜欢
  • 2021-12-11
  • 2019-08-30
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 2014-11-14
  • 2017-12-15
  • 1970-01-01
  • 2016-12-29
相关资源
最近更新 更多