哪位大神用stm8s003做IIC的从机?

2019-07-14 19:51发布

为什么主一直写正常,一直读也正常,但是写过之后再读,第一次读到的是0XFF,第二次读到的数据才是正确的呢?不知有哪位大神遇见过这个问题,指点一下
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
18条回答
风_轻_云淡
1楼-- · 2019-07-16 17:54
hobbye501 发表于 2017-3-15 08:20
应答不对 那应该就是你发的不对  要么数据不对 要么时序不对

嗯,我再查查,但是不明白的是连续读两次,第二次就正确
风_轻_云淡
2楼-- · 2019-07-16 22:29
SXST_T 发表于 2017-3-15 09:04
I2C_DR数据寄存器,I2C_TRISE上升时间寄存器,这两个看下有没有配对,还有就是模拟I2C跟硬件的I2C终究是有点区别的,如果不行的话,不用硬件的I2C,把两个端口做成模拟电平通信就OK了

嗯,我再调试一下
idianze
3楼-- · 2019-07-17 01:40
 精彩回答 2  元偷偷看……
风_轻_云淡
4楼-- · 2019-07-17 06:00
//*******************硬件IIC从测试程序******************/
#include "stm8s.h"

#define SLAVE_ADDRESS 0xA0

void main(void)
{

  /* system_clock / 1 */
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
  
  I2C_DeInit();
  /* Initialize I2C peripheral */
  I2C_StretchClockCmd(DISABLE);
  I2C_Init(100000, SLAVE_ADDRESS, I2C_DUTYCYCLE_16_9, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16);           
  /* Enable Error Interrupt*/
  I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE);
  /* Enable general interrupts */
  enableInterrupts();
  /*Main Loop */
  while (1)
  {
    /* infinite loop */
  }
}
/------------------------------------------------------------------------------------
下面是中断函数
------------------------------------------------------------------------------------/
unsigned char Slave_Buffer_Rx[10];

INTERRUPT_HANDLER(I2C_IRQHandler, 19)
{
  static unsigned char reg_slave = 0;
static unsigned char rx_count = 0;
  /* Read SR2 register to get I2C error */
  if ((I2C->SR2) != 0)
  {
    /* Clears SR2 register */
    I2C->SR2 = 0;
  }
  Event = I2C_GetLastEvent();
  switch (Event)
  {
      /******* Slave transmitter ******/
      /* check on EV1 */
    case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
      break;

      /* check on EV3 */
    case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:
      /* Transmit data */
      I2C_SendData(Slave_Buffer_Rx[reg_slave]);
      break;
      /******* Slave receiver **********/
      /* check on EV1*/
    case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
    rx_count = 1;
      break;

      /* Check on EV2*/
    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
   if(rx_count == 1)  
  {       
        reg_slave = I2C_ReceiveData();
       rx_count = 2;
  }
else if(rx_count == 2)  
{
        Slave_Buffer_Rx[reg_slave] = I2C_ReceiveData();
       rx_count  = 0;
}      
    break;

      /* Check on EV4 */
    case (I2C_EVENT_SLAVE_STOP_DETECTED):
            /* write to CR2 to clear STOPF flag */
            I2C->CR2 |= I2C_CR2_ACK;
      break;

    default:
      break;
  }

}


//*******************硬件IIC主测试程序******************//
#include "stm8s.h"

#define EEPROM_ADDRESS         0xA0
#define Fsys  16000000

void Delay_ms(unsigned int mm)
{
unsigned int mm2,mm1=Fsys/6000;
while(mm--)
for(mm2=mm1;mm2>0;mm2--);
}

void I2C_Config(void)
{
  I2C_DeInit();
        I2C_Init(100000, 0xB0, I2C_DUTYCYCLE_16_9, I2C_ACK_CURR,  I2C_ADDMODE_7BIT, 16);
        CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
        I2C_Cmd(ENABLE);
}

/*******************************************************************************
* 名称: I2C_EEPROM_WriteOneByte
* 功能: I2C主模式往I2C从器件内部地址写一个字节
* 形参: WriteAddr  Byte
* 返回: 无
* 说明:
*/
void I2C_WriteOneByte(u8 WriteAddr,u8 Byte)
{
        /* 等待空闲 */
        //while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
        while((I2C->SR3 & 0x02 ) != 0);
       
        /* 发起始位 */
        //I2C_GenerateSTART(ENABLE);       
        I2C->CR2 |= 0x01;
        /* 测试EV5 ,检测从器件返回一个应答信号*/
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
       
        /* 设置I2C从器件地址,I2C主设备为写模式*/
        I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);       
        /* 测试EV6并清除标志位,检测从器件返回一个应答信号 */
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
         
        /* 设置往从器件写数据内部的地址 */
        //I2C_SendData(WriteAddr);
        I2C->DR = WriteAddr;
        /* 测试EV8并清除标志位 ,检测从器件返回一个应答信号*/
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING));
       
        /* 向从器件写一个字节 */
        //I2C_SendData(Byte);
        I2C->DR = Byte;
        /* 测试EV8_2并清除标志位,检测从器件返回一个应答信号 */
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
       
        /* 发结束位 */
        //I2C_GenerateSTOP(ENABLE);
        I2C->CR2 |= 0x02;
}

/*************************************************************************
* 名称: I2C_EEPROM_ReadOneByte
* 功能: 从从设备读取一个字节
* 形参: ReadAddr
* 返回: 字节数据
* 说明: 无
*/
u8 I2C_ReadOneByte(u8 ReadAddr)
{
        u8 RxData;
        /* 等待空闲 */
        //while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
        while((I2C->SR3 & 0x02 ) != 0);
        /* 发起始位 */
        //I2C_GenerateSTART(ENABLE);
        I2C->CR2 |= 0x01;
        /* 测试EV5 ,检测从器件返回一个应答信号*/
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
       
        /* 设置I2C从器件地址,I2C主设备为写模式*/
        I2C_Send7bitAddress(EEPROM_ADDRESS , I2C_DIRECTION_TX);       
        /* 测试EV6并清除标志位 */
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
       
        //I2C_SendData(ReadAddr);
        I2C->DR = ReadAddr;
        /* 测试EV8并清除标志位 */
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
       
        /* 发起始位 */
        //I2C_GenerateSTART(ENABLE);
        I2C->CR2 |= 0x01;
        /* 测试EV5 ,检测从器件返回一个应答信号*/
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
       
        /* 设置I2C从器件地址,I2C主设备为读模式*/
        I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_RX);
        /* 测试EV6 ,检测从器件返回一个应答信号*/
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
       
        //I2C_AcknowledgeConfig(I2C_ACK_NONE);//不使能应答
        I2C->CR2 &= 0xfb;
        /* 测试EV7,等待数据接收完毕 */
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED));
        //RxData=I2C_ReceiveData();
        RxData = ((uint8_t)I2C->DR);
       
        /* 发结束位*/
        //I2C_GenerateSTOP(ENABLE);
        I2C->CR2 |= 0x02;
        return RxData;
}



void main(void)
{
        unsigned char read_data;
                        /*配置内部16MHz时钟------------------------------*/
         CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
       
        I2C_Config();
        while(1)
        {
                I2C_WriteOneByte(5,0x11);
                read_data = I2C_ReadOneByte(5);
                Delay_ms(100);
        }

}
风_轻_云淡
5楼-- · 2019-07-17 11:02
SXST_T 发表于 2017-3-15 09:04
I2C_DR数据寄存器,I2C_TRISE上升时间寄存器,这两个看下有没有配对,还有就是模拟I2C跟硬件的I2C终究是有点区别的,如果不行的话,不用硬件的I2C,把两个端口做成模拟电平通信就OK了

大神,帮我看一下硬件IIC主从程序,不知道是不是哪个标志没有清,还是不行的,多谢了
602411570
6楼-- · 2019-07-17 12:31
在不?你的程序能给我发一份不?我现在调试从机的话,只能接收一个字节,如果想一次接收多个字节的话,在完成第一个字节的接收后 SR1的STOP会置位。不知道是什么问题

一周热门 更多>