打印
[应用方案]

普通IO口模拟串口

[复制链接]
695|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
vivilyly|  楼主 | 2024-11-13 13:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
SIMU_UART.c 串口初始化
函数外部接口指针,串口参数初始化

#include "SIMU_UART.h"

#if(SIMU_UART_SRC == SIMU_METHOD1)
#include "simu_uart1.h"
#elif(SIMU_UART_SRC == SIMU_METHOD2)
#include "simu_uart2.h"
#elif(SIMU_UART_SRC == SIMU_METHOD3)
// #include "simu_uart3.h"
#endif

SIMU_UART simu_uart = {0};
volatile UART gsUARTBuff = {0}; // 定义串口
UART_KEY_MSG desk_key_msg = {0};

void simu_uart_init(void)
{
    simu_uart.baudrate = BAUDRATE;
    simu_uart.data_bits = 8;
    simu_uart.stop_bits = 1; // 这个默认
    simu_uart.parity = 0;

#if(SIMU_UART_SRC == SIMU_METHOD1)

    simu_uart.ext_irq = UART_EXT_IRQ_METHOD1;
    simu_uart.timer_irq = UART_TIM_IRQ_METHOD1;
    simu_uart.write = UART_Write_Data_API_METHOD1;
    simu_uart.read = UART_Read_Data_API_METHOD1;
    UART_Init_METHOD1(simu_uart);
#elif(SIMU_UART_SRC == SIMU_METHOD2)

    simu_uart.ext_irq = UART_EXT_IRQ_METHOD2;
    simu_uart.timer_irq = UART_TIM_IRQ_METHOD2;
    simu_uart.write = UART_Write_Data_API_METHOD2;
    simu_uart.read = UART_Read_Data_API_METHOD2;
    UART_Init_METHOD2(simu_uart);
#elif(SIMU_UART_SRC == SIMU_METHOD3)

#endif

}

void over_time_open_rx(void)
{
    // 当处于工作状态超过1000ms就超时恢复接收状态
    if(gsUARTBuff.UartStat != COM_NONE_BIT_DEAL && (++gsUARTBuff.over_rx_time > 1000))
    {
        gsUARTBuff.over_rx_time = 0;
        gsUARTBuff.UartStat = COM_NONE_BIT_DEAL;
        gsUARTBuff.RxEn = 0;
        gsUARTBuff.TxEn = 0;
#if(SIMU_UART_SRC == SIMU_METHOD1)
        UART_TIM_ENABLE_METHOD1(0, 0);
        UART_EXT_ENABLE_METHOD1(1);
#elif(SIMU_UART_SRC == SIMU_METHOD2)
        UART_TIM_ENABLE_METHOD2(0, 0);
        UART_EXT_ENABLE_METHOD2(1);
#endif
    }
}
// 测试
void simu_uart_test(void)
{
    uint8_t databuff[40] = {0}, len = 0;
    static uint16_t delay_time = 0;

    if(++delay_time > 2000)
    {
        delay_time = 0;

        len = simu_uart.read(databuff, 40);

        if(len)
        {
            simu_uart.write(databuff, len);
        }
    }
}

void uart_data_process(uint8_t *data, uint16_t size)
{
    uint8_t cmd_sta = CMD_FRAME_STA, len = 0, j = 0, data_buff[7] = {0};
    uint16_t check_sum = 0;

    for(uint16_t i = 0; i < size; i++)
    {
        switch (cmd_sta)
        {
        case CMD_FRAME_STA:
            if(data == 0x55)
                cmd_sta = CMD_LEN_STA;
            /* code */
            break;
        case CMD_LEN_STA:
            len = data;
            check_sum = 0;

            cmd_sta = CMD_FRAME_STA; // 如果校验和不过就重新开始
            if(i + len < size - 1)
            {
                for(j = i; j <= i + len; j++)
                {
                    check_sum += data[j];
                }

                if(check_sum & 0xff == data[j])
                    cmd_sta = CMD_DATA_STA;
            }
            break;
        case CMD_DATA_STA:
            memcpy(data_buff, &data, len);
            i += len - 1;
            cmd_sta = COM_CHECK_BIT_DEAL;
            break;
        case COM_CHECK_BIT_DEAL:
            cmd_sta = CMD_FRAME_STA;
            break;   
        default:
            break;
        }
    }

    memcpy(&desk_key_msg, data_buff, 7);
}

SIMU_UART.h
#ifndef _SIMU_UART_H_
#define _SIMU_UART_H_

#include "stdint.h"
#include "AppInclude.h"

#define     SIMU_METHOD1    0
#define     SIMU_METHOD2    1   
#define     SIMU_METHOD3    2
#define     SIMU_UART_SRC     SIMU_METHOD1

#define SYSTICK_TIM_ENABLE  1
#define TIM_SRC_FREQ    96 * 1000000  // 时钟频率,单位:Hz
#define TIM_PRESCALER   1 // 默认1
#define BAUDRATE        9600
#define DATA_BUFF_LEN   100

#define TX_IO(x)      if(x){SetPB6();}else{ResetPB6();}

#define RX_IO       ReadPB0()

#define TEST_IO(x)     if(x){SetPC5();}else{ResetPC5();}

#define TEST_IO_DELAY(x)   {TEST_IO(1);DelayUs(x);TEST_IO(0);DelayUs(x);}

#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) > (y) ? (y) : (x))
#define COMPARE(x, y) ((x) == (y) ? 1 : 0)      

typedef struct
{
    uint16_t baudrate;
    uint8_t data_bits;
    uint8_t stop_bits;
    uint8_t parity;

    void (*timer_irq)(void);
    void (*ext_irq)(void);
    uint8_t (*write)(uint8_t *data, uint16_t size);
    uint16_t (*read)(uint8_t *data, uint16_t size);
}SIMU_UART;

typedef enum
{
    COM_NONE_BIT_DEAL = 0,
    COM_START_BIT_DEAL,
    COM_DATA_BIT_DEAL,
    COM_CHECK_BIT_DEAL,
    COM_STOP_BIT_DEAL,
}UART_RX_STA;

typedef enum
{
    // CMD_NONE_STA = 0,
    CMD_FRAME_STA = 0,
    CMD_LEN_STA,
    CMD_DATA_STA,
    CMD_CHECK_STA,
}UART_PRO_STA;

typedef struct
{
    uint8_t CheckType;
    uint8_t DataBits;

    uint8_t UartStat;
    uint8_t TxEn;
    uint8_t RxEn;

    uint8_t UART_Send_buf[DATA_BUFF_LEN];
    uint8_t UART_Recv_buf[DATA_BUFF_LEN];

    uint16_t Sendlength;
    uint16_t Recvlength;

    float BaudTime;

    uint16_t curren_time;
    uint16_t over_rx_time;
}UART;

typedef struct
{
    uint8_t height;
    uint8_t Key_1_sta;
    uint8_t Key_2_sta;
    uint8_t Key_3_sta;
    uint8_t Key_s_sta;
    uint8_t Key_up_sta;
    uint8_t Key_down_sta;
}UART_KEY_MSG;

void simu_uart_init(void);
void simu_uart_test(void);
void over_time_open_rx(void);
void uart_data_process(uint8_t *data, uint16_t size);

extern SIMU_UART simu_uart;

extern volatile UART gsUARTBuff;

extern UART_KEY_MSG desk_key_msg;
#endif

simu_uart1.c 模拟串口实现
一些io初始化

/*
// 使用通用定时器和外部中断:外部中断触发启动接收,三次接收滤波。定时器负责接收、发送。
// 定时时钟源48M,分频后定时器3M
*/

#include "simu_uart1.h"
// 定时器加载值
static uint32_t TimeSet[5];

// 时间,第一个是调节开始采集数据的位置
float TimeSetBuff[][5] = {
    {250, 20, 20, 793.33, 833.33}, // 1200
    {100, 20, 20, 376.67, 416.67},  // 2400
    {30, 20, 20, 168.33, 208.33},    // 4800
    {5, 20, 20, 64.17, 104.17},    // 9600
    {0, 0, 0, 0, 0},            // 预留
};

// 时间
// float TimeSetBuff[][5] = {
//     {400, 20, 20, 793.33, 833.33}, // 1200
//     {180, 20, 20, 376.67, 416.67},  // 2400
//     {80, 20, 20, 168.33, 208.33},    // 4800
//     {50, 10, 10, 84.17, 104.17},    // 9600
//     {0, 0, 0, 0, 0},            // 预留
// };

static uint8_t ucRecvData = 0;    // 每次接收的字节
static uint8_t ucAcquCx = 0;      // 三次滤波计数
static uint8_t ucRecvBitCx = 0;   // 接收位计数
static uint8_t ucSendBitCx = 0;   // 发送位计数
static uint8_t ucSendLengCx = 0;  // 发送长度计数
static uint8_t ucRecvBitBuff = 0; // 采集位保存
static uint8_t time_offset = 0;

#if (!SYSTICK_TIM_ENABLE)
TIM_HandleTypeDef htim6;
#endif
/*******************************************************************************
* @FunctionName   : UART_TIM_Init_METHOD1.
* @description    : 定时器初始化.
* @Input          : 定时器时间.
* @output         : None.
* @return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_TIM_Init_METHOD1(uint32_t time)
{
#if (SYSTICK_TIM_ENABLE)
#if (TIM_PRESCALER > 1)
    /*
    code systick分频代码
    */
#endif

    // 初始化为波特率时间:us
    if (time <= 0xFFFFFFUL)
    {
        SysTick->LOAD = (uint32_t)time; /* set reload register */

        NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */

        SysTick->VAL = 0UL; /* Load the SysTick Counter Value  | (1UL << 0)*/
        SysTick->CTRL = (1UL << 2) | (1UL << 1);

    }
#else
    __HAL_RCC_TIM6_CLK_ENABLE();

    htim6.Instance = TIM6;
    htim6.Init.Prescaler = 15;
    htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim6.Init.Period = time;
    htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

    HAL_NVIC_SetPriority(TIM6_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM6_IRQn);

    HAL_TIM_Base_Init(&htim6);
#endif
}

/*******************************************************************************
* @FunctionName   : UART_GPIO_Init_METHOD1.
* @Description    : 串口模拟io口初始化.
* @Input          : None.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_GPIO_Init_METHOD1(void)
{
    SetInputModePB0();
    SetPullUpPB0();

    SetOutputModePB6();
    SetPullUpPB6();

    SetOutputModePC5();
    SetPullUpPC5();

    rSYSTEM1.per1.csbscl_gpio_sel = 0;

}
/*******************************************************************************
* @FunctionName   : UART_Rx_Ext_Init_METHOD1.
* @Description    : 串口模拟io口所用中断初始化.
* @Input          : None.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_Rx_Ext_Init_METHOD1(void)
{
        rSYSTEM2.per0.ext_intr2_level_edge_sel = 1;                // 选择边沿触发
        rSYSTEM2.per0.ext_intr2_rise_falling_sel = 1;        // 下降沿触发
       
        rINTR.sts.ext_intr2 = 1;                                                // 请中断
        rINTR.mask.ext_intr2 = 1;                                                // 开中断

        NVIC_SetPriority(ExtIntr2_IRQ,1);
        NVIC_ClearPendingIRQ(ExtIntr2_IRQ);
        NVIC_EnableIRQ(ExtIntr2_IRQ);
}
/*******************************************************************************
* @FunctionName   : UART_Init_METHOD1.
* @Description    : 模拟串口结构体初始化.
* @Input          : 串口参数结构体.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_Init_METHOD1(SIMU_UART simu_uart)
{
    float temp_buff[5] = {0};

    gsUARTBuff.CheckType = simu_uart.parity;
    gsUARTBuff.DataBits = simu_uart.data_bits;

    gsUARTBuff.UartStat = COM_NONE_BIT_DEAL;

    if (simu_uart.baudrate == 1200)
    {
        memcpy(temp_buff, &TimeSetBuff[0][0], sizeof(temp_buff));
    }
    else if (simu_uart.baudrate == 2400)
    {
        memcpy(temp_buff, &TimeSetBuff[1][0], sizeof(temp_buff));
    }
    else if (simu_uart.baudrate == 4800)
    {
        memcpy(temp_buff, &TimeSetBuff[2][0], sizeof(temp_buff));
    }
    else if (simu_uart.baudrate == 9600)
    {
        memcpy(temp_buff, &TimeSetBuff[3][0], sizeof(temp_buff));
    }

    for (uint8_t i = 0; i < 5; i++)
    {
        TimeSet = (uint32_t)(TIM_SRC_FREQ / TIM_PRESCALER / 1000000.0 * temp_buff + 0.5 - 1);
    }

    time_offset = (uint8_t)(TIM_SRC_FREQ / TIM_PRESCALER / 1000000.0);

    UART_GPIO_Init_METHOD1();

    UART_Rx_Ext_Init_METHOD1();

    UART_TIM_Init_METHOD1(TimeSet[TimeSendStep]);

}

/*******************************************************************************
* @FunctionName   : UART_EXT_IRQ_METHOD1.
* @Description    : 接收引脚外部中断,下降沿触发,触发后即进入起始位判断.
* @Input          : None.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_EXT_IRQ_METHOD1(void)
{
    /*
    // 清除中断标志等操作
    // if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4) != RESET)
    // {
    //     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);
    //     flag = 1;
    // }
    */

    static uint8_t flag = 1;

    if (gsUARTBuff.UartStat == COM_NONE_BIT_DEAL)
    {
        gsUARTBuff.over_rx_time = 0;

        gsUARTBuff.RxEn = 1;
        ucRecvData = 0;
        ucRecvBitCx = 0;
        gsUARTBuff.UartStat = COM_START_BIT_DEAL;
        // buff溢出进行重新初始化索引
        if(gsUARTBuff.Recvlength >= DATA_BUFF_LEN)
            gsUARTBuff.Recvlength = 0;

        UART_EXT_ENABLE_METHOD1(0); // 接收先屏蔽事件

        UART_TIM_ENABLE_METHOD1(1, TimeSet[TimeRecvStartStep1]);
    }
}

/*******************************************************************************
* @FunctionName   : UART_TIM_IRQ_METHOD1.
* @Description    : 中断处理函数,包括发送和接收两部分.
* @Input          : None.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_TIM_IRQ_METHOD1(void)
{
    /*
    // 清除中断标志等操作
    // HAL_TIM_IRQHandler(&htim6); // This function handles TIM interrupts requests.
    */

    UART_Send_Data_METHOD1();

    UART_Recv_Data_METHOD1();

}

/*******************************************************************************
* @FunctionName   : UART_Send_Data_METHOD1.
* @Description    : 发送数据.
* @Input          : None.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_Send_Data_METHOD1(void)
{
    if (gsUARTBuff.TxEn == 1) /*数据发送,发送优先,无发送后才进入接收状态*/
    {
        switch (gsUARTBuff.UartStat) /*串口发送位状态判断*/
        {
        // 启动位
        case COM_START_BIT_DEAL:
        {
            TX_IO(0);                               // 拉低初始化io
            gsUARTBuff.UartStat = COM_DATA_BIT_DEAL; // 进入下个阶段
            ucSendBitCx = 0;                         // 初始化发送记数
        }
        break;
        // 数据位
        case COM_DATA_BIT_DEAL:
        {
            TX_IO((gsUARTBuff.UART_Send_buf[ucSendLengCx] >> ucSendBitCx) & 0x01);

            ucSendBitCx++;

            if (ucSendBitCx >= gsUARTBuff.DataBits)
            {
                if (gsUARTBuff.CheckType == 0)
                {
                    gsUARTBuff.UartStat = COM_STOP_BIT_DEAL;
                }
                else
                {
                    gsUARTBuff.UartStat = COM_CHECK_BIT_DEAL;
                }
            }
        }
        break;

        case COM_CHECK_BIT_DEAL:
        {
        }
        break;

        case COM_STOP_BIT_DEAL:
        {
            TX_IO(1); // 拉高停止

            ucSendBitCx = 0;

            // 判断是否发送结束
            if (ucSendLengCx < gsUARTBuff.Sendlength - 1)
            {
                gsUARTBuff.UartStat = COM_START_BIT_DEAL;
                ucSendLengCx++;
            }
            else
            {
                ucSendLengCx = 0;
                gsUARTBuff.UartStat = COM_NONE_BIT_DEAL;
                gsUARTBuff.TxEn = 0;
                gsUARTBuff.RxEn = 1;

                UART_TIM_ENABLE_METHOD1(0, 0);
                UART_EXT_ENABLE_METHOD1(1);
            }
        }
        break;

        default:
            break;
        }
    }
}

/*******************************************************************************
* @FunctionName   : UART_Send_Data_METHOD1.
* @Description    : 接收数据.
* @Input          : None.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_Recv_Data_METHOD1(void)
{
    if (gsUARTBuff.RxEn == 1)
    {

        switch (gsUARTBuff.UartStat)
        {
        case COM_START_BIT_DEAL:
        {

            // 接收保存
            ucRecvBitBuff = (ucRecvBitBuff << 1) | (RX_IO & 0x01);

            if (++ucAcquCx >= 3)
            {   
                // 启动位-拉低,否则无效
                if (BitValueChk(ucRecvBitBuff) == 0)
                {
                    gsUARTBuff.UartStat = COM_DATA_BIT_DEAL;
                    UART_TIM_CTRL_METHOD1(TimeSet[ucAcquCx]);
                }
                else
                {
                    gsUARTBuff.UartStat = COM_STOP_BIT_DEAL;
                }

                ucRecvBitBuff = 0;
                ucAcquCx = 0;
            }
            else
            {
                UART_TIM_CTRL_METHOD1(TimeSet[ucAcquCx]); // 修改重载值
            }
        }
        break;

        case COM_DATA_BIT_DEAL: // 数据位
        {

            ucRecvBitBuff = (ucRecvBitBuff << 1) | (RX_IO & 0x01);

            if (++ucAcquCx >= 3)
            {   
                ucRecvData |= (BitValueChk(ucRecvBitBuff) & 0x01) << ucRecvBitCx;

                if (ucRecvBitCx >= gsUARTBuff.DataBits - 1)
                {
                    ucRecvBitCx = 0;

                    if (gsUARTBuff.CheckType == 0)
                    {
                        gsUARTBuff.UartStat = COM_STOP_BIT_DEAL;
                    }
                    else
                    {
                        gsUARTBuff.UartStat = COM_CHECK_BIT_DEAL;
                    }
                }
                else
                {
                    ucRecvBitCx++;
                }

                UART_TIM_CTRL_METHOD1(TimeSet[ucAcquCx]);
                ucAcquCx = 0;
                ucRecvBitBuff = 0;
            }
            else
            {
                UART_TIM_CTRL_METHOD1(TimeSet[ucAcquCx]);
            }
        }
        break;

        case COM_CHECK_BIT_DEAL: // 校验位
        {
        }
        break;

        case COM_STOP_BIT_DEAL: // 停止位
        {

            ucRecvBitBuff = (ucRecvBitBuff << 1) | (RX_IO & 0x01);

            if (++ucAcquCx >= 3)
            {   
                // 空闲-拉高,否则重新记数获取停止位
                if (BitValueChk(ucRecvBitBuff) == 1)
                {
                    if (gsUARTBuff.Recvlength < DATA_BUFF_LEN)
                    {
                        gsUARTBuff.UART_Recv_buf[gsUARTBuff.Recvlength] = ucRecvData;
                        gsUARTBuff.Recvlength++;


                    }

                    gsUARTBuff.UartStat = COM_NONE_BIT_DEAL;
                    gsUARTBuff.RxEn = 0;
                    UART_TIM_ENABLE_METHOD1(0, 0);
                    UART_EXT_ENABLE_METHOD1(1);
                }
                else
                {
                    ucAcquCx = 0;
                }

                ucRecvBitBuff = 0;
                ucAcquCx = 0;
            }
            else
            {
                UART_TIM_CTRL_METHOD1(TimeSet[ucAcquCx]);
            }
        }
        break;

        default:
            break;
        }
    }
}

/*******************************************************************************
* @FunctionName   : UART_TIM_ENABLE_METHOD1.
* @Description    : 定时器使用前后使能.
* @Input          : 是否使能,初始化时间(适用使能).
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_TIM_ENABLE_METHOD1(uint8_t flag, uint32_t time)
{
#if (SYSTICK_TIM_ENABLE)
    if (flag)
    {
        if(SysTick->CTRL & 0x01)
            SysTick->CTRL &= ~(1UL << 0);

        SysTick->LOAD = (uint32_t)time;
        SysTick->VAL = 0UL;
        SysTick->CTRL |= (1UL << 0);
    }
    else
    {
        SysTick->CTRL &= ~(1UL << 0);
        SysTick->VAL = 0UL;
    }
#else
    if (flag)
    {
        TIM6->ARR = time;
        TIM6->EGR = TIM_EGR_UG;

        HAL_TIM_Base_Start_IT(&htim6);
    }
    else
    {
        HAL_TIM_Base_Stop_IT(&htim6);
        TIM6->CNT = 0;
    }
#endif
}

/*******************************************************************************
* @FunctionName   : UART_TIM_CTRL_METHOD1.
* @Description    : 定时器重加载.
* @Input          : 初始化时间.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_TIM_CTRL_METHOD1(uint32_t time)
{
    time = TimeSet_Offset(time);

#if (SYSTICK_TIM_ENABLE)
    // if(SysTick->CTRL & 0x01)
    //     SysTick->CTRL &= ~(1UL << 0);

    SysTick->LOAD = (uint32_t)time;

    // SysTick->CTRL |= (1UL << 0);
    // UART_TIM_ENABLE_METHOD1(1, time); // 这里有些奇异,如果重启会不准,和清空记数有关
#else
    TIM6->ARR = time;
#endif
}

/*******************************************************************************
* @FunctionName   : UART_EXT_ENABLE_METHOD1.
* @Description    : 定时器使用前后使能.
* @Input          : 是否使能.
* @Output         : None.
* @Return         : None.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
void UART_EXT_ENABLE_METHOD1(uint8_t flag)
{
    if (flag)
    {
        rINTR.sts.ext_intr2 = 1;                                                // 请中断
        rINTR.mask.ext_intr2 = 1;                                                // 开中断

        // EXTI->IMR |= 0x10;
        // EXTI->EMR |= 0x10;
    }
    else
    {
        rINTR.sts.ext_intr2 = 1;                                                // 请中断
        rINTR.mask.ext_intr2 = 0;                                                // 关中断

        // EXTI->IMR &= ~(0x10); // 中断屏蔽
        // EXTI->EMR &= ~(0x10); // 事件屏蔽
    }
}

/*******************************************************************************
* @FunctionName   : UART_Write_Data_API_METHOD1.
* @Description    : 模拟串口发送数据接口.
* @Input          : 数据,数据长度.
* @Output         : None.
* @Return         : 发送状态.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
uint8_t UART_Write_Data_API_METHOD1(uint8_t *data, uint16_t size)
{
    if (gsUARTBuff.UartStat == COM_NONE_BIT_DEAL)
    {
        gsUARTBuff.over_rx_time = 0;
        // memcpy(gsUARTBuff.UART_Send_buf, data, size);

        if(DATA_BUFF_LEN < size)
            size = DATA_BUFF_LEN;

        gsUARTBuff.Sendlength = size;
        for(uint16_t i = 0; i < size; i++)
        {
            gsUARTBuff.UART_Send_buf = data;
        }

        ucSendLengCx = 0;
        gsUARTBuff.TxEn = 1;
        gsUARTBuff.RxEn = 0;
        gsUARTBuff.UartStat = COM_START_BIT_DEAL;
        // 发送前一定要屏蔽接收中断,要不然发送时基会被打乱
        UART_EXT_ENABLE_METHOD1(0);
        UART_TIM_ENABLE_METHOD1(1, TimeSet[TimeSendStep]);

        return 1;
    }

    return 0;
}

/*******************************************************************************
* @FunctionName   : UART_Read_Data_API_METHOD1.
* @Description    : 模拟串口读取数据接口初始化.
* @Input          : 数据.
* @Output         : 接收数据.
* @Return         : 数据长度.
* @Author&Data    : MrShuCai  2019.4.11.
*******************************************************************************/
uint16_t UART_Read_Data_API_METHOD1(uint8_t *data, uint16_t size)
{
    if (gsUARTBuff.UartStat == COM_NONE_BIT_DEAL && gsUARTBuff.Recvlength)
    {
        gsUARTBuff.over_rx_time = 0;
        // memcpy(data, gsUARTBuff.UART_Recv_buf, gsUARTBuff.Recvlength);

        if(gsUARTBuff.Recvlength < size)
            size = gsUARTBuff.Recvlength;

        for(uint16_t i = 0; i < size; i++)
        {
            data = gsUARTBuff.UART_Recv_buf;
        }

        gsUARTBuff.Recvlength = 0;

        return size;
    }
    return 0;
}

/*******************************************************************************
* @FunctionName   : BitValueChk.
* @Description    : 判断采集bit值,三次中为1的次数大于等于2则值为1否则为0.
* @Input          : n 采集记录的位值.
* @Output         : BitValue.
* @Return         : BitValue.
* @Author&Data    : MrShuCai  2019.5.1.
*******************************************************************************/
uint8_t BitValueChk(uint8_t n)
{
    uint8_t BitValCx = 0;

    for (BitValCx = 0; n; n >>= 1)
    {
        BitValCx += n & 0x01;
    }

    return (BitValCx < 2) ? (0) : (1);
}


uint32_t TimeSet_Offset(uint32_t time)
{
#if(BAUDRATE == 9600)
    if(ucRecvBitCx > 6)
    {
        if(ucAcquCx == 1 || ucAcquCx == 2)
        {
            time -= time_offset * (ucRecvBitCx - 1);
        }
        else if(ucAcquCx == 3)
        {
            time += time_offset * (ucRecvBitCx - 1) * 2;
        }
    }
#endif

    return time;

}

simu_uart1.h
#ifndef _SIMU_UART1_H_
#define _SIMU_UART1_H_

#include "stdint.h"
#include "string.h"
#include "SIMU_UART.h"

typedef enum
{
    TimeRecvStartStep1 = 0,
    TimeRecvStep1 = 1,
    TimeRecvStep2 = 2,
    TimeRecvStep3 = 3,
    TimeSendStep = 4,

}TimeStep;

void UART_EXT_ENABLE_METHOD1(uint8_t flag); // 外部中断事件使能

void UART_TIM_ENABLE_METHOD1(uint8_t flag, uint32_t time); // 定时器使用前后使能

void UART_TIM_CTRL_METHOD1(uint32_t time);

void UART_TIM_IRQ_METHOD1(void); // 定时器中断

void UART_EXT_IRQ_METHOD1(void); // 外部中断

void UART_GPIO_Init_METHOD1(void); // 串口模拟io口初始化

void UART_TIM_Init_METHOD1(uint32_t time); // 定时器配置

void UART_Rx_Ext_Init_METHOD1(void); // 串口模拟io口所用中断初始化

void UART_Init_METHOD1(SIMU_UART simu_uart); // 串口初始化

void UART_Send_Data_METHOD1(void); // 发送数据

void UART_Recv_Data_METHOD1(void); // 接收数据

uint8_t BitValueChk(uint8_t n); // 滤波
uint32_t TimeSet_Offset(uint32_t time);

uint8_t UART_Write_Data_API_METHOD1(uint8_t *data, uint16_t size); // 发送数据
uint16_t UART_Read_Data_API_METHOD1(uint8_t *data, uint16_t size); // 接收数据

#endif



使用特权

评论回复
沙发
Undshing| | 2024-11-17 13:50 | 只看该作者
模拟出串口时序就可以了

使用特权

评论回复
板凳
Undshing| | 2024-11-17 13:50 | 只看该作者
我们这之前用过一款需要模拟串口的芯片

使用特权

评论回复
地板
wahahaheihei| | 2024-11-17 20:15 | 只看该作者
一般这种都要定时器配合。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

86

主题

1697

帖子

1

粉丝