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.

[参考译文] CCS/EK-TM4C123GXL:在将我的自制队列与 UART 一起使用时遇到问题

Guru**** 2350610 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/611157/ccs-ek-tm4c123gxl-having-trouble-using-my-self-made-queue-with-uart

器件型号:EK-TM4C123GXL

工具/软件:Code Composer Studio

大家好、我正在尝试将 UART 与队列结合使用。

我觉得逻辑方面没有缺陷、但在这方面工作起来很奇怪。

例如、我添加了"状态13 0模式1 CALSTATE 0"等内容、结果显示为"STATEE 13 0模式1 CALSTATE 0"或"状态33 0模式1 CALSTATE 0"

我尝试调试、无法理解我遇到的情况。

为了进行调试、首先我设置了一个数组变量、并存储了 MCU 发送的数据。 我确认队列的数据正常、队列中的数据不正常。

但是、如果我每次都使用断点、则从队列中输出的数据会突然工作正常。

所以、我认为有问题、但我无法理解发生了什么。

随附我正在使用的代码

--------------------------------------------------------------------

<<<<<<<< >>>

#define buffersize 256

类缓冲器

专用:
   volatile uint8_t data[buffersize];
   volatile uint32_t length;
   volatile uint32_t size;
   volatile uint32_t index;
   volatile uint32_t lineNum;
   volatile uint32_t readIndex;
   volatile uint32_t writeIndex;

公开:
   void init();
   void addToEnd (uint8_t data);
   uint32_t byteAvailable();
   uint32_t lineAvailable();
   uint8_t getFromFront();
   uint8_t peek();
   void addArrayToEnd (const char* pui8Buffer);
   内联 bool full();
   内联 bool empty();

};

<<<<<<<< >>>

空缓冲区:init()

   长度= 0;
   size = buffersize;
   索引= 0;
   lineNum = 0;
   readIndex = 0;
   writeIndex = 0;

   for (int i=i;<BUFFERSIZE; i++) 0
       DATA[i]= 0;

空缓冲区:addToEnd (uint8_t cData)

   IntMasterDisable();
  if (!full())(如果(!full()))

   {
    Data[writeIndex]= cData;
    writeIndex =(writeIndex+1)%size;

    if (cData ='\n')
     lineNum++;

   }

   IntMasterEnable();

空缓冲区::addArrayToEnd (const char* pui8Buffer)

   IntMasterDisable();

   while (* pui8缓冲区)
   {
   if (full ())

     中断;

    if (*pui8Buffer='\n')
     lineNum++;

    data[writeIndex]=* pui8Buffer;
    pui8Buffer++;
    writeIndex =(writeIndex+1)%size;

   }

   IntMasterEnable();

uint32_t 缓冲区:byteAvailable()

   返回(writeIndex+size-readIndex)%size;

uint32_t 缓冲区:lineAvailable()

   返回 lineNum;

uint8_t 缓冲区::getFromFront()

   IntMasterDisable();

   静态字符返回值;
   返回值= 0;
  

   if (!empty())(如果!empty())
   {
    返回值= data[readIndex];
    readIndex =(readIndex+1)%size;

   }

   if (返回值='\n')
    lineNum--;

   IntMasterEnable();

   返回返回值;

uint8_t 缓冲区::peek()

   IntMasterDisable();

   静态 uint8_t 返回值;

   if (empty())
    返回值= 0;

   其他
    返回值= data[readIndex];

   IntMasterEnable();

   返回返回值;

内联 bool 缓冲区:empty()

 if (readIndex == writeIndex)
  返回 true;

 其他
  返回 false;

内联 bool 缓冲区:full()

 if (((writeIndex+1)%size)== readIndex)
  返回 true;

 其他
  返回 false;

<<<<<< >>>

空 UARTIntHandler (空)

   IntMasterDisable();

   静态 uint32_t ui32Status;

   //
   //获取中断状态。
   //
   ui32Status = UARTIntStatus (UART0_BASE、TRUE);

   //
   //清除已发出的中断。
   //
   UARTIntClear (UART0_BASE、ui32Status);

   //
   //在接收 FIFO 中有字符时循环。
   //
   IF (ui32Status 和 UART_INT_TX)
       serial.transmit ();

   if (UARTCharsAvail (UART0_BASE))
   {
       serial.receive();

   }

   IntMasterEnable();

空序列:init()

   SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
   SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);

   //
   // UART0 U0RX 的使能引脚 PA0
   //
   GPIOPinConfigure (GPIO_PA0_U0RX);
   GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0);

   //
   // UART0 U0TX 的使能引脚 PA1
   //
   GPIOPinConfigure (GPIO_PA1_U0TX);
   GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_1);

   UARTConfigSetExpClk (UART0_BASE、SysCtlClockGet ()、921600、(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
   
   //
   //启用 UART 中断。
   //
   UARTFIFOLevelSet (UART0_BASE、UART_FIFO_TX2_8、UART_FIFO_RX4_8);
   IntEnable (INT_UART0);
   UARTIntEnable (UART0_BASE、UART_INT_RX | UART_INT_RT | UART_INT_TX);

   IntRegister (INT_UART0、UARTIntHandler);
   //IntPrioritySet (INT_UART0、0xE0);


   txBuffer.init();
   rxBuffer.init();

   超时= 1000;

空串行:Transmit ()

   bool doTransmit = true;
   while (UARTSpaceAvail (UART0_BASE)&& doTransmit)
   {
   if (!txBuffer.empty())
       {
   uint8_t cData = txBuffer.peek();
     txBuffer.getFromFront();
        if (cData)
         UARTCharPutNonBlocking (UART0_BASE、cData);

       }

       其他
       {
        doTransmit = false;
       }

   }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    可能与发送器和接收器之间的波特率有关。 您使用的波特率为921600。 您可以尝试115200吗? 默认情况下、几乎所有 TivaWare 示例都使用此波特率。 看看它是否会产生影响、以便您可以在依赖于波特率的情况下隔离问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    给 Charles。

    感谢您的建议。 我听从了你的建议、效果更好。 但我仍然无法理解为什么波特率会起作用。 您能告诉我921600和115200之间的区别吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Young、
    您的 UART 源时钟是什么? UART 位时间由 UART 时钟导出(或可分频)。 在高波特率下、很难进行分频并接近预期的波特率。 其次、发送器和接收器之间的距离是多少? 我认为距离越长、在极高的波特率下、误差越容易发生。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    首先、  

    我使用如下所示的函数生成了主时钟。 当我使用  SysCtlClockGet ()函数时、它会显示80MHz

    SysCtlClockSet (SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz);  //// 80MHz

    我通过使用系统时钟作为 UART 时钟源来设置波特率。

    UARTConfigSetExpClk (UART0_BASE、SysCtlClockGet ()、115200、(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

    其次、我将使用 UART0、它通过自己的 LaunchPad 本身转换为 USB。 因此、我认为第二个问题不是问题。

    实际上,我使数组用于存储发送到  UARTCharPutNonBlocking ()的数据,并创建断点以查看数据,此时该数据已崩溃。

    更详细地描述它、

    在 UARTCharPut 每次设置断点时... FUNC、数据似乎正常。 2.当我自己随机设置断点时,数据会崩溃。

    可能是因为我的错误而发生这种情况、但由于显示的结果与调试结果相同、我认为这意味着什么。

    但是、有了这个事实、我无法理解正在发生的情况。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Young、
    调用 UARTCharPutNonBlocking()时,请检查返回的值,以查看返回的值是否为 false 或 true。 如果为 false、则表示写入 FIFO 失败、可能 FIFO 已满、在这种情况下、您需要再次重试。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我使用 UARTFIFOLevelSet (UART0_BASE、UART_FIFO_TX1_8、UART_FIFO_RX4_8)设置五电平;
    在 UARTIntterupt 函数中、我放置了这个逻辑

    IF (ui32Status 和 UART_INT_TX)

    bool doTransmit = true;
    while (UARTSpaceAvail (UART0_BASE)&& doTransmit)

    if (!txBuffer.empty())

    uint8_t cData = txBuffer.peek();

    if (cData)
    if (UARTCharPutNonBlocking (UART0_BASE、cData))
    txBuffer.getFromFront();


    //UARTCharPutNonBlocking (UART0_BASE、txBuffer.getFromFront ());

    其他

    doTransmit = false;






    我认为通过使用 UARTSpaceAvail (),我阻止了添加比 FIFO 可以处理的更多数据的可能性,并且可能获得返回值 UARTCharPut...()函数会有所帮助,所以我添加了一个,但它仍然显示添加了一些相同的字符或未使用的数据。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    看看 getFromFront。 当为空时、它返回什么?

    顺便说一下、我怀疑 PC-Lint 会捕获到这种情况、尽管静态声明可能隐藏了错误。 该静态声明可能也不应该是它们。

    Robert

    哦、为什么它依赖于波特率? 两个字、比赛条件。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    看看 getFromFront。 当为空时、它返回什么?

    ->它返回0、而不是上次调用返回的存储。 我在函数启动时清除了它。

    顺便说一下、我怀疑 PC-Lint 会捕获到这种情况、尽管静态声明可能隐藏了错误。 该静态声明可能也不应该是它们。

    ->我使用静态的原因是、如果发生另一个 intterupt、我担心内存分配问题。 此外、我确实使用了静态变量、但我也通过在其中放置0来清除变量。

    哦、为什么它依赖于波特率? 两个字、比赛条件。

    ->我知道可能会有竞争状况导致问题、但我认为我尽力防止这种情况。

    我仅在主循环中使用了 addBuffer 函数、当我创建 addBuffer 函数时、我将 IntDisable 函数放置在第一个函数中、将 IntEnable 函数放置在最后一个函数中、以防止在添加元素时发生中断。

    当从缓冲区获取元素时、此处也添加了 IntDisable 和 IntEnable

    如果您发现我找不到的错误、请提醒我对我造成问题的特定代码部分。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    好的、我没有看到零初始化(这是提出问题而不是断言的原因之一)。 这不是一个有用的安全结构、实际上可能会导致比它解决的更多的问题。

    说到不安全的构造、请查看您使用 int enable/disable 对的情况。 这是一种固有的不安全模式。 如果存在嵌套使用、则失败。 更安全的版本是使用禁用/恢复序列。 即使是嵌套的、这也是安全的、但确实需要更多的设置工作。 但是、在任何情况下、使用该结构的频率都过高。 如果只允许单个生产者和使用者、则只需使索引/指针提升原子化。 如果您允许多个、则需要提供某种所有权令牌、可能是通过互斥。

    Robert

    哦、如果您使用了粘贴代码、您的代码将更容易遵循 功能