# 18.01_SIF-发送数据

## 测试步骤

在P2.6上发送0x0xf0，并记录实际波形

## 实测数据

## 参考代码

18.01_SIF_SendData.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;
            }
        }
    }

## 使用到的库函数

库函数部分代码

    #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;
        }
    }