0

I want to convert two times the Signal[8] values into a uint16_t word, so I can send it via the SPI port.(shift register)?

I tried the following, but it doesn't work: the code was like that, my you can compile it.

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
    }

 }
  • please add exemplary (but not trivial) content of array `Signal` and the value that you expect in variable `value`. The code does not even compile – tstanisl Sep 13 '21 at 11:33
  • the values of Signal[i] are boolean. for example to turn on a specific LED or tto blink the other one in the same time. In this case a sequence of 0 and 1 (or, 0 and 0xff) – Ahmed Fradi Sep 15 '21 at 11:46

2 Answers2

2

Endianness independent

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

or depending on endianess

uint16_t get16(volatile uint8_t *table)
{
    uint16_t result;
    memcpy(&result, table, sizeof(result));
    return result;
}
0___________
  • 60,014
  • 4
  • 34
  • 74
  • 2
    Note that `Signal` is qualified as `volatile`. There may be a reason for it – tstanisl Sep 13 '21 at 11:52
  • will it be the same result if: uint8_t value; ? – Ahmed Fradi Sep 13 '21 at 12:10
  • @Aconcagua: `int` may be 16 bits, so `table[1] << 8` could overflow, so a cast to `uint16_t` should be used. – Eric Postpischil Sep 13 '21 at 12:23
  • @EricPostpischil yes it can be - on 8 bits platforms for example (AVR like Arduino) – 0___________ Sep 13 '21 at 12:24
  • @EricPostpischil Oh, sure. Normally having it in mind, seems as if being asleep today :( – thanks for the hint. – Aconcagua Sep 13 '21 at 12:57
  • @AhmedFradi What exactly do you mean? `uint8_t value = _16bitRegister;`? There's no cast *necessary* in such case, but compilers might and usually do warn about assignment with precision loss. Actually desired in *this* case you tell the compiler so by the cast and thus it won't warn. – Aconcagua Sep 13 '21 at 12:59
2

You can combine each subsequent two bytes into the SPI port register as follows:

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... 

Analogously you split back on receiver side:

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;
}

Note: Additions or shifts by 0 are unnecessary and only added for code consistency; they will be optimised away by compiler anyway, but you can omit, if you prefer. Similarly the casts in second case, but these in addition silent the compiler from warning about precision loss.

Note, though, that even though promotion to int occurs in first case int might only be of size of 16 bits – and as you apparently operate on a MCU chances for rise – in which case the shift could provoke overflow, thus undefined behaviour, thus the cast should be applied in any case!

Aconcagua
  • 24,880
  • 4
  • 34
  • 59