# 18.01_SIF-发送数据  

## 测试步骤  
在P2.6上发送0x0xf0，并记录实际波形
## 实测数据  

```csv_line
t,io0,
0.000776370,0,
0.000922885,0,
0.000922885,1,
0.000986708,1,
0.000986708,0,
0.001018422,0,
0.001018422,1,
0.001082250,1,
0.001082250,0,
0.001113953,0,
0.001113953,1,
0.001177776,1,
0.001177776,0,
0.001209484,0,
0.001209484,1,
0.001273307,1,
0.001273307,0,
0.001337089,0,
0.001337089,1,
0.001368854,1,
0.001368854,0,
0.001432635,0,
0.001432635,1,
0.001464396,1,
0.001464396,0,
0.001528172,0,
0.001528172,1,
0.001559927,1,
0.001559927,0,
0.001623693,0,
0.001623693,1,
0.001655458,1,
0.001655458,0,
0.001801969,0,
```

## 参考代码  
18.01_SIF_SendData.c
```c
/**
 * @brief SIF-发送数据
 * @details
 * 在P2.6上发送0x0xf0，并记录实际波形
 */
#include "lks32mc09x_lib.h"
void SoftDelaymS(uint32_t n);

volatile int baud = 115200;    // 设定波特率
volatile int refbaud = 115200; // 设定波特率
volatile int sendflg = 0;      // 设定波特率
int main(void)
{
    __disable_irq();
    SIF_InitTypeDef SIF_InitStruct;
    SIF_StructInit(&SIF_InitStruct);

    SIF_InitStruct.SIF_DONE = DISABLE;       // 传输完成后默认低电平
    SIF_InitStruct.SIF_SYNC = DISABLE;       // 同步信号默认低电平
    SIF_InitStruct.SIF_SYNC_PULSE = DISABLE; // 同步信号有电平反转
    SIF_InitStruct.SIF_DONE_VLD = DISABLE;   // 无结束信号
    SIF_InitStruct.SIF_SYNC_VLD = DISABLE;   // 有同步信号
    SIF_InitStruct.SIF_RATIO = DISABLE;      // 数据占空比 2：1
    SIF_InitStruct.SIF_MSB = ENABLE;         // 数据传送顺序 高字节在前
    SIF_InitStruct.SIF_EN = ENABLE;          // SIF模块使能
    SIF_InitStruct.SIF_TOSC = 2;             // 时基设置 47 * 333 = 15.67US
    SIF_InitStruct.SIF_TSTH1 = 2;            // 同步时长 1000 * SIF_TOSC * 32
    SIF_InitStruct.SIF_TDTH1 = 2;            // 结束信号时长 1MS
    SIF_InitStruct.SIF_IRQ_IF = ENABLE;      // 有SIF中断标志位
    SIF_InitStruct.SIF_DMA_EN = DISABLE;     // DMA传输使能
    SIF_InitStruct.SIF_IRQ_EN = DISABLE;     // SIF中断关闭

    SIF_Init(SIF0, &SIF_InitStruct);

    GPIO_Config(GPIO2, GPIO_PinSource_6, GPIO_Mode_OUT, GPIO_AF_SIF);
    for (;;)
    {
        if (sendflg)
        {
            SIF0->IRQ = BIT4;
            SIF_Senddata(SIF0, 0xf0);
            while ((SIF0->IRQ & BIT4) == 0)
                ;
            sendflg = 0;
        }
    }
}

```

## 使用到的库函数  
库函数部分代码
```c
#define GPIO_AF_I2C 6
#define REG_RESET(reg,mask) reg &= ~(mask)
#define REG_SET(reg,mask) reg |= (mask)
#define REG_WRITE(reg,mask) reg = (mask)
#define SYS0 ((SYS_TypeDef *)(SYS_BASE))
#define SYS_MODULE_GPIO BIT11
#define SYS_MODULE_SIF0 BIT20
/**
 * @brief GPIO功能配置结构体句柄
 */
typedef struct GPIO_InitTypeDef {
    uint32_t GPIO_Pin;
    GPIO_Mode_TypeDef GPIO_Mode;
    GPIO_PuPd_TypeDef GPIO_PuPd;
    uint32_t GPIO_PODEna;
    uint32_t GPIO_PFLT;
};
/**
 * @brief GPIO模式选择枚举
 */
typedef enum GPIO_Mode_TypeDef {
    GPIO_Mode_IN = 0,
    GPIO_Mode_OUT = 1,
    GPIO_Mode_ANA = 2,
    GPIO_Mode_IO = 3,
}} {enum_name};
/**
 * @brief SIF初始化结构体定义
 */
typedef struct SIF_InitTypeDef {
    uint8_t SIF_DONE;
    uint8_t SIF_SYNC;
    uint8_t SIF_SYNC_PULSE;
    uint8_t SIF_DONE_VLD;
    uint8_t SIF_SYNC_VLD;
    uint8_t SIF_RATIO;
    uint8_t SIF_MSB;
    uint8_t SIF_EN;
    uint16_t SIF_TOSC;
    uint16_t SIF_TSTH1;
    uint8_t SIF_TDTH1;
    uint8_t SIF_IRQ_IF;
    uint8_t SIF_DMA_EN;
    uint8_t SIF_IRQ_EN;
};
/**
 * @brief  GPIO配置函数
 * @param  GPIOx: GPIO端口
 * @param  GPIO_PinSource: GPIO引脚
 * @param  mode: GPIO模式
 * @param  GPIO_AF_x: GPIO复用功能选择
 */
void GPIO_Config(GPIO_TypeDef *GPIOx, uint32_t GPIO_PinSource, GPIO_Mode_TypeDef mode, uint32_t GPIO_AF_x)
{
    GPIO_PinAFConfig(GPIOx, GPIO_PinSource, GPIO_AF_x);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin  = 1 << GPIO_PinSource;
    GPIO_InitStructure.GPIO_Mode = mode;
    if (GPIO_AF_x == GPIO_AF_I2C)
    {
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    }
    else
    {
        __NOP();
    }
    GPIO_Init(GPIOx, &GPIO_InitStructure);
}
/**
 * @brief 初始化GPIO
 * @param GPIOx GPIO模块指针
 * @param GPIO_InitStruct 指向包含初始化参数的GPIO_InitTypeDef结构体
 */
void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct)
{
    // 使能GPIO时钟
    SYS_ModuleClockCmd(SYS_MODULE_GPIO, ENABLE);

    // 配置引脚模式
    if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IN)
    {
        GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin;  // 打开输入使能
        GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
    }
    else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT)
    {
        GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
        GPIOx->POE |= GPIO_InitStruct->GPIO_Pin;  // 使能输出
    }
    else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IO)
    {
        GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin; // 使能输入
        GPIOx->POE |= GPIO_InitStruct->GPIO_Pin; // 使能输出
    }
    else // GPIO_Mode_ANA
    {
        GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
        GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
    }

    if (GPIO_InitStruct->GPIO_PuPd == GPIO_PuPd_UP)
    {
        GPIOx->PUE |= GPIO_InitStruct->GPIO_Pin; // 使能上拉
    }
    else
    {
        GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉
    }
    // 配置开漏使能
    if (GPIO_InitStruct->GPIO_PODEna)
    {
        GPIOx->PODE |= GPIO_InitStruct->GPIO_Pin;
    }
    else
    {
        GPIOx->PODE &= ~GPIO_InitStruct->GPIO_Pin;
    }

    // 配置滤波使能
    if (GPIO_InitStruct->GPIO_PFLT)
    {
        GPIOx->PFLT |= GPIO_InitStruct->GPIO_Pin;
    }
    else
    {
        GPIOx->PFLT &= ~GPIO_InitStruct->GPIO_Pin;
    }
}
/**
 * @brief 初始化GPIO结构体为默认值
 * @param GPIO_InitStruct 指向要初始化的GPIO_InitTypeDef结构体
 */
void GPIO_StructInit(GPIO_InitTypeDef *GPIO_InitStruct)
{
    for (int i = 0; i < sizeof(GPIO_InitTypeDef); i++)
    {
        ((uint8_t *)GPIO_InitStruct)[i] = 0;
    }
}
/**
 * @brief 初始化SIF模块
 * @param SIFx 指向SIF_TypeDef结构体的指针，表示具体的SIF实例
 * @param SIFInitStruct 指向SIF_InitTypeDef结构体的指针，包含初始化参数
 */
void SIF_Init(SIF_TypeDef *SIFx, SIF_InitTypeDef *SIFInitStruct)
{
    // 使能SIF模块时钟
    SYS_ModuleClockCmd(SYS_MODULE_SIF0, ENABLE);

    // 配置SIF寄存器
    SIFx->CFG = (SIFInitStruct->SIF_DONE << 7) |
                (SIFInitStruct->SIF_SYNC << 6) |
                (SIFInitStruct->SIF_SYNC_PULSE << 5) |
                (SIFInitStruct->SIF_DONE_VLD << 4) |
                (SIFInitStruct->SIF_SYNC_VLD << 3) |
                (SIFInitStruct->SIF_RATIO << 2) |
                (SIFInitStruct->SIF_MSB << 1) |
                SIFInitStruct->SIF_EN;

    SIFx->TOSC  = SIFInitStruct->SIF_TOSC;
    SIFx->TSTH1 = SIFInitStruct->SIF_TSTH1;
    SIFx->TDTH1 = SIFInitStruct->SIF_TDTH1;
    SIFx->IRQ   = (SIFInitStruct->SIF_IRQ_IF << 4) |
                (SIFInitStruct->SIF_DMA_EN << 1) |
                SIFInitStruct->SIF_IRQ_EN;
}
/**
 * @brief 初始化SIF结构体
 * @param SIFInitStruct 指向SIF_InitTypeDef结构体的指针
 */
void SIF_StructInit(SIF_InitTypeDef *SIFInitStruct)
{
    for (int i = 0; i < sizeof(SIF_InitTypeDef); i++)
    {
        ((uint8_t *)SIFInitStruct)[i] = 0;
    }
}
/**
 * @brief 发送数据
 * @param Data 要发送的数据
 */
void SIF_Senddata(SIF_TypeDef *SIFx, uint8_t Data)
{
    SIFx->WDATA = Data;
}
/**
 * @brief 数字模块时钟使能
 * @param nModule 模块编号
 * @param state 使能或禁用状态
 */
void SYS_ModuleClockCmd(uint32_t nModule, uint8_t state)
{
    REG_WRITE(SYS0->PROTECT, 0x7a83);
    if (state)
    {
        REG_SET(SYS0->CLK_FEN, nModule);
    }
    else
    {
        REG_RESET(SYS0->CLK_FEN, nModule);
    }
    REG_WRITE(SYS0->PROTECT, 0);
}
/**
 * @brief 配置GPIO引脚复用功能
 * @param GPIOx GPIO模块指针
 * @param GPIO_PinSource 引脚源
 * @param GPIO_AF 复用功能选择
 */
void GPIO_PinAFConfig(GPIO_TypeDef *GPIOx, uint32_t GPIO_PinSource, uint32_t GPIO_AF)
{
    uint8_t offset;
    uint8_t pins = GPIO_PinSource >> 2;
    offset       = ((GPIO_PinSource & 0x3) * 4);
    switch (pins)
    {
        case 0:
            GPIOx->F3210 = (GPIOx->F3210 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 1:
            GPIOx->F7654 = (GPIOx->F7654 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 2:
            GPIOx->FBA98 = (GPIOx->FBA98 & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        case 3:
            GPIOx->FFEDC = (GPIOx->FFEDC & ~(0xf << offset)) | (GPIO_AF << offset);
            break;
        default:
            break;
    }
}
```
