打印
[DemoCode下载]

单线串口回环数据传输

[复制链接]
439|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xuanhuanzi|  楼主 | 2024-2-19 22:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
* @brief
*           Two Single-Wire Loopback data test.
*
* SPDX-License-Identifier: Apache-2.0
* [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2017 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include "stdio.h"
#include "string.h"
#include "NuMicro.h"


#define PLL_CLOCK   FREQ_96MHZ
#define BUFSIZE   128

/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
uint8_t g_u8RecData[BUFSIZE] = {0};
uint8_t g_u8TxData [BUFSIZE] = {0};
volatile uint32_t g_u32RecLen  =  0;
volatile int32_t  g_i32RecOK  = FALSE;


/*---------------------------------------------------------------------------------------------------------*/
/* Define functions prototype                                                                              */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void);
void UART1_TEST_HANDLE(void);
void UART02_TEST_HANDLE(void);
void UART_FunctionTest(void);


void SYS_Init(void)
{

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Enable HIRC clock (Internal RC 48MHz) */
    CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;

    /* Wait for HIRC clock ready */
    while(!(CLK->STATUS & CLK_STATUS_HIRCSTB_Msk));

    /* Select HCLK clock source as HIRC and and HCLK source divider as 1 */
    CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC;
    CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | CLK_CLKDIV0_HCLK(1);

    /* Enable UART0/1/2 peripheral clock */
    CLK->APBCLK0 |= (CLK_APBCLK0_UART0CKEN_Msk | CLK_APBCLK0_UART1CKEN_Msk | CLK_APBCLK0_UART2CKEN_Msk);

    /* Select IP clock source */
    /* Select UART0 clock source is HIRC */
    CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_UART0SEL_Msk)) | CLK_CLKSEL1_UART0SEL_HIRC;
    CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_UART0DIV_Msk)) | CLK_CLKDIV0_UART0(1);

    /* Select UART1 clock source is HIRC */
    CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_UART1SEL_Msk)) | CLK_CLKSEL1_UART1SEL_HIRC;
    CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_UART1DIV_Msk)) | CLK_CLKDIV0_UART1(1);

    /* Select UART2 clock source is HIRC */
    CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_UART2SEL_Msk)) | CLK_CLKSEL3_UART2SEL_HIRC;
    CLK->CLKDIV4 = (CLK->CLKDIV4 & (~CLK_CLKDIV4_UART2DIV_Msk)) | CLK_CLKDIV4_UART2(1);

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
    SystemCoreClockUpdate();

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Set PB multi-function pins for UART0 RXD=PB.12 and TXD=PB.13 */
    SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) | \
                    (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

    /* Set PA multi-function pins for UART1 RXD */
    SYS->GPA_MFPL = (SYS->GPA_MFPL & ~(SYS_GPA_MFPL_PA2MFP_Msk)) | SYS_GPA_MFPL_PA2MFP_UART1_RXD;

    /* Set PB multi-function pins for UART2 RXD */
    SYS->GPB_MFPL = (SYS->GPB_MFPL & ~(SYS_GPB_MFPL_PB0MFP_Msk)) | SYS_GPB_MFPL_PB0MFP_UART2_RXD;

    /* The RX pin needs to pull-high for single-wire */
    /* If the external circuit doesn't pull-high, set GPIO pin as Quasi-directional mode for this purpose here */
    PA->MODE &= (PA->MODE & ~GPIO_MODE_MODE2_Msk) | (GPIO_MODE_QUASI << GPIO_MODE_MODE2_Pos);

    PB->MODE = (PB->MODE & ~GPIO_MODE_MODE0_Msk) | (GPIO_MODE_QUASI << GPIO_MODE_MODE0_Pos);

    /* Lock protected registers */
    SYS_LockReg();

}
/*---------------------------------------------------------------------------------------------------------*/
/*                                     Init UART0                                                          */
/*---------------------------------------------------------------------------------------------------------*/
void UART0_Init()
{

    /* Configure UART0 and set UART0 baud rate */
    UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HIRC, 115200);
    UART0->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;

}
/*---------------------------------------------------------------------------------------------------------*/
/*                               Init Single Wire(UART1)                                                   */
/*---------------------------------------------------------------------------------------------------------*/

void UART1_Init()
{
    /* Configure Single Wire(UART1) and set Single Wire(UART1) baud rate */
    UART1->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HIRC, 115200);
    UART1->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;

    UART1->FUNCSEL = ((UART1->FUNCSEL & (~UART_FUNCSEL_FUNCSEL_Msk)) | UART_FUNCSEL_SINGLE_WIRE);
}


/*---------------------------------------------------------------------------------------------------------*/
/*                               Init Single Wire(UART2)                                                   */
/*---------------------------------------------------------------------------------------------------------*/

void UART2_Init()
{
    /* Configure Single Wire(UART2) and set Single Wire(UART2) baud rate */
    UART2->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HIRC, 115200);
    UART2->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;

    UART2->FUNCSEL = ((UART2->FUNCSEL & (~UART_FUNCSEL_FUNCSEL_Msk)) | UART_FUNCSEL_SINGLE_WIRE);

}

/*---------------------------------------------------------------------------------------------------------*/
/* UART Test Sample                                                                                        */
/* Test Item                                                                                               */
/* Debug port control the Single wire 1(UART1) send data to Single wire 2(UART2) or Single wire 2(UART1)   */
/* send data to Single wire 1(UART1)                                                                       */
/*---------------------------------------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------------------------------------*/
/*                                         Main Function                                                   */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{

    /* Init System, peripheral clock and multi-function I/O */
    SYS_Init();

    /* Init UART0 for printf */
    UART0_Init();
    /* Init UART1 and UART2 for Single Wire Test*/
    UART1_Init();
    UART2_Init();

    /*---------------------------------------------------------------------------------------------------------*/
    /*                                           SAMPLE CODE                                                   */
    /*---------------------------------------------------------------------------------------------------------*/

    printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
    printf("\nUART Sample Program\n");

    /* UART sample function */
    UART_FunctionTest();

    while (1);

}

/*---------------------------------------------------------------------------------------------------------*/
/*                       ISR to handle UART Channel 1 interrupt event                                      */
/*---------------------------------------------------------------------------------------------------------*/
void UART13_IRQHandler(void)
{
    UART1_TEST_HANDLE();
}

/*---------------------------------------------------------------------------------------------------------*/
/*                                  UART1 Callback function                                                */
/*---------------------------------------------------------------------------------------------------------*/
void UART1_TEST_HANDLE()
{

    uint32_t u32IntSts = UART1->INTSTS;

    if (u32IntSts & UART_INTSTS_RDAIF_Msk)
    {
        /* Get all the input characters */
        while (UART_IS_RX_READY(UART1))
        {
            /* Get the character from UART Buffer */
            g_u8RecData[g_u32RecLen] = UART_READ(UART1);

            if (g_u32RecLen == BUFSIZE - 1)
            {
                g_i32RecOK = TRUE;
                g_u32RecLen = 0;
            }
            else
            {
                g_u32RecLen++;
            }
        }
    }

    if (u32IntSts & UART_INTSTS_SWBEIF_Msk)
    {
        printf("Single-wire Bit Error Detection \n");
        UART1->INTSTS = UART_INTSTS_SWBEIF_Msk;
    }
}


/*---------------------------------------------------------------------------------------------------------*/
/* ISR to handle UART Channel 0/2 interrupt event                                                            */
/*---------------------------------------------------------------------------------------------------------*/
void UART02_IRQHandler(void)
{
    UART02_TEST_HANDLE();
}

/*---------------------------------------------------------------------------------------------------------*/
/* UART0/2 Callback function                                                                                  */
/*---------------------------------------------------------------------------------------------------------*/
void UART02_TEST_HANDLE()
{

    uint32_t u32IntSts = UART2->INTSTS;

    if (u32IntSts & UART_INTSTS_RDAIF_Msk)
    {
        /* Get all the input characters */
        while (UART_IS_RX_READY(UART2))
        {
            /* Get the character from UART Buffer */
            g_u8RecData[g_u32RecLen] = UART_READ(UART2);

            if (g_u32RecLen == BUFSIZE - 1)
            {
                g_i32RecOK = TRUE;
                g_u32RecLen = 0;
            }
            else
            {
                g_u32RecLen++;
            }
        }
    }

    if (u32IntSts & UART_INTSTS_SWBEIF_Msk)
    {
        printf("Single-wire Bit Error Detection \n");
        UART2->INTSTS = UART_INTSTS_SWBEIF_Msk;

    }
}
/*---------------------------------------------------------------------------------------------------------*/
/*                              Bulid Source Pattern function                                              */
/*---------------------------------------------------------------------------------------------------------*/
void Build_Src_Pattern(uint32_t u32Addr, uint8_t type, uint32_t u32Length)
{
    uint32_t i = 0, pattern = 0;
    uint8_t *pAddr;
    pAddr = (uint8_t *)u32Addr;

    if (type == 0)      pattern = 0x1f;
    else if (type == 1) pattern = 0x3f;
    else if (type == 2) pattern = 0x7f;
    else if (type == 3) pattern = 0xff;
    else  pattern = 0xff;

    for (i = 0; i < u32Length ; i++)
        pAddr[i] = (i & pattern);

}

/*---------------------------------------------------------------------------------------------------------*/
/*                    Verify that the received data is correct                                             */
/*---------------------------------------------------------------------------------------------------------*/
uint8_t Check_Pattern(uint32_t u32Addr0, uint32_t u32Addr1, uint32_t u32Length)
{
    uint32_t i = 0;
    uint8_t result = 1;
    uint8_t *pAddr0;
    uint8_t *pAddr1;
    pAddr0 = (uint8_t *)u32Addr0;
    pAddr1 = (uint8_t *)u32Addr1;

    for (i = 0; i < u32Length ; i++)
    {
        if (pAddr0[i] != pAddr1[i])
        {
            printf("Data Error Idex=%d,tx =%d,rx=%d\n", i, pAddr0[i], pAddr1[i]) ;
            result = 0;
        }
    }

    return result;
}


/*---------------------------------------------------------------------------------------------------------*/
/*  UART Function Test                                                                                     */
/*---------------------------------------------------------------------------------------------------------*/
void UART_FunctionTest()
{
    char cmmd ;
    uint32_t  u32i;

    printf("+-----------------------------------------------------------+\n");
    printf("|            UART Single Wire Function Test                 |\n");
    printf("+-----------------------------------------------------------+\n");
    printf("|  Description :                                            |\n");
    printf("|    The sample code will print input char on terminal      |\n");
    printf("|    The user must connect the UART1 RX pin(PA2) to         |\n");
    printf("|    UART_Rx Pin(PB0).                                      |\n");
    printf("|    Single Wire 1(PA2)send data to Single Wire 2(PB0).     |\n");
    printf("|    Single Wire 2(PB0)send data to Single Wire 1(PA2).     |\n");
    printf("|    Please enter any to start    (Press '0' to exit)       |\n");
    printf("+-----------------------------------------------------------+\n");

    /*
        Using a RS232 cable to connect UART0 and PC.UART0 is set to debug port.
          UART1 and UART2 is enable RDA and RLS interrupt.
          The user can use URT0 to control the transmission or reception of UART1(Single Wire mode)
        When UART1(Single Wire 1)transfers data to UART2(Single Wire 2), if data is valid,
          it will enter the interrupt and receive the data.And then check the received data.
        When UART2(Single Wire 2)transfers data to UART1(Single Wire 1), if data is valid,
          it will enter the interrupt and receive the data.And then check the received data.
      */

    /* Enable UART1 RDA/Time-out/Single-wire Bit Error Detection interrupt */
    NVIC_EnableIRQ(UART13_IRQn);
    UART1->INTEN |= (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_SWBEIEN_Msk);
    /* Enable UART2 RDA/Time-out/Single-wire Bit Error Detection interrupt */
    NVIC_EnableIRQ(UART02_IRQn);
    UART2->INTEN |= (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_SWBEIEN_Msk);

    do
    {
        printf("+--------------------------------------------------------------+\n");
        printf("|                UART Single Wire Test Item                    |\n");
        printf("+--------------------------------------------------------------+\n");
        printf("|    (1)Single Wire 1(PA2)send data to Single Wire 2(PB0).     |\n");
        printf("|    (2)Single Wire 2(PB0)send data to Single Wire 1(PA2).     |\n");
        printf("|    (E)Exit                                                   |\n");
        printf("+--------------------------------------------------------------+\n");

        cmmd = getchar();

        switch (cmmd)
        {
        case '1':
        {
            printf("SW1(UART1) --> SW2(UART2)Test :");
            g_i32RecOK  = FALSE;
            Build_Src_Pattern((uint32_t)g_u8TxData, UART_WORD_LEN_8, BUFSIZE);

            /* Check the Rx status is Idel */
            while (!UART_RX_IDLE(UART1)) {};

            /* Send data */
            for(u32i = 0; u32i < BUFSIZE; u32i++)
            {
                /* Send 1 byte data */
                UART1->DAT = g_u8TxData[u32i];

                /* Wait if Tx FIFO is full */
                while((UART1->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk)==0);
            }

            while (g_i32RecOK != TRUE) {}

            Check_Pattern((uint32_t)g_u8TxData, (uint32_t)g_u8RecData, BUFSIZE) ? printf(" Pass\n") : printf(" Fail\n");
            /* Clear the Tx and Rx data buffer */
            memset((uint8_t *)g_u8TxData, 0, BUFSIZE);
            memset((uint8_t *)g_u8RecData, 0, BUFSIZE);
        }
        break;

        case '2':
        {
            printf("SW2(UART2) --> SW1(UART1)Test :");
            g_i32RecOK  = FALSE;
            Build_Src_Pattern((uint32_t)g_u8TxData, UART_WORD_LEN_8, BUFSIZE);

            /* Check the Rx status is Idel */
            while (!UART_RX_IDLE(UART2)) {};

            /* Send data */
            for(u32i = 0; u32i < BUFSIZE; u32i++)
            {
                /* Send 1 byte data */
                UART2->DAT = g_u8TxData[u32i];

                /* Wait if Tx FIFO is full */
                while((UART2->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk)==0);
            }

            while (g_i32RecOK != TRUE) {};

            Check_Pattern((uint32_t)g_u8TxData, (uint32_t)g_u8RecData, BUFSIZE) ? printf(" Pass\n") :   printf(" Fail\n");

            /* Clear the Tx and Rx data buffer */
            memset((uint8_t *)g_u8TxData, 0, BUFSIZE);

            memset((uint8_t *)g_u8RecData, 0, BUFSIZE);
        }
        break;

        default:
            break;
        }

    }
    while ((cmmd != 'E') && (cmmd != 'e'));

    /* Disable UART1 RDA/Time-out interrupt */
    UART1->INTEN &= ~(UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_SWBEIEN_Msk);
    /* Disable UART2 RDA/Time-out interrupt */
    UART2->INTEN &= ~(UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_SWBEIEN_Msk);
    printf("\nUART Sample Demo End.\n");

}

/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/




使用特权

评论回复
沙发
xuanhuanzi|  楼主 | 2024-2-19 22:54 | 只看该作者
导入必要的库文件,包括<stdio.h>、<string.h>和"Nuvoton.h"。
定义了一些全局变量,包括接收数据缓冲区、发送数据缓冲区以及接收数据长度等。
进行系统初始化,包括时钟设置和串口引脚配置。
分别初始化了三个串口,其中UART0用于调试打印,UART1和UART2用于单线串口的测试。
在主函数中进行了串口功能测试。
定义了UART1和UART2的中断处理函数,用于处理数据接收和单线模式的错误检测。
定义了一些辅助函数,如构建源模式和检查接收数据是否正确。
在串口功能测试函数中,首先打印测试项目的描述信息,然后通过用户输入选择测试项目,分别是单线1发送数据到单线2和单线2发送数据到单线1。
测试过程中,通过循环发送数据,并等待数据接收完成,然后检查接收到的数据是否正确。
最后,根据用户输入决定是否退出测试,并禁用串口中断。
整体思路是通过配置单线串口,实现两个串口之间的数据传输和回环测试,通过中断处理函数处理数据接收和单线模式的错误检测,最终进行数据正确性验证。

使用特权

评论回复
板凳
小明的同学| | 2024-2-27 11:52 | 只看该作者
这个主要用于测试,单个芯片就可以完成收发验证。

使用特权

评论回复
地板
21mengnan| | 2024-2-27 21:34 | 只看该作者
常用的测试方法。

使用特权

评论回复
5
21mengnan| | 2024-2-27 21:34 | 只看该作者
串口还可以用DMA方法使用更好。

使用特权

评论回复
6
LEDyyds| | 2024-2-28 20:30 | 只看该作者
这就是为了测试吧

使用特权

评论回复
7
黑心单片机| | 2024-2-28 20:47 | 只看该作者
这玩意只有测试有用吧

使用特权

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

本版积分规则

155

主题

2084

帖子

2

粉丝