Hello,
Yes, some operations are more difficult to code in C, compared with assembler, whislt other operations are more straight forward using C. However, there should be little difficulty in doing what you require.
I think that some of the confusion is because you originally seemed to be implying that you required a suitable preprocessor macro, i.e. #define ... It is the macros that are very limited in their application, and cannot utilize the value of a runtime variable. Such limitations do not apply to the use of C functions.
Consider the following functions that use an index value to any of the port E pins:
// Set or clear a Port E pinvoid RELE( byte index, byte state){ byte mask; mask = 1 << index; if (state) PTED |= mask; // Set port E pin else PTED &= ~mask; // Clear port E pin}// Test a Port E pinbyte RELE_test( byte index){ byte mask; mask = 1 << index; if (PTED & mask) return 1; // Pin is high else return 0; // Pin is low}
These functions can then be utilised in a further function that processes a single Opto channel in accordance with your original coding.
#define ON 1 // These are macros#define OFF 0// Process Opto channelvoid Opto_proc( byte n){ if (RELE_test(n) == OFF) { // Test output state if (OptoLow[n] >= OffTime[n]) { RELE( n, ON); // Set output state to ON OptoLow[n] = 0; } if (OPTO[n] == OFF) OptoLow[ch]++; }}
This function can then be called to process whatever channels you require.
e.g.if (Ch <= 2) Opto_proc( Ch);else OptoLow[Ch] = 0;
You can use a similar principle for your ADC code. However, I think that your posted code is a little confused. You appear to have enabled the ADC conversion complete interrupt, and then proceed to poll the COCO flag. And you don't appear to have any ISR code.
I assume that you require to cycle through the various ADC channels, but the approach taken will depend on the sampling frequency required. If you do not require the maximum sampling rate, but require to space the samples at regular intervals, the use of a timer interrupt, rather than the ADC interrupt, would be more appropriate (with the interrupt period exceeding the ADC conversion time). The procedure within the ISR (timer or ADC) would be to:
- Read the result of the previous conversion, and store the result global variable or array.
- Increment a counter variable to the next channel, and start the next conversion on this channel.
- Maybe set a flag to externally indicate outside of the ISR, that a new conversion is available.
Any global variables that are referenced both within the ISR and in the main loop will need to be defined as volatile. Do any processing of the raw ADC result within the main loop, so that the ISR executes as quickly as possible.
Regards,
Mac