This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129芯片的UART

您好,您帮忙看下
while(!ROM_UARTBusy(UART2_BASE))
{
ROM_UARTCharPutNonBlocking(UART2_BASE, SendCode);//发送
}
我是想通过判断一个字节是否发送完成,如果上个字节发送完成后再接着发送下一个字节。这个用法测试时串口的数据没有发出来。
  • 是这个:
    while(ROM_UARTBusy(UART2_BASE))
    {
    ROM_UARTCharPutNonBlocking(UART2_BASE, SendCode);//发送
    }
  • 我用TM4C123测试了一下,加了

    while(ROM_UARTBusy(UART0_BASE))//add by susan
    {
    // delay here until transmission is complete
    }

    可以成功发送,代码如下

    //*****************************************************************************
    //
    // uart_echo.c - Example for reading data from and writing data to the UART in
    //               an interrupt driven fashion.
    //
    // Copyright (c) 2012-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.4.178 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>UART Echo (uart_echo)</h1>
    //!
    //! This example application utilizes the UART to echo text.  The first UART
    //! (connected to the USB debug virtual serial port on the evaluation board)
    //! will be configured in 115,200 baud, 8-n-1 mode.  All characters received on
    //! the UART are transmitted back to the UART.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // The UART interrupt handler.
    //
    //*****************************************************************************
    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Get the interrrupt status.
        //
        ui32Status = ROM_UARTIntStatus(UART0_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        ROM_UARTIntClear(UART0_BASE, ui32Status);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(ROM_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART0_BASE,
                                       ROM_UARTCharGetNonBlocking(UART0_BASE));
    
            //
            // Blink the LED to show a character transfer is occuring.
            //
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
    
            //
            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
            //
            SysCtlDelay(SysCtlClockGet() / (1000 * 3));
    
            //
            // Turn off the LED
            //
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
    
        }
    }
    
    //*****************************************************************************
    //
    // Send a string to the UART.
    //
    //*****************************************************************************
    void
    UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count)
    {
        //
        // Loop while there are more characters to send.
        //
        while(ui32Count--)
        {
            //
            // Write the next character to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);
        }
    
        while(ROM_UARTBusy(UART0_BASE))//add by susan
           {
             // delay here until transmission is complete
           }
    }
    
    //*****************************************************************************
    //
    // This example demonstrates how to send a string of data to the UART.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPUEnable();
        ROM_FPULazyStackingEnable();
    
        //
        // Set the clocking to run directly from the crystal.
        //
        ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                           SYSCTL_XTAL_16MHZ);
    
        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Enable the GPIO pins for the LED (PF2).
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    
        //
        // Enable the peripherals used by this example.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable processor interrupts.
        //
        ROM_IntMasterEnable();
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Configure the UART for 115,200, 8-N-1 operation.
        //
        ROM_UARTConfigSetExpClk(UART0_BASE, ROM_SysCtlClockGet(), 115200,
                                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_PAR_NONE));
    
        //
        // Enable the UART interrupt.
        //
        ROM_IntEnable(INT_UART0);
        ROM_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
    
    
    
    
        //
        // Prompt for text to be entered.
        //
        UARTSend((uint8_t *)"\033[2JEnter text: ", 16);
    
        //
        // Loop forever echoing data through the UART.
        //
        while(1)
        {
        }
    }
    

  • 好的,我按照您这样测试下。谢谢您。
  • 好的,期待您的反馈~
  • 您好,您提供的这种方式确实是可行的,但是我想问下,标题中我那种方式不合理吗?还有就是我想通过判断忙闲来确定CPU是否需要去执行发送。如果该位忙,则跳出去执行其他任务。UART的发送需要占用CPU的时间对吧?
  • 若是可以的话,请您上传一下您的代码,谢谢。我对您的描述有些疑惑
  • 您好, 我明白了。下面是部分代码,单字节发送:

    (1)while(1)

    {

    if(Uart2RX_OK==1)

           {

               Slave_B(Rx_Uart[UART2].RxBuffer,Rx_Uart[UART2].InPointer,UART2);

           }

    }

    (2)void Slave_B(uint8_t * ComRecBuffer,uint16_t Length,int iPort)

    {

       if(ComRecBuffer[0]==Rx_Uart[iPort].self_Addr)

       {

           Tempaddr=(ComRecBuffer[2]<<8)+ComRecBuffer[3];

           Templen=(ComRecBuffer[4]<<8)+ComRecBuffer[5];

           if(ComRecBuffer[1]==0x03)

           {

               dataClass=CheckAdde(Tempaddr,Tempaddr+Templen-1);

               if(send_count_B==0)

               {

                   YC_YX(Tempaddr,Templen,iPort,ComRecBuffer[1],dataClass);

                }

               else

               {

                   if(send_count_B<Templen*2+5)

                   {

                       YC_YX(Tempaddr,Templen,iPort,ComRecBuffer[1],dataClass);

                   }

                   else

                   {

                       send_count_B=0;

                       Uart2RX_OK=0;

                       Rx_Uart[iPort].RxCounter=0;

                       Rx_Uart[iPort].InPointer=0;

                   }

               }

           }

       }

    }

    (3)void Pack_YC_YX_Modbus(uint16_t StartValue,uint16_t Length,int iPort,uint8_t FCCode,uint16_t DataClass)

    {

       unsigned int i=0;

       uint16_t getvalue;

       unsigned int CRCValue=0;

       Command[0]=Rx_Uart[iPort].self_Addr;

       Command[1]=FCCode;

       Command[2]=Length*2;

       for(i=0; i<Length; i++)

       {

           getvalue=SearchDataValue(StartValue+i,DataClass);

           Command[3+2*i]   = (getvalue>>8)&0xff;

           Command[3+2*i+1] = getvalue&0xff;

       }

       CRCValue=CRC16(Command,Length*2+3);

       Command[Length*2+3]=(CRCValue>>8)&0xff;

       Command[Length*2+4]=CRCValue&0xff;

       if(iPort==UART2)

       {

           if(send_count_B<Length*2+5)

           {

               TxFIFOFill_UART2(iPort,Command[send_count_B],1);

               send_count_B++;

           }

       }

       else if(iPort==UART6)

       {

           if(send_count_D<Length*2+5)

           {

               TxFIFOFill_UART6(iPort,Command[send_count_D],1);

               send_count_D++;

           }

       }

    else

    {

    ;

    }

    }

    (4)void TxFIFOFill_UART2(int iport,unsigned char  SendCode,unsigned int Length)

    {

    unsigned int j=0,my_length;

    my_length=Length;

    UART2ENABLETX;

    ROM_UARTCharPutNonBlocking(UART2_BASE, SendCode);//发送UARTCharPut  ROM_UARTCharPut

    while(ROM_UARTBusy(UART2_BASE))//add by susan

    {

    // delay here until transmission is complete

    }

    UART2DISABLETX;

    }

    我的问题是:上述代码是UART2的执行过程,UART3与UART2执行过程和方法一致,如果中断来临时间点基本一致的话(未配置中断优先级),两个串口的输出从测试结果来看,UART3的输出必须是在等UART2完成后才执行。

    上图1~6的执行是否占用CPU的资源呢?

  • 应该是均占用CPU时间,UART有两个FIFO,是每个UART都具有2个FIFO,而且均是独立的是吗?但是这两个FIFO都是通过寄存器UARTDR来访问的,那要是两个独立的UART,如果是同时响应了中断后,FIFO处理时是不能同时处理的是吧?
  • Susan,您好,帮我回复下这个问题吧?我主要的疑问点是ROM_UARTCharPutNonBlocking这个函数的执行是否占用CPU的资源?
  • 抱歉,之前miss掉了您这个帖子

    pei gong 说:
    这两个FIFO都是通过寄存器UARTDR来访问的,那要是两个独立的UART,如果是同时响应了中断后,FIFO处理时是不能同时处理的是吧

    您的理解是正确的,并且如您之前所说这个函数的执行是占用CPU时间的

    FIFO的原理和使用都是类似的,网络上有一些讲解的文章,您可以看一下

    https://blog.csdn.net/houqi02/article/details/51683635 

    https://blog.csdn.net/wxc971231/article/details/95624942 

    另外建议用中断处理方式,根据需求设定FIFO中断级位,SCIFFRX中的RXFFIL设置接收中断,cpu接收到一定数目的字符后去读FIFO中的数据,避免数据丢失。

  • 好的,谢谢您。
  • 好的,谢谢您。
  • 很高兴能帮到您
  • susan,您好, while(ROM_UARTBusy(UART0_BASE))//add by susan
    {
    // delay here until transmission is complete
    }
    这个函数是判断FIFO中的数据是否已经全部从移位寄存器中移出,为什么需要再此处等待?就是标题中if判断这种方式有何不妥呢?
  • Susan,您好,我这边已处理正常了,之前遇到问题如果还是因为应用逻辑写的不合理导致。针对UartBusy函数,可根据实际情况,使其while()一直等待,或者也可通过if()判断,直到其空闲时再处理。
  • 谢谢您的反馈!