I think, You didn't understand my question completely. my question was for rules of c language.You can create a structure x which contains different data types.
Not just the compiler. Look at my example. What is the final value of x after the assignment? Is it 2 or is it 'L'.Thanks for clearing the doubts. I wrote code with two storage classes and one variable. Experiment show that we cannot have two storages with one variable.
Why we can't have two storages with one variable. What is the purpose of the C language creators behind this rule?
I think the reason is that if there are two storage classes then the compiler will get confused where to store the variable
The times you really need unions to clarify software are typically with arbitrary hardware interfaces to I/O devices. If you need to transform a untyped bit-based interface into the typed C structured universe with unions it will likely be system and and hardware dependant (like a 24-bit adc buffer, index and control bits) on a few levels.Not just the compiler. Look at my example. What is the final value of x after the assignment? Is it 2 or is it 'L'.
Having the same name for two different things causes problems in everyday contexts, too. We've all experienced this when we are in a group of people and two of them have the same first name.
One thing that C has, which are seldom used and, when they are, are often abused and cause problems, are unions whereby you have essentially the opposite, multiple variable identifiers and storage classes associated with the same storage space. This can be a very powerful and useful tool, if used judiciously, but it makes it impossible for the compiler to enforce good typing.
/* for 24-bit transmit and extra status data */
typedef struct A_data {
uint32_t dummy12 : 12; // dummy space for adc data
uint32_t nullbits : 2;
uint32_t index : 3; //adc channel select
uint32_t single_diff : 1;
uint32_t start_bit : 1;
uint32_t dummy8 : 8;
uint32_t finish : 1;
uint32_t in_progress : 1;
} A_data;
/* upper-> lower bytes to 32 bit word for ADC/DAC, etc ... */
union bytes4 {
uint32_t ld;
uint8_t bd[4];
};
/* upper/lower bytes to 16 bit word for ADC/DAC, etc ... */
union bytes2 {
uint16_t ld;
uint8_t bd[2];
};
/* used to hold 24-bit adc buffer, index and control bits */
union adc_buf_type {
uint32_t ld;
uint8_t bd[4];
struct A_data map;
};
typedef struct {
union adc_buf_type mcp3208_cmd;
uint16_t potValue;
uint8_t chan;
} ADC_DATA;
void ADC_Init()
{
adcData.mcp3208_cmd.ld = 0; // clear the command word
adcData.chan = 0;
adcData.mcp3208_cmd.map.start_bit = 1;
adcData.mcp3208_cmd.map.single_diff = 1;
adcData.mcp3208_cmd.map.index = 0; // channel
appData.ADCcalFlag = true;
SPI_CS0 = 1;
}
//State machine for restarting ADC and taking new readings from pot
//Returns true when SPI data has been returned from the mpc3208; false otherwise
bool ADC_Tasks(void)
{
static uint8_t count = 0;
/* send the command sequence to the adc */
if (!adcData.mcp3208_cmd.map.in_progress) {
adcData.mcp3208_cmd.map.in_progress = true;
adcData.mcp3208_cmd.map.finish = false;
count = 0;
if (!SPI_IsTxData()) {
adcData.mcp3208_cmd.map.single_diff = 1;
adcData.mcp3208_cmd.map.index = adcData.chan;
SPI_ClearBufs(); // dump the spi buffers
SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[2]);
SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[1]);
SPI_WriteTxBuffer(adcData.mcp3208_cmd.bd[0]);
SPI_CS0 = 0; // select the ADC
SPI_Speed(0);
SPI_TxStart();
}
return false;
}
/* read the returned spi data from the buffer and format it */
if (adcData.mcp3208_cmd.map.in_progress) {
while (SPI_IsNewRxData()) {
switch (count) {
case 1:
adcData.potValue = (SPI_ReadRxBuffer()&0x0f) << 8;
break;
case 2:
adcData.potValue += SPI_ReadRxBuffer();
adcData.mcp3208_cmd.map.finish = true;
break;
default:
SPI_ReadRxBuffer(); // eat extra bytes
break;
}
count++;
}
}
/* cleanup for next time */
if (adcData.mcp3208_cmd.map.finish) {
adcData.mcp3208_cmd.map.in_progress = false;
appData.accumReady = true;
return true;
}
return false;
}
//Process the accumulator value once it is ready
//And update stored potentiometer values
void ADC_ProcAccum(void)
{
appData.potValueOld = appData.potValue; //Save previous value
appData.potValue = adcData.potValue;
}
//ADC ISR
void _ISR_NO_AUTO_PSV _ISR _ADC1Interrupt(void)
{
IFS0bits.AD1IF = 0;
//Accumulation complete
}
void GetNewADC_Chan(void)
{
adcData.chan = appData.receive_packet[9] == '1' ? 1 : 0; // update adc channel
adcData.chan += appData.receive_packet[11] == '1' ? 2 : 0;
adcData.chan += appData.receive_packet[13] == '1' ? 4 : 0;
}