STM32:I2C从机未启用时钟拉伸功能

STM32:I2C从机未启用时钟拉伸功能,stm32,i2c,master-slave,cortex-m,Stm32,I2c,Master Slave,Cortex M,我必须在STM32L053上实现一个I2C从机,以便在从机uC上读取/写入一些任意字节的内存,要求它也适用于不支持时钟拉伸的I2C主机(NOSTRETCH=1) 我在以下方面找到了一个很好的例子: 以下是本条的实施情况: 对于100KHz数据速率下的读取操作,这个实现对我来说没有问题,但是来自主机的写入操作在50%左右正常工作。有时写入的字节正确,有时不正确 这个例子和我的环境之间的区别是,尽管uC有点不同,但STM32L0仍然有偏差,我必须使用一个相当低的系统时钟,因为事实上,我还

我必须在STM32L053上实现一个I2C从机,以便在从机uC上读取/写入一些任意字节的内存,要求它也适用于不支持时钟拉伸的I2C主机(
NOSTRETCH=1

我在以下方面找到了一个很好的例子:

以下是本条的实施情况:

对于100KHz数据速率下的读取操作,这个实现对我来说没有问题,但是来自主机的写入操作在50%左右正常工作。有时写入的字节正确,有时不正确

这个例子和我的环境之间的区别是,尽管uC有点不同,但STM32L0仍然有偏差,我必须使用一个相当低的系统时钟,因为事实上,我还必须满足另一个低功耗的要求。我的uC运行频率为4Mhz,示例中的uC运行频率为32Mhz。 因此,我担心,这是因为我的系统时钟太慢,无法在ISR内足够快地从主机读取输入的写入数据,在接收到下一个输入数据之前

有没有人能给我一个提示,在我的4Mhz环境中是否有可能实现这样一个无时钟的I2C从机,如果有,我该怎么做才能使写操作也可靠地工作

以下是
NOSTRETCH=1
设置参考手册的说明:

以下是读/写功能和I2C ISR的实现:


volatile unsigned char i2c_mem[256];     /* contains data, which read or written */
volatile unsigned char i2c_idx;          /* the current index into i2c_mem */
volatile unsigned char i2c_is_write_idx; /* write state */

volatile uint16_t i2c_total_irq_cnt;
volatile uint16_t i2c_TXIS_cnt;
volatile uint16_t i2c_RXNE_cnt;


void i2c_mem_reset_write(void)
{
  i2c_is_write_idx = 1;  
}

void i2c_mem_init(void)
{
  i2c_idx = 0;
  i2c_mem_reset_write();
}

void i2c_mem_set_index(unsigned char value)
{
  i2c_idx = value;
  i2c_is_write_idx = 0;
}

void i2c_mem_write_via_index(unsigned char value)
{
  i2c_mem[i2c_idx++] = value;
}

unsigned char i2c_mem_read(void)
{
  i2c_mem_reset_write();
  i2c_idx++;
  return i2c_mem[i2c_idx];
}

void i2c_mem_write(unsigned char value)
{
  if ( i2c_is_write_idx != 0 )
  {
    i2c_mem_set_index(value);
  }
  else
  {
    i2c_is_write_idx = 0;
    i2c_mem_write_via_index(value);
  }
}

void __attribute__ ((interrupt, used)) I2C1_IRQHandler(void)
{
  unsigned long isr = I2C1->ISR;

  i2c_total_irq_cnt ++;

  if ( isr & I2C_ISR_TXIS )
  {
    i2c_TXIS_cnt++;
    I2C1->TXDR = i2c_mem_read();
  }
  else if ( isr & I2C_ISR_RXNE )
  {
    i2c_RXNE_cnt++;
    i2c_mem_write(I2C1->RXDR);
    I2C1->ISR |= I2C_ISR_TXE;           // allow overwriting the TCDR with new data
    I2C1->TXDR = i2c_mem[i2c_idx];
  }
  else if ( isr & I2C_ISR_STOPF )
  {
    I2C1->ICR = I2C_ICR_STOPCF;
    I2C1->ISR |= I2C_ISR_TXE;           // allow overwriting the TCDR with new data
    I2C1->TXDR = i2c_mem[i2c_idx];
    i2c_mem_reset_write();
  }
  else if ( isr & I2C_ISR_NACKF )
  {
    I2C1->ICR = I2C_ICR_NACKCF;
    I2C1->ISR |= I2C_ISR_TXE;           // allow overwriting the TCDR with new data
    I2C1->TXDR = i2c_mem[i2c_idx];
    i2c_mem_reset_write();
  }
  else if ( isr & I2C_ISR_ADDR )
  {
    /* not required, the addr match interrupt is not enabled */
    I2C1->ICR = I2C_ICR_ADDRCF;
    I2C1->ISR |= I2C_ISR_TXE;           // allow overwriting the TCDR with new data
    I2C1->TXDR = i2c_mem[i2c_idx];
    i2c_mem_reset_write();
  }

  /* if at any time the addr match is set, clear the flag */
  /* not sure, whether this is required */
  if ( isr & I2C_ISR_ADDR )
  {
    I2C1->ICR = I2C_ICR_ADDRCF;
  }

}

在你的硬件上,它能在32兆赫的频率下工作吗?您使用的是哪个gcc版本?是的,我刚刚尝试了32 MHz,无法再现任何写入错误。我使用的是新的STM32CubeIDE,它用作gcc:arm-none-eabi-gcc.exe(GNU Tools for STM32 7-2018-q2-update.20190328-1800)7.3.1 20180622(发布)[arm embedded-7-branch revision 261907]奇怪的是:我尝试了I2C时钟源的另一个设置,并将其从
RCC\u I2ClKSource\u PCLK1
(是4MHz MSI)更改为
RCC\u I2ClKSource\u HSI
(运行频率为16MHz),似乎在4MHz系统时钟下工作。是否I2C外设在这种操作模式下需要超过4Mhz的时钟?我测试了一些定时寄存器的组合,发现没有通信错误的积极变化仅仅来自将I2C外设时钟源从sysclock(4Mhz MSI)更改为HSI(16MHz)。有人知道为什么变通方法有效吗?可能是未记录的硬件故障/限制?