您尚未登录。

楼主 # 2022-09-13 16:45:19

XMGroupe.
会员
注册时间: 2022-08-22
已发帖子: 12
积分: 237

[XMG助力国产]MC3172普通IO模拟UART-9600

[XMG助力国产生态]
@XMGroupe.

本文介绍MC3172普通IO模拟UART

此驱动通过软件延时实现,目前9600波特率能够稳定运行。
内部RC高速时钟 192M

1.初始化代码

typedef enum _TX_STATE_{
    eUART_TX_IDLE = 0,      //发送空闲
    eUART_TX_SEND = 1,      //发送数送
}eTX_STATE;
typedef struct _eUART_TX_{
    eTX_STATE tx_state;                      //发送状态
    u32 bound;                         //波特率
    u8  nstop;                         //停止位数
}eUART_TX;

typedef enum _RX_STATE_{
    eUART_RX_IDLE = 0,      //接收空闲
    eUART_RX_RECV = 1,      //接收数据
}eRX_STATE;
typedef struct _eUART_RX_{
    eTX_STATE rx_state;                      //发送状态
    u32 bound;                         //波特率
    u8  nstop;                         //停止位数
}eUART_RX;

eUART_TX    exUART_TX;
eUART_RX    exUART_RX;
void Uart_Soft_Init(u32 Rate)
{
    /*启动外设*/
    INTDEV_SET_CLK_RST(GPIOA_BASE_ADDR,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV8));//24M
    GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
    GPIO_SET_INPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN5),GPIO_SET_ENABLE);

    GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));

    exUART_TX.bound = Rate;
    exUART_TX.nstop = 1;
    exUART_TX.tx_state = eUART_TX_IDLE;
}

2.发送程序

/***   euart开始位   ***/
/*
 * baud 波特率
 */
void Send_Start_Soft(eUART_TX *extx)
{
    GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
    GPIO_SET_OUTPUT_PIN_TO_0(GPIOA_BASE_ADDR,(GPIO_PIN4));
    delay_baud(extx->bound);

    //GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN6));
}
/***   euar停止位   ***/
/*
 * baud 波特率
 * stop 停止位数
 */
void Send_Stop_Soft(eUART_TX *extx)
{
    GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
    GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
    delay_baud(extx->bound);
}
/***   euart空闲   ***/
/*
 * baud 波特率
 * stop 停止位数
 */
void Send_Idle_Soft(eUART_TX *extx)
{
    GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
    GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
    extx->tx_state = eUART_TX_IDLE;             //空闲标志位置
}
//发送单个byte
void Send_Byte_Soft(unsigned char dat)
{
    u8 i = 0;
    while(exUART_TX.tx_state == eUART_TX_SEND);     //等待总线空闲
    if(exUART_TX.tx_state == eUART_TX_IDLE)         //总线空闲
    {
        exUART_TX.tx_state = eUART_TX_SEND;         //总线忙
        Send_Start_Soft(&exUART_TX);
        for(i = 0; i < 8; i++)
        {
            if(dat&0x01)
            {
                GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
                GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
            }
            else
            {
                GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
                GPIO_SET_OUTPUT_PIN_TO_0(GPIOA_BASE_ADDR,(GPIO_PIN4));
            }
            dat = dat >> 1;
            delay_baud(exUART_TX.bound);
        }
        Send_Stop_Soft(&exUART_TX);
    }
    Send_Idle_Soft(&exUART_TX);
}
//发送字符串
void Send_String_Soft(u8 *dat, u16 len)
{
    u8 temp = 0;
    u16 send_count = 0;
    u8 i = 0;
    while(send_count < len)
    {
        exUART_TX.tx_state = eUART_TX_SEND;         //总线忙
        temp = dat[send_count];
        Send_Start_Soft(&exUART_TX);
        for(i = 0; i < 8; i++)
        {
            if(temp&0x01)
            {
                GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
                GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
            }
            else
            {
                GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
                GPIO_SET_OUTPUT_PIN_TO_0(GPIOA_BASE_ADDR,(GPIO_PIN4));
            }
            temp = temp >> 1;
            delay_baud(exUART_TX.bound);
        }
        send_count ++;
        Send_Stop_Soft(&exUART_TX);
    }
    Send_Idle_Soft(&exUART_TX);
}

3.接收函数

u8 Recv_String_Soft(u8 *recv, u16 len)
{
    u8 i = 0;
    u16 recv_count = 0;
    u8 dat = 0x00;

    while(recv_count < len)
    {
        //等待RX拉低,接收数据起始位
        while(((GPIO_GET_INPUT_VALUE_FAST(GPIOA_BASE_ADDR)&0x0020)>>5) != 0);
        //接收到起始位,设置为接收繁忙,延时波特率时间
        exUART_RX.rx_state = eUART_RX_RECV;
        delay_baud(exUART_TX.bound);
        NOP();
        for(i = 0; i < 8; i ++)
        {
            dat = dat >> 1;
            if(((GPIO_GET_INPUT_VALUE_FAST(GPIOA_BASE_ADDR)&0x0020) >> 5) == 1)
            {
                dat |= 0x80;
            }
            delay_baud(exUART_TX.bound);
        }
        recv[recv_count] = dat;
        dat = 0;
        recv_count ++;
        delay_baud(exUART_TX.bound);    //延时一个停止位时间
    }
    return recv_count;
}

4.延时函数

void delay_baud(u32 baud)
{
    u32 start,stop,ticks;
    start = CORE_CNT;
    if(baud == 9600)
    {
        ticks = 5002;
    }
    else
    {
//其他波特率对应延时自行添加
        //ticks = (u32)(Sys_Clk * 1000000 / baud);
    }
    if(0xFFFFFFFF-start>=ticks){
        stop=start+ticks;
        while(CORE_CNT<stop && CORE_CNT>start){}
    }
    else{
        stop=ticks-(0xFFFFFFFF-start);
        while(CORE_CNT>start){}
        while(CORE_CNT<stop){}
    }
}

最终效果
9600.jpg

*程序还有很多可以优化的地方,比如接收函数可以添加接收超时,此贴只作为一个DEMO,欢迎大家批评指正。
*也希望起到抛砖引玉的效果,能够看到更多优秀的程序开源。

离线

#1 2022-09-13 19:08:22

support_gxchip
Moderator
注册时间: 2022-07-26
已发帖子: 58
积分: 103

Re: [XMG助力国产]MC3172普通IO模拟UART-9600

感谢分享,真是高产啊

离线

楼主 #2 2022-09-14 10:45:52

XMGroupe.
会员
注册时间: 2022-08-22
已发帖子: 12
积分: 237

Re: [XMG助力国产]MC3172普通IO模拟UART-9600

@XMGroupe.
补一个串口数据波形图,下图是1M波特率,每个bit占1us,8,N,1,低位先传。模拟串口改参数可以参照这个波形图自己写时序。
1M%E4%B8%B2%E5%8F%A3%E8%A7%A3%E7%A0%81.jpg

离线

#3 2022-10-05 14:29:46

luther
会员
注册时间: 2022-10-04
已发帖子: 1
积分: 1

Re: [XMG助力国产]MC3172普通IO模拟UART-9600

文档说内部高速RC是200M, 低速是 8M, 这怎么说是 192M ?

离线

#7 2024-03-28 09:14:10

honami520
会员
注册时间: 2020-05-24
已发帖子: 10
积分: 9

Re: [XMG助力国产]MC3172普通IO模拟UART-9600

串口发送模拟还是比较简单的,STC都可以轻松做到,误码率都不高。但是串口接收模拟就不容易了,波特率高了就误码率高,然后中断太频繁对正常程序影响也大

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn