【问题标题】:how Converting 2 arrays of bytes (uint8_t) into a word (uint16_t)?如何将 2 个字节数组 (uint8_t) 转换为一个字 (uint16_t)?
【发布时间】:2021-09-13 11:16:05
【问题描述】:

我想将 Signal[8] 值的两倍转换成一个 uint16_t 字,这样我可以通过 SPI 端口发送它。(移位寄存器)?

我尝试了以下方法,但它不起作用: 代码是这样的,我的你可以编译它。

void senddata(void){
    
    uint8_t NZero = 0;
    uint16_t timeout;
    uint8_t value ;
    volatile uint8_t Signal[8]={RGB_NC_0, RGB_1, RGB_2, RGB_3, RGB_4, RGB_5, RGB_6, RGB_NC_7}; // to be set by the state machine
    volatile uint8_t SPIData[16]={0};
    
for(int i=0;i<8;i++){
        nonZero|= Signal[i];
        }
  int i , j;
  //Set LATCH low
    GPIO_WriteBit(LED_LATCH_PORT, LED_LATCH, Bit_RESET);
    //Set blank high
    GPIO_WriteBit(LED_BLANK_PORT, LED_BLANK, Bit_SET);
    //Enable SPI
    SPI_Cmd(LED_SPI, ENABLE);
  //iterate through the registers
    for(i = 2 - 1; i >=  0; i--){
  //iterate through the bits in each registers
        for(j = 8 - 1; j >=  0; j--){
           valr = Signal[i] & (1 << j);
            SPI_I2S_SendData(LED_SPI, value);
          while(SPI_I2S_GetFlagStatus(LED_SPI, SPI_I2S_FLAG_TXE) == 0 && timeout < 0xFFFF) //Odota että TXE=1
        { timeout++; }
        if(timeout == 0xFFFF){break;}
                    }
    }

    SPI_Cmd(LED_SPI, DISABLE); /*!< SPI disable */
        
    GPIO_WriteBit(LED_LATCH_PORT, LED_LATCH, Bit_SET);//Set LATCH high
        if(NZero){
            GPIO_WriteBit(LED_BLANK_PORT, LED_BLANK, Bit_RESET);//Set BLANK low
    }
    else{
            GPIO_WriteBit(LED_BLANK_PORT, LED_BLANK, Bit_SET);//Set BLANK high
    }

 }

【问题讨论】:

  • 请添加数组Signal 的示例性(但不是微不足道的)内容以及您在变量value 中期望的值。代码甚至没有编译
  • Signal[i] 的值是布尔值。例如打开特定的 LED 或同时闪烁另一个 LED。在这种情况下,一个 0 和 1 的序列(或者,0 和 0xff)

标签: c


【解决方案1】:

您可以将每个后续的两个字节组合到 SPI 端口寄存器中,如下所示:

for(size_t i = 0; i < sizeof(signal/sizeof(*signal); i += 2)
{
    spiPortRegister = (uint16_t)signal[i + 0] << 0
                    | (uint16_t)signal[i + 1] << 8;
    // send via SPI here!
}
// a *totally* generic implementation might add special handling for
// odd arrays, in your specific case you can omit... 

类似地,你在接收端分裂:

for(size_t i = 0; i < sizeof(signal/sizeof(*signal); i += 2)
{
    // receive via SPI here
    signal[i + 0] = (uint8_t) spiPortRegister >> 0;
    signal[i + 1] = (uint8_t) spiPortRegister >> 8;
}

注意:添加或移位 0 是不必要的,只是为了代码一致性而添加;无论如何,它们都会被编译器优化掉,但如果你愿意,你可以省略。与第二种情况下的强制转换类似,但这些也使编译器不会发出有关精度损失的警告。

但请注意,即使在第一种情况下升级为 intint 的大小可能只有 16 位——而且你显然在 MCU 上操作,上升的机会——在这种情况下,这种转变可能会引发溢出,因此未定义的行为,因此在任何情况下都应该应用强制转换!

【讨论】:

    【解决方案2】:

    字节序无关

    uint16_t get16(volatile uint8_t *table)
    {
        return *table | ((uint16_t)*(table + 1) << 8);
    }
    

    或取决于字节序

    uint16_t get16(volatile uint8_t *table)
    {
        uint16_t result;
        memcpy(&result, table, sizeof(result));
        return result;
    }
    

    【讨论】:

    • 请注意,Signal 被限定为 volatile。可能是有原因的
    • 如果:uint8_t 值,结果是否相同; ?
    • @Aconcagua: int 可能是 16 位,所以 table[1] &lt;&lt; 8 可能会溢出,所以应该使用对 uint16_t 的强制转换。
    • @EricPostpischil 是的,它可以是 - 例如在 8 位平台上(像 Arduino 一样的 AVR)
    • @EricPostpischil 哦,当然。通常考虑到这一点,今天好像睡着了:(——谢谢你的提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 2018-05-15
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2014-07-23
    • 2017-03-27
    相关资源
    最近更新 更多