你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

正在使用stm8作为从机与esp32进行i2c通讯,但是发现主机扫描的i2c地址与stm8从机设置的i2c地址不一样,请问如何解决?

[复制链接]
Troy-_Wong 提问时间:2024-10-24 10:51 / 未解决

这个是stm8从机代码

===



#include <Arduino.h>
// #include <stm8s.h> // 假设你使用了STM8标准库
// #include "i2c_slave.h"
#include "Wire.h"
#define I2C_SLAVE_ADDR 0x30

#define I2C_DATA_SIZE 8

#if ((I2C_DATA_SIZE > 0) && ((I2C_DATA_SIZE & (I2C_DATA_SIZE - 1)) != 0))
#error I2C_DATA_SIZE isnt a power of 2.
#endif

#define uint8_bits_def(x)         \
  union                           \
  {                               \
    unsigned char x;              \
    struct                        \
    {                             \
      unsigned char x##_Bit0 : 1, \
          x##_Bit1 : 1,           \
          x##_Bit2 : 1,           \
          x##_Bit3 : 1,           \
          x##_Bit4 : 1,           \
          x##_Bit5 : 1,           \
          x##_Bit6 : 1,           \
          x##_Bit7 : 1;           \
    };                            \
  }

uint8_bits_def(tagI2C);
uint8_t i2c_addr = 0;
uint8_t i2c_data[I2C_DATA_SIZE] = {0x00};
int tagI2C_Bit0 = 0;

// // I2C中断服务处理函数声明
// void I2C_ISR(void) __interrupt(19); // I2C中断向量号

void Serial_print(const char *str)
{
  while (*str)
  {
    Serial_write(*str++); // 逐个字符发送
  }
}

void I2C_Slave_IRQHandler(void)
{
  volatile I2C_Event_TypeDef Event = I2C_GetLastEvent();
  Serial_print("STM8 I2C_Slave_IRQHandler.");
  /* Slave address matched with the address sent by master */
  /* EV1: ADDR = 1, 顺序读SR1,SR3寄存器清除此标志位 */
  if (Event == (I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED))
  {
    tagI2C_Bit0 = 1;
  }
  /* Slave received the data byte from master */
  /* EV2: RxNE = 1, 读DR寄存器清除此位 */
  else if (Event == (I2C_EVENT_SLAVE_BYTE_RECEIVED))
  {
    uint8_t ch = I2C_ReceiveData();
    if (tagI2C_Bit0)
    {
      tagI2C_Bit0 = 0;
      i2c_addr = ch;
    }
    else
    {
      i2c_data[i2c_addr++ & (I2C_DATA_SIZE - 1)] = ch;
    }
  }
  /* Slave received STOP byte from master */
  /* EV4: STOPF = 1,读SR1寄存器后再写CR2清除 */
  else if (Event == (I2C_EVENT_SLAVE_STOP_DETECTED))
  {
    I2C_GetFlagStatus(I2C_FLAG_STOPDETECTION);
    I2C_GenerateSTOP(DISABLE);
  }
  /* SLAVE TRANSMITTER */
  /* Data transmited from slave to master */
  /* EV3: TxE = 1, 写DR寄存器清除DR */
  else if ((Event == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED)) ||
           (Event == (I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED)))
  {
    uint8_t ch = i2c_data[i2c_addr++ & (I2C_DATA_SIZE - 1)];
    I2C_SendData(ch);
  }
  /* Acknowledge failure */
  /* EV3-2: AF = 1, AF is cleared by writing '0' in AF bit of SR2 register */
  else if (Event == (I2C_EVENT_SLAVE_ACK_FAILURE))
  {
    I2C_ClearFlag(I2C_FLAG_ACKNOWLEDGEFAILURE);
  }
}

// INTERRUPT_HANDLER(I2C_IRQHandler, 19)
// {
//   I2C_Slave_IRQHandler();
// }

void I2C_Slave_Init(void)
{
  // open I2C clk
  CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
  I2C_DeInit();
  I2C_Init(50000, I2C_SLAVE_ADDR, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, (CLK_GetClockFreq() / 1000000));
  /* Enable Error Interrupt*/
  I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE);
  /* enable IIC*/
  I2C_Cmd(ENABLE);
  // enableInterrupts();
}
void setup()
{
  // 初始化串口通信,波特率为9600
  Serial_begin(9600);

  // 给串口输出一条消息,表示系统已经启动
  Serial_print("STM8 initialized and ready.");

  I2C_Slave_Init();

  // pid_i2c_init();
}

void loop()
{
}

这个是esp32主机代码

===

#include <Arduino.h>
#include "Wire.h"
uint32_t I2C2_SPEED = 50000;
void setup()
{
  Serial.begin(115200);
  Wire.begin(21, 22, I2C2_SPEED);
}

void loop()
{
  byte error, address;
  int nDevices = 0;

  delay(3000);

  Serial.println("Scanning for I2C devices ...");
  for (address = 0x01; address < 0x7f; address++)
  {
    Wire.beginTransmission(address);
    // Wire.write(0x11);
    error = Wire.endTransmission();
    if (error == 0)
    {
      Serial.printf("I2C device found at address 0x%02X\n", address);
      nDevices++;
    }
    else if (error != 2)
    {

      Serial.printf("Error %d at address 0x%02X\n", error, address);
    }
  }
  if (nDevices == 0)
  {
    Serial.println("No I2C devices found");
  }
}
esp32 debug:
Scanning for I2C devices ...
I2C device found at address 0x18
Scanning for I2C devices ...
I2C device found at address 0x18
Scanning for I2C devices ...
I2C device found at address 0x18

当esp32扫描到这个i2c地址后stm8会重启,当前不知道是什么原因导致的
收藏 评论6 发布时间:2024-10-24 10:51

举报

6个回答
butterflyspring 回答时间:2024-10-25 11:00:02
通常可以调试看看地址寄存器的内容是否是设置的地址,同时看看响应时的寄存器标志位 ADDR 是否置位。


另外STM8速度通常只有16Mhz,响应中断要尽可能快,所以最好优化中断执行时间,可参考一下例程。
Troy-_Wong 回答时间:2024-10-26 11:48:43

butterflyspring 发表于 2024-10-25 11:00
通常可以调试看看地址寄存器的内容是否是设置的地址,同时看看响应时的寄存器标志位 ADDR 是否置位。</p>
<p>

`当esp32扫描到这个i2c地址后stm8会重启,这个重启会是什么原因导致的呢,而且debug一点报错都没有,stm直接是重启了,只要主机扫描到i2c设备从机stm8就重启了

Troy-_Wong 回答时间:2024-10-26 12:00:12

Troy-_Wong 发表于 2024-10-26 11:48
`当esp32扫描到这个i2c地址后stm8会重启,这个重启会是什么原因导致的呢,而且debug一点报错都没有, ...

[md]请问下有stm8作为从设备的案例吗

butterflyspring 回答时间:2024-10-28 09:49:05

Troy-_Wong 发表于 2024-10-26 12:00
请问下有stm8作为从设备的案例吗

有的,在标准外设库里,注意中断尽可能快些。优先级高。

stm8sfwlib2.31\STM8S_StdPeriph_Lib\Project\STM8S_StdPeriph_Examples\I2C\I2C_TwoBoards\I2C_DataExchange\Slave

Troy-_Wong 回答时间:2024-10-31 17:56:44

butterflyspring 发表于 2024-10-28 09:49
有的,在标准外设库里,注意中断尽可能快些。优先级高。</p>
<p>

我试过这个案例,stm8 作为从机,但是主机一旦扫描到从机的i2c地址后,stm8就会自动重启。如果stm8作为主机的话扫描其它从机则不会出现重启现象,请问这个如何解决呢

butterflyspring 回答时间:2024-11-4 14:28:05
Troy-_Wong 发表于 2024-10-31 17:56
[md]我试过这个案例,stm8 作为从机,但是主机一旦扫描到从机的i2c地址后,stm8就会自动重启。如果stm8作 ...

这个现象很奇怪,需要调试看看。


1. 可以简化I2C 中断内容,看看是否还会重启。

2. REST 有个状态寄存器,首次上电清零,然后复位后判断输出看看是什么复位标志置位起来的。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版