stm32G031模拟iic从机+stm32f4模拟主机

以下例程链接:从机例程

主机例程:主机例程

从机部分

void I2cGpioIsr(void)
{
  uint32_t temp;
 
  // 处理SCL的上下沿中断
  if(__HAL_GPIO_EXTI_GET_IT(SW_SLAVE_SCL_PIN) != RESET)//检测scl触发的中断
  {
    __HAL_GPIO_EXTI_CLEAR_IT(SW_SLAVE_SCL_PIN);
    // 更新通信起始时间
     StartMs = HAL_GetTick();
    // SCL的下降沿事件处理,此时需要更新要传输的数据
		SCL_FLAG_IF = (SW_SLAVE_SCL_PRT->IDR & SW_SLAVE_SCL_PIN);
    if(SCL_FLAG_IF == (uint32_t)GPIO_PIN_RESET)
    {
      switch(State)
      {
        case I2C_STA_START:    // 起始信号的下降沿,初始化相关参数并转到接收比特数据状态
          SclFallCnt = 0;
          RxIdx = 0;
          TxIdx = 0;
          Flag = 0;  // 默认地址不匹配
          RxBuf[RxIdx] = 0;
          Rw = I2C_WRITE;  // 第1字节为设备地址,一定是写入
          State = I2C_STA_DATA;
          break;
        case I2C_STA_DATA:
          SclFallCnt++;
          if(8 > SclFallCnt)
          {
            // 如果是主机读取数据,则在SCL低电平时更新比特数据
            if(Rw == I2C_READ)
            {
              if(TxBuf[TxIdx] & (1 << (7 - SclFallCnt)))
              {
                SET_SDA_PIN();
              }
              else
              {
                CLR_SDA_PIN();
              }
            }
          }
          else if(8 == SclFallCnt)
          {
            if(Rw == I2C_WRITE)
            {
              // 从第一个地址字节中获取读写标志位,并判断地址是否匹配
              if(RxIdx == 0)
              {
								
                if((RxBuf[0] & 0xFE) == SW_SLAVE_ADDR)
                {
                   Flag = 1;  // 地址匹配
                  Rw =  RxBuf[0] & 0x01;
                }
								
              }
              if( Flag)
              {
                // 如果是主机写入数据,且地址匹配,则接收完8比特数据后,需要发送ACK信号进行应答
                SET_SDA_DIR(temp, GPIO_DIR_OUT);
                CLR_SDA_PIN();
              }
            }
            else
            {
              // 如果是主机读取数据,需要将SDA设置成输入以便判断应答标志位状态
              SET_SDA_DIR(temp, GPIO_DIR_IN);
              // 如果是主机读取数据,准备发送下一个字节的数据
               TxIdx++;
            }
            // 接收或发送完8比特数据后,准备发送或接收应答信号
             State = I2C_STA_ACK;
          }
          break;
        case I2C_STA_ACK:
           SclFallCnt = 0;
          if( Rw == I2C_WRITE)
          {
            // 如果是主机写入数据,且ACK发送完毕,则SDA设置成输入,继续接收数据
            SET_SDA_DIR(temp, GPIO_DIR_IN);
             RxIdx++;
             RxBuf[ RxIdx] = 0;
          }
          else
          {
            // 如果是主机读取数据,且ACK接收完毕,则SDA设置成输出,继续发送数据
            SET_SDA_DIR(temp, GPIO_DIR_OUT);
            if( TxBuf[ TxIdx] & 0x80)
            {
              SET_SDA_PIN();
            }
            else
            {
              CLR_SDA_PIN();
            }
          }
           State = I2C_STA_DATA;
          break;
        case I2C_STA_NACK:    // 如果收到了NACK,则后面将是STOP或者ReSTART信号,需要将SDA设置成输入
           SclFallCnt = 0;
          SET_SDA_DIR(temp, GPIO_DIR_IN);
          break;
      }
    }
    // SCL的上升沿事件处理,此时需要采集数据,而且在数据阶段,SCL高电平时数据必须保持不变
    else
    {
      switch( State)
      {
        case I2C_STA_DATA:  // 数据阶段,如果是主机写入数据,则采集比特数据
          if((I2C_WRITE ==  Rw) && (8 >  SclFallCnt))
          {
						SDA_FLAG_IF = SW_SLAVE_SDA_PRT->IDR & SW_SLAVE_SDA_PIN;
						
            if(SDA_FLAG_IF == 0x80)
            {
							 RxBuf[ RxIdx] |= (1 << (7 -  SclFallCnt));

            }

						
          }
          break;
        case I2C_STA_ACK:  // 应答阶段,如果是主机读取数据,则判断ACK/NACK信号,默认状态是ACK
					SDA_FLAG_IF = (SW_SLAVE_SDA_PRT->IDR & SW_SLAVE_SDA_PIN);
          if(( Rw == I2C_READ) && SDA_FLAG_IF)
          {
             State = I2C_STA_NACK;
          }
          break;
      }
    }
  }
  else if(__HAL_GPIO_EXTI_GET_IT(SW_SLAVE_SDA_PIN) != RESET)//检测是不是sda触发的中断
  {
    __HAL_GPIO_EXTI_CLEAR_IT(SW_SLAVE_SDA_PIN);
		//SDA的下降沿事件
		SDA_FLAG_IF = (SW_SLAVE_SDA_PRT->IDR & SW_SLAVE_SDA_PIN);
    if( SDA_FLAG_IF == (uint32_t)GPIO_PIN_RESET)
    {
      // SCL为高电平时,SDA从高变低,说明是起始信号
			SCL_FLAG_IF = SW_SLAVE_SCL_PRT->IDR & SW_SLAVE_SCL_PIN;
      if(SCL_FLAG_IF)
      {
         State = I2C_STA_START;
      }
    }
    else//SDA的上升沿事件
    {
      // SCL为高电平时,SDA从低变高,说明是停止信号,一次I2C通信结束,直接将状态设置成空闲
			SCL_FLAG_IF = SW_SLAVE_SCL_PRT->IDR & SW_SLAVE_SCL_PIN;
      if(SCL_FLAG_IF)
      {
         State = I2C_STA_IDLE;
      }
    }
  }
}

主机部分

	while(1)
	{
		key=KEY_Scan(0);
		if(key==KEY1_PRES)//KEY1按下,写入24C02
		{
//						LCD_Fill(0,170,239,319,WHITE);//清除半屏    
//			 			LCD_ShowString(30,170,200,16,16,"Start Write 24C02....");
				IIC_Start();
				IIC_Send_Byte(0X6E);   //发送器件地址0XA0,写数据 	 
				IIC_Wait_Ack();	   
				IIC_Send_Byte(0X10);   //发送低地址
				IIC_Wait_Ack(); 	 										  		   
				IIC_Send_Byte(0XAA);     //发送字节							   
				IIC_Wait_Ack();  		    	   
				IIC_Stop();//产生一个停止条件 
				delay_ms(10);	

//			AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
			LCD_ShowString(30,170,200,16,16,"very OKOK!!");//提示传送完成
		}
		if(key==KEY0_PRES)//KEY0按下,读取字符串并显示
		{
// 			LCD_ShowString(30,170,200,16,16,"Start Read 24C02.... ");
//			AT24CXX_Read(0,datatemp,SIZE);
//			LCD_ShowString(30,170,200,16,16,"The Data Readed Is:  ");//提示传送完成
//			LCD_ShowString(30,190,200,16,16,datatemp);//显示读到的字符串
			u8 temp=0;		  	    																 
			IIC_Start();  
      IIC_Send_Byte(0X6E);   //发送器件地址0XA0,写数据 	   
			IIC_Wait_Ack(); 
			IIC_Send_Byte(0X1);   //发送低地址
			IIC_Wait_Ack();	    
			IIC_Start();  	 	   
			IIC_Send_Byte(0X6F);           //进入接收模式			   
			IIC_Wait_Ack();	 
			temp=IIC_Read_Byte(0);		   
			IIC_Stop();//产生一个停止条件
			delay_ms(10);	
			
			IntToHexString(temp, hexString);
			LCD_ShowString(30,170,200,16,16,"The Data Readed Is:  ");//提示传送完成
			LCD_ShowString(30,190,200,16,16,hexString);//显示读到的字符串
//				IIC_SDA=1;	  	  
//				IIC_SCL=0;
		}
		i++;
		delay_ms(10);
		if(i==20)
		{
			LED0=!LED0;//提示系统正在运行	
			i=0;
		}		   
	} 	  

使用硬件iic从机和硬件iic主机连接,可以正常连接,但出现了三次烧板子的情况,两次烧主机,一次烧从机,未找到烧板子原因

硬件iic,F4参考该资源,烧录就可以使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值