微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 哪位大神用stm8s003做IIC的从机?

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

时间:10-02 整理:3721RD 点击:
为什么主一直写正常,一直读也正常,但是写过之后再读,第一次读到的是0XFF,第二次读到的数据才是正确的呢?不知有哪位大神遇见过这个问题,指点一下

你写和读的时间间隔长一点  是不是时序乱了

时序没有乱的,下面是用示波器抓到的波形


这是gpio模拟的iic还是硬件IIC?

主是模拟,从是stm8s的硬件

有示波器就好办了  你看看 收到0XFF的时候 读和写的地址对不对 还有看看应答

模拟端口IIC,还是003内设的IIC

003的内部外设寄存器,读出的时候,需要清掉寄存器的缓冲数据,还有可能是应答位接收不到造成的问题

从用的是硬件IIC

这个缓冲区需要怎么清呢?

第一次读数据的时候应答不对

看到的波形,第一次读应答不对

应答不对 那应该就是你发的不对  要么数据不对 要么时序不对  

I2C_DR数据寄存器,I2C_TRISE上升时间寄存器,这两个看下有没有配对,还有就是模拟I2C跟硬件的I2C终究是有点区别的,如果不行的话,不用硬件的I2C,把两个端口做成模拟电平通信就OK了

嗯,我再查查,但是不明白的是连续读两次,第二次就正确

嗯,我再调试一下

不错,真是太棒了!

//*******************硬件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);
        }
}

大神,帮我看一下硬件IIC主从程序,不知道是不是哪个标志没有清,还是不行的,多谢了

在不?你的程序能给我发一份不?我现在调试从机的话,只能接收一个字节,如果想一次接收多个字节的话,在完成第一个字节的接收后 SR1的STOP会置位。不知道是什么问题

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top