Reputation: 3
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
}
}
Upvotes: 0
Views: 170
Reputation: 25536
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!
Upvotes: 2
Reputation: 67745
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;
}
Upvotes: 2