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.

[参考译文] MSPM0C1104:向 UART 发送多于4字节的十六进制值。

Guru**** 2591700 points
Other Parts Discussed in Thread: MSPM0C1104

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1362038/mspm0c1104-send-hex-values-to-uart-more-than-4-bytes

器件型号:MSPM0C1104

我正在使用 MSPM0C1104、但向 UART 发送十六进制值时遇到困难、请建议我如何将十六进制值发送到超过4字节的 UART、例如 #define OpenLID  {0x11、0x22、0x33、0x44、0x55、0x66};



以下是源代码。

/*
* Configure the internal loopback mode.
* Note that data received on the UART RXD IO pin will be ignored when
* loopback is enabled.
*/
#define ENABLE_LOOPBACK_MODE true

/*
* Number of bytes for UART packet size
* The packet will be transmitted by the UART.
* This example uses FIFOs with polling, and the maximum FIFO size is 4.
* Refer to interrupt examples to handle larger packets.
*/
#define UART_PACKET_SIZE (4)

/* Delay for 5ms to ensure UART TX is idle before starting transmission */
#define UART_TX_DELAY (160000)
#define OpenLid {'M', 'S', 'P', '!'};//{0x11,0x22, 0x33, 0x44};

/* Data for UART to transmit */
uint8_t txPacket[UART_PACKET_SIZE];//= {'M', 'S', 'P', '!'};

/* Data received from UART */
uint8_t rxPacket[UART_PACKET_SIZE];

void UART_Write_buffer(uint8_t *data, int size);
void UART_Write(uint8_t *DataBuffer,uint8_t size);

void UART_Write_buffer(uint8_t *data, int size) {
for (int i=0; i<size; i++){
txPacket[i] = data[i]; //register

}
UART_Write( txPacket, size);
}

void UART_Write(uint8_t *DataBuffer,uint8_t size){

/* Optional delay to ensure UART TX is idle before starting transmission */
delay_cycles(UART_TX_DELAY);

/* Set LED to indicate start of transfer */
DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
for (int i=0; i<size; i++){
/* Fills TX FIFO with data and transmits the data */
DL_UART_Main_fillTXFIFO(UART_0_INST, &txPacket[i], UART_PACKET_SIZE);
}
/* Wait until all bytes have been transmitted and the TX FIFO is empty */
while (DL_UART_Main_isBusy(UART_0_INST))
;
}

int main(void)
{
SYSCFG_DL_init();


// /*
// * Wait to receive the UART data
// * This loop expects UART_PACKET_SIZE bytes
// */
// for (uint8_t i = 0; i < UART_PACKET_SIZE; i++) {
// rxPacket[i] = DL_UART_receiveDataBlocking(UART_0_INST);
// }

/* If write and read were successful, toggle LED */
while (1) {
uint8_t arr[] = OpenLid;
UART_Write_buffer(arr, 5);
//UART_Write(txPacket,4);
DL_GPIO_togglePins(GPIO_LEDS_PORT,
GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN);
delay_cycles(1200000);
}
}

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

    嗨、Harshita、

    我认为只需要用您想要发送的十六进制值填充 txPacket[]、并将值的数目传递给 UART_Write 函数。

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

    您将获得什么?

    请注意、您执行此操作:

    DL_UART_Main_fillTXFIFO (UART_0_INST、&txPacket[i]、UART_packet_size);

    我假设您要在 txPacket 中发送4个字节。

    您应该忽略 for 循环并写入:

    DL_UART_Main_fillTXFIFO (UART_0_INST、&txPacket[0]、UART_PACKET_SIZE);

    或使用 for 循环并执行:

    DL_UART_Main_fillTXFIFO (UART_0_INST、&txPacket[i]、1);

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

    unsigned char txPacket[UART_packet_size];
    unsigned char arr[]={0x11、0x22、0x33、0x44、0x66、0x88、0x77};
    我已经将数组分配为 unsigned char、这解决了我的问题。 我将使用 sscom 作为串行视图、并在终端中启用 show hex 选项。


    但是、我面临的一个未决问题是我想在 txPacket 中发送超过4个字节。 你能建议我怎么做吗?

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

    嗨、Harshita、

    问题是 UART FIFO 最多只能容纳4个字节。  要传输超过4个字节、您需要使用 UART ISR 处理程序来管理额外的字节。

    或者、您可以使用此 driverlib 函数、一次仅发送一个字节。  您可以将其放入 for ()循环并发送任意数量的字节。

    /**
    *@短块以确保传输在发送数据之前已准备就绪
    *
    *阻塞之后将数据放入 TX FIFO、确保 TX FIFO 不是
    *已满。 将以不定义的方式等待、直到 TX FIFO 中有空间为止。 参阅
    *用于额外传输选项的相关 API。
    *
    *可用于任何小于或等于8位的数据传输。
    *
    *@param[in] uart 指针指向外设的寄存器覆盖
    *@param[in]要发送的数据
    *
    *@sa DL_UART_transmitData
    *@sa DL_UART_transmitDataCheck
    */
    void DL_UART_transmitDataBlocking (UART_Regs * uart、uint8_t data);

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

    尊敬的 Dennis:

    我又遇到一个错误。 由于我是从 UART 发送十六进制值、因此接收值也是十六进制。

    空 UART_Write (uint8_t DataBuffer[]、uint8_t Size){

    /*可选延迟、以确保 UART TX 在开始传输之前处于空闲状态*/
    delay_cycles (UART_TX_DELAY);

    /*设置 LED 以指示传输开始*/
    DL_GPIO_clearPins (GPIO_LEDS_PORT、GPIO_LEDS_USER_LED_1_PIN);

    for (int i=0;i<size;i++){
    /*用数据填充 TX FIFO 并发送数据*/
    // DL_UART_Main_fillTXFIFO (UART_0_INST、&txPacket[i]、1);
    DL_UART_transmitDataBlocking (UART_0_INST、txPacket[i]);

    }

    /*等待直到所有字节都已发送且 TX FIFO 为空*/
    while (DL_UART_Main_isBusy (UART_0_INST))

    }

    void uart_READ (uint8_t size){
    /*
    *等待接收 UART 数据
    *该循环需要 UART_PACKET_SIZE 字节
    */
    对于(uint8_t i = 0;i < size;i++){
    rxPacket[i]= DL_UART_receiveDataBlocking (UART_0_INST);
    }
    }

    以上就是这些函数。  
    这里我要将 unsigned char arr[]={0x34、0x1A、0x00、0x0E、0x71}传递给 UART 写入函数。  
    在串行端口 UART TX 数据是34 1A 00 0E 71 (正确)、但 UART (读取) Rx 数据是 D0 C0 C4 F8 E4 FE。 但它应该是43 01 00 0E 71 (我应该在 UART 读取时得到这个响应)。  
    但无论如何、我的 UART 从器件会响应。 它只有在获得正确的 TX 数据时才会响应。 从设备什么也不做、只要它获得响应命令、它就会立即响应。

     
    在串行端口 I 启用后显示十六进制选项、写入数据正确、但读取数据不正确。 问题在哪里? 要获取正确的十六进制数据、我需要对 UART_READ 执行什么操作。 Typecasting 或其他什么?

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

    "在串行端口 UART TX 数据是34 1A 00 0E 71"

    这是否意味着您使用示波器进行了检查?

    如果是这样、并且发送方正在以正确的波特发送正确的字节、并且示波器以正确的波特显示正确的字节、这显然在接收器中。

    是否设置为正确的波特? 是否存在可能使波特率降低10%的时钟错误? 是否检查了溢出错误?

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

    我使用 BUSCLK 时钟源、总线速率为115200、即 OVS 16x。 但计算出的总谐波率为11524610、误差百分比为0.04%。 这会导致问题。

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

    接收器怎么样?

    您的电路板是否使用晶体?

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

    嗨、Harshita、

    根据 Keith 的建议、您是否有示波器或逻辑探头可以捕获正在传输的数据的屏幕截图?

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

    嗨、Dennis、
    我已经了解数据传输并在通信端口上获得正确的响应。
    但还需要一个帮助、

    以下函数是我用于 UART 读取的。

    void uart_READ (uint8_t size){
    /*
    *等待接收 UART 数据
    *该循环需要 UART_PACKET_SIZE 字节
    */
    对于(uint8_t i = 0;i < size;i++){
    rxPacket[i]= DL_UART_receiveDataBlocking (UART_0_INST);
    }
    }

    在 main()中

    SYSCFG_DL_init ();

    ---

    ---

    while (1){

    ---

    ---

    ---

    UART_Write_buffer (arr、UART_packet_size);

    I2C_Write_buffer (REG_14、0x0B);
    // delay_cycles (8000000);

    UART_READ (UART_PACKET_SIZE); //预期:如果此函数未成功读取包、它将退出该函数并切换 LED  

    DL_GPIO_togglePins (GPIO_LEDS_PORT、
    GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN);
    delay_cycles (12000000);

    }

    }
    在这里、只要从器件未发送 UART Rx 包 、主函数就卡在 UART_READ()位置、不会再次切换和发送 UART 写入。

    我希望即使 UART 读取不成功的主循环(继续)也反复发送 Uartwrite、直到从器件发送 Rx 数据包。 但此处的主循环卡在 UART_READ 处、没有继续前进。 如何根据我的应用程序继续使用场景什么是适合 UART 读取的 API。

    请提供帮助。

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

    嗨、Harshita、

    看起来你正在调用的函数 uart_read()是一个阻塞函数。  这意味着该函数在接收到字节之前不会返回。  在此函数内部、调用哪个 MSPM0 driverlib UART 函数?  

    以下函数定义不会阻塞、但不能保证其中是否有数据。

    /**
     *  @brief      Reads data from the RX FIFO
     *
     *  Reads the data from the RX FIFO without checking its status. Use if
     *  already sure the RX FIFO has data available. See related APIs for
     *  additional receive options.
     *
     *  @param[in]  uart  Pointer to the register overlay for the peripheral
     *
     *  @return     The data in the RX FIFO
     *
     *  @sa         DL_UART_receiveDataBlocking
     *  @sa         DL_UART_receiveDataCheck
     */
    __STATIC_INLINE uint8_t DL_UART_receiveData(UART_Regs *uart)

    相反,我建议首先通过调用下面的函数来检查 FIFO 中是否有数据,然后再调用 UART_READ()函数。

    /**
     *  @brief      Checks the RX FIFO before trying to transmit data
     *
     *  Checks if the RX FIFO is already empty before trying to read new data from
     *  the FIFO. Exits immediately if empty rather than trying to block. See
     *  related APIs for additional receive options.
     *
     *  Can be used for any data transfers that are less than or equal to 8 bits.
     *
     *  @param[in]  uart   pointer to the register overlay for the peripheral
     *  @param[in]  buffer a buffer to write the received data into
     *
     *  @return     If the receive occurred
     *
     *  @retval     true  if data was read from the RX FIFO
     *  @retval     false if the RX FIFO was empty and data was not read
     *
     *  @sa         DL_UART_receiveData
     *  @sa         DL_UART_receiveDataBlocking
     */
    bool DL_UART_receiveDataCheck(UART_Regs *uart, uint8_t *buffer);

    代码如下所示。  显然、更改变量名称以匹配您使用的 UART 和缓冲区。

        if(DL_UART_receiveDataCheck(UART_0_INST, RxBuffer) == true)
            UART_Read(uart_packet_size);

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

    尊敬的 Dennis:

    我需要检查 rxbuffer 以获得整个数据、直到 UART_packet_size。 但是、如果它只有一个字节 (DL_UART_receiveDataCheck (UART_0_INST、RxBuffer)函数、则为 true。 但我想检查 Rx 缓冲区中是否有所有  UART_PACKET_SIZE 数据、然后仅 UART_READ。 有什么方法可以做到这一点。

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

    您需要将每个字节输入到缓冲区中并使大小变量递增。 您可以创建一个 UART_Check()函数、该函数将返回接收到的字节数。 如果大小合适、请处理缓冲器。

    我在 main 中执行类似这样的操作。 我直接发送 ASCII、因此"\0"带外。 我还将 LF 和 CR 用作数据包结束标记、因此我不跟踪其大小:

    if (RXdata != 0) {
          data = RXdata;
          RXdata = 0;
    
          if ((data == '\r') || (data == '\n')) {
            // do the command
            // for now just, echo
    
            if (rxbufidx != 0) {
              // weed out naked \n's
              strcat(rxbuf, "\n\r");
              StartSerialTX(rxbuf);
            }
    
            // zero the buffer
            rxbuf[0] = '\0';
            rxbufidx = 0;
    
          } else {
    
            rxbuf[rxbufidx++] = data;
            rxbuf[rxbufidx] = '\0';
          }
        }
    
    My interrupt looks like this:
    void BACKCHANNEL_INST_IRQHandler(void) {
      switch (DL_UART_Main_getPendingInterrupt(BACKCHANNEL_INST)) {
    
      case DL_UART_MAIN_IIDX_RX:
        RXdata = DL_UART_Main_receiveData(BACKCHANNEL_INST);
    
        break;
    
      case DL_UART_MAIN_IIDX_TX:
        if (TXData[TXChar] != '\0') {
          DL_UART_Main_transmitData(BACKCHANNEL_INST, TXData[TXChar++]);
        } else {
          TXChar = -1;
        }
    
        break;
    
      default:
        break;
      }
    }

    您可以将接收到的数据放入缓冲区并在中断中递增计数。

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

    感谢您分享您的代码 Keith。  Harshita、这能满足您的需求吗?

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

    实际上、我要在没有中断的情况下执行。 正如 Keith 建议的、创建 UART_Check 函数、我们可以不中断地创建它。 我使用 UART 多字节轮询方法。

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

    你的 uart_check()会做的是看看数据字节是否可用。 如果是、将其放入缓冲器中。 如果已接收帧大小字节、请设置一个标志。 但是根据其余代码的作用、您可能会丢失字节。

    中断可以在幕后完成所有操作。

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

    尊敬的 Keith 和 Dennis:

    在紧急基础上需要另一个解决方案。 我的 PCBA 设计使用 MSPM01104芯片组 VSSOP20。 此处使用了除 PA22和 PA23 (我之前 用于测试点)之外的所有引脚。 但现在我要将这些引脚设置为 GPIO SW UART。 但是、当我将 PA22启用为 UART_GPIO_TX 时、我将收到启用 CLKOUT 错误。 请帮助我解决此错误。

    路由高频时、当前选择的 CLK_OUT 引脚不可用。 请选择不同的 CLK_OUT 源或不同的引脚。 有关引脚限制、请参阅器件文档。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    PA22显示资源冲突。 有什么方法可以处理这个问题。

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

    对于高频时钟、您需要对其进行分频、以使频率达到 GPIO 可以处理的水平。

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

    Keith、您好、您能给我提供软件 GPIO UART 的示例代码吗?

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

    我通常会将人们指向 Arduino SoftwareSerial 代码、它实现了位拆裂 UART。