/********************************************************************************
 * @file    TWI_Master_DMA.c
 * @author  SOC AE Team
 * @version V1.1
 * @date    2025-06-27
 * @brief   TWI0作为主机，TWI1作为从机，TWI0使用DMA向TWI1发送和接收数据。（主从机模式请在宏定义进行选择，TWI_Mode=0为主机代码，TWI_Mode=1为从机代码）
 *
 *******************************************************************************/
#include "sc32_conf.h"
#include "Function_Init.h"

/* 选择主从机代码 */
#define TWI_Mode 0
 uint8_t Master_DMA_TWI0_SendData[16] = "ABCDEFGHIJKLMNOP";
 uint8_t Master_DMA_TWI1_SendData[16] = "abcdefghijklmnop";

#if (TWI_Mode == 0)
uint8_t Master_DMA_TWI0_ReceiveData[16];
static volatile FlagStatus TWI0_Flag = RESET, DMA0_Flag = RESET, DMA1_Flag = RESET;
#elif(TWI_Mode == 1)
static uint8_t TWI1_Num = 0;
uint8_t Master_DMA_TWI1_ReceiveData[16];
static volatile FlagStatus TWI1_Flag = RESET;
#endif

void TWI_Master_DMA_Function(void)
{
  uint8_t i;
	


#if (TWI_Mode == 0)


  TWI_InitTypeDef TWI_InitStruct; //定义TWI初始化结构体变量
  DMA_InitTypeDef DMA_InitStruct; //定义DMA初始化结构体变量

  /* 使能DMA和TWI0的时钟 */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);
  RCC_APB0Cmd(ENABLE);  //TWI0外设挂载在APB0时钟上
#if defined(SC32f10xx)||defined(SC32f12xx)
  RCC_APB0PeriphClockCmd(RCC_APB0Periph_TWI0, ENABLE);

#endif
  /* 结构体成员初始化 */
  TWI_StructInit(&TWI_InitStruct);
  DMA_StructInit(&DMA_InitStruct);

  /* TWI0主机	*/
  {
    /* 配置TWI0作为主机 */
    TWI_InitStruct.TWI_Ack = TWI_Ack_Enable;	//回应ACK
#if defined(SC32f10xx)||defined(SC32f12xx)
    TWI_InitStruct.TWI_Prescaler = TWI_PRESCALER_1024;

#endif
    /*  根据结构体配置初始化串口 */
    TWI_Init(TWI0, &TWI_InitStruct);

#if defined(SC32f10xx)||defined(SC32f12xx)
    /* 使能TWI中断 */
    TWI_ITConfig(TWI0, TWI_IT_INT, ENABLE);
    NVIC_EnableIRQ(TWI0_IRQn);

#endif		
    /* 使能TWI DMA */
    TWI_DMACmd(TWI0, TWI_DMAReq_TX, ENABLE);
    /* 使能接收发送口 */
#if defined(SC32f12xx)
   TWI_PinRemapConfig(TWI0,TWI_PinRemap_A);
#endif
    TWI_Cmd(TWI0, ENABLE);
  }

  /* TWI0主机DMA发送配置 */
  {
    DMA_InitStruct.DMA_BufferSize = 16;	//DMA搬运数量为16个
    DMA_InitStruct.DMA_CircularMode = DMA_CircularMode_Disable;	//关闭循环模式
    DMA_InitStruct.DMA_DataSize = DMA_DataSize_Byte;	//传输宽度为字节
    DMA_InitStruct.DMA_SourceMode = DMA_SourceMode_INC_CIRC;	//源地址循环递增
    DMA_InitStruct.DMA_TargetMode = DMA_TargetMode_FIXED;	//目标地址固定
    DMA_InitStruct.DMA_SrcAddress = (uint32_t)Master_DMA_TWI0_SendData;
    DMA_InitStruct.DMA_DstAddress = (uint32_t)&TWI0->TWI_DATA;
#if defined(SC32f10xx)||defined(SC32f12xx)
    DMA_InitStruct.DMA_Request = DMA_Request_TWI0_TX;	//TWI0 发送触发DMA0

#endif	
    DMA_InitStruct.DMA_Priority = DMA_Priority_HIGH;	//设置优先级为高
    DMA_Init(DMA0, &DMA_InitStruct);
    /* 开启DMA相关的中断 */
    DMA_ITConfig(DMA0, DMA_IT_INTEN | DMA_IT_TCIE, ENABLE);
    NVIC_EnableIRQ(DMA0_IRQn);
    DMA_Cmd(DMA0, ENABLE);	//使能DMA0
  }

  /* TWI0主机DMA接收配置 */
  {
    DMA_InitStruct.DMA_BufferSize = 16;	//DMA搬运数量为16个
    DMA_InitStruct.DMA_CircularMode = DMA_CircularMode_Disable;	//关闭循环模式
    DMA_InitStruct.DMA_DataSize = DMA_DataSize_Byte;	//传输宽度为字节
    DMA_InitStruct.DMA_SourceMode = DMA_SourceMode_FIXED;	//源地址固定
    DMA_InitStruct.DMA_TargetMode = DMA_TargetMode_INC_CIRC;	//目标地址循环递增
    DMA_InitStruct.DMA_SrcAddress = (uint32_t)&TWI0->TWI_DATA;
    DMA_InitStruct.DMA_DstAddress = (uint32_t)Master_DMA_TWI0_ReceiveData;
#if defined(SC32f10xx)||defined(SC32f12xx)
    DMA_InitStruct.DMA_Request = DMA_Request_TWI0_RX;	//TWI0接收触发DMA1

#endif
    DMA_InitStruct.DMA_Priority = DMA_Priority_HIGH;	//设置优先级为高
    DMA_Init(DMA1, &DMA_InitStruct);
    /* 开启DMA相关的中断 */
    DMA_ITConfig(DMA1, DMA_IT_INTEN | DMA_IT_TCIE, ENABLE);
    NVIC_EnableIRQ(DMA1_IRQn);
    DMA_Cmd(DMA1, ENABLE);	//使能DMA1
  }
	
#elif(TWI_Mode == 1)

  TWI_InitTypeDef TWI_InitStruct; //定义TWI初始化结构体变量

	 RCC_APB1Cmd(ENABLE);  //SPI0外设挂载在APB0时钟上
#if defined(SC32f10xx)||defined(SC32f12xx)
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TWI1, ENABLE);
#endif
  /* 结构体成员初始化 */
  TWI_StructInit(&TWI_InitStruct);

  /* TWI1从机配置*/
  {
    TWI_InitStruct.TWI_Ack = TWI_Ack_Enable;	//回应ACK
    TWI_InitStruct.TWI_GeneralCall = TWI_GeneralCall_Disable;	//不响应通用地址
    TWI_InitStruct.TWI_SlaveAdress = 0x12;	//配置从机地址
    TWI_InitStruct.TWI_Stretch = TWI_Stretch_Enable;
    /*  根据结构体配置初始化串口 */
    TWI_Init(TWI1, &TWI_InitStruct);
    
    /* 使能TWI中断 */
#if defined(SC32f10xx)||defined(SC32f12xx)	
    TWI_ITConfig(TWI1, TWI_IT_INT, ENABLE);
    NVIC_EnableIRQ(TWI1_IRQn);
#endif

    /* 使能接收发送口 */
    TWI_Cmd(TWI1, ENABLE);
  }
#endif

  while(1)
  {
#if (TWI_Mode == 0)

    /* 主机发送 */
    /* TWI使用DMA传输时需要配置Nbyte个数 */
    TWI_SetNbytes(TWI0, 16);
    DMA_SetCurrDataCounter(DMA0, 16);
    TWI_DMACmd(TWI0, TWI_DMAReq_TX, DISABLE);
    TWI_DMACmd(TWI0, TWI_DMAReq_TX, ENABLE);
    TWI_GenerateSTART(TWI0, ENABLE);
    {
      uint32_t delay_time = 1000;
      while(delay_time--);
    }
    while(TWI0_Flag == RESET);	//等待起始信号发送完成
    TWI0_Flag = RESET;
    TWI_Send7bitAddress(TWI0, 0x12, TWI_Command_Write);
    while(TWI0_Flag == RESET);	//等待地址发送完成
    TWI0_Flag = RESET;
    //判断DMA0搬运完成
    while(DMA0_Flag == RESET);
      DMA0_Flag = RESET;
      printf("TWI0主机发送数据成功！\r\n");   
    TWI_GenerateSTOP(TWI0, ENABLE);//发送停止信号

    while(TWI_GetStateMachine(TWI0) != TWI_Master_Idle);//等待主机恢复为空闲状态
    {
      uint32_t delay_time = 100000;
      while(delay_time--);
    }


    /* 主机接收 */
    TWI_SetNbytes(TWI0, 16);
    DMA_SetCurrDataCounter(DMA1, 16);
    TWI_DMACmd(TWI0, TWI_DMAReq_RX, DISABLE);
    TWI_DMACmd(TWI0, TWI_DMAReq_RX, ENABLE);

     TWI_GenerateSTART(TWI0, ENABLE);
    while(TWI0_Flag == RESET);	//等待起始信号发送完成
    TWI0_Flag = RESET;
    TWI_Send7bitAddress(TWI0, 0x12, TWI_Command_Read);
    while(TWI0_Flag == RESET);	//等待地址发送完成
    TWI0_Flag = RESET;
    //判断DMA1搬运完成
		while(DMA1_Flag == RESET);
    if(DMA1_Flag == SET)
    {
      DMA1_Flag = RESET;
      i = 0;
      while(Master_DMA_TWI0_ReceiveData[i] == Master_DMA_TWI1_SendData[i])//主机接收数据判断
      {
        i++;
        if(i == 16)
        {
          PA_OT(10);//主机接收数据全部正确，翻转主机的PA10
        }
      }
      printf("TWI0主机接收到的数据是 %.16s。\r\n", Master_DMA_TWI0_ReceiveData);
    }
    TWI_GenerateSTOP(TWI0, ENABLE);//发送停止信号
    while(TWI_GetStateMachine(TWI0) != TWI_Master_Idle);//等待主机恢复为空闲状态

    {
      uint32_t delay_time = 100000;
      while(delay_time--);
    }

#elif(TWI_Mode == 1)

    /* 从机接收 */
    while(TWI1_Num < 16)
    {
      if(TWI1_Flag == SET)
      {
        /* TWI1没有DMA，需要手动接收数据 */
        Master_DMA_TWI1_ReceiveData[TWI1_Num] = TWI_ReceiveData(TWI1);
        TWI1_Num ++;
        TWI1_Flag = RESET;
      }
    }
    TWI1_Num = 0;
    while(TWI_GetStateMachine(TWI1) != TWI_Slave_Idle);  //等待从机恢复为空闲状态
    i= 0;
    while(Master_DMA_TWI1_ReceiveData[i] == Master_DMA_TWI0_SendData[i])//从机接收数据判断
    {
      i++;
      if(i == 16)
      {
        PA_OT(10);//从机接收数据全部正确，翻转从机的PA10
      }
    }
    printf(" TWI1从机接收到数据是 %.16s。\r\n ", Master_DMA_TWI1_ReceiveData);

    /* 从机发送 */
    while(TWI1_Num < 16)
    {
      if(TWI1_Flag == SET)
      {
        /* TWI1没有DMA，需要手动发送数据 */
        TWI_SendData(TWI1, Master_DMA_TWI1_SendData[TWI1_Num]);
        TWI1_Num ++;
        TWI1_Flag = RESET;
      }
    }
    TWI1_Num = 0;
    while(TWI_GetStateMachine(TWI1) != TWI_Master_Idle);
    printf(" TWI1从机发送数据成功！\r\n ");

#endif
  }




}
//TWI0中断
void TWI_Master_DMA_TWI0Handler(void)
{
#if (TWI_Mode == 0)
#if defined(SC32f10xx)||defined(SC32f12xx)
  if(TWI_GetFlagStatus(TWI0, TWI_FLAG_TWIF) == SET)
  {
    TWI_ClearFlag(TWI0, TWI_FLAG_TWIF);

    TWI0_Flag = SET;
  }
#endif
#endif
}
//DMA0中断
void TWI_Master_DMA_DMA0Handler(void)
{
#if (TWI_Mode == 0)
  if(DMA_GetFlagStatus(DMA0, DMA_FLAG_TCIF) == SET)//DMA0搬运完成
  {
    DMA_ClearFlag(DMA0, DMA_FLAG_TCIF);
    DMA0_Flag = SET;
  }
#endif
}
//DMA1中断
void TWI_Master_DMA_DMA1Handler(void)
{
#if (TWI_Mode == 0)
  if(DMA_GetFlagStatus(DMA1, DMA_FLAG_TCIF) == SET)//DMA1搬运完成
  {
    DMA_ClearFlag(DMA1, DMA_FLAG_TCIF);
    DMA1_Flag = SET;
  }
#endif
}
//TWI1中断
void TWI_Master_DMA_TWI1Handler(void)
{

#if (TWI_Mode == 1)
#if defined(SC32f10xx)||defined(SC32f12xx)
  if(TWI_GetFlagStatus(TWI1, TWI_FLAG_TWIF) == SET)
  {
    if(TWI_GetFlagStatus(TWI1, TWI_FLAG_TXRXnE) == SET)	//从机接收到数据才置起标志位
    {
      TWI_ClearFlag(TWI1, TWI_FLAG_TXRXnE);
      TWI1_Flag = SET;
    }
    TWI_ClearFlag(TWI1, TWI_FLAG_TWIF);
  }

#endif
#endif
}





