create program modes using #if in c - c

I am trying to create two modes for a program using #if and #define but the second mode isn't working why is that ?
I would aslo appreciate it if you could suggest a better way to do this.
Here's my code:
#include "Types.h"
#include <stdio.h>
void main (void)
{
u32 m;
u32 flag = 1;
do
{
printf("\nWelcome\nPress 1 for Admin mode\nPress 2 for User Mode\nYour Choice:");
scanf("%d",&m);
if (m==1)
{
#define m 1
flag = 0;
}
else if (m==2)
{
#define n 2
flag = 0;
}
else
{
printf("\nInvalid number \nPlease Try again");
}
}while(flag);
//using conditional directive to run only the portion of the code for the slected mode
#if m==1
printf("Welcome to admin mode");
#elif n==2
printf("Welcome to user mode");
#endif
}

The #define and ifs are part of the preprocessor macro.
One way to think about them is to imagine the compiler going through your files and cutting and pasting in them as an early step in compilation. When you define for example PI to be 3, it will paste 3's everywhere in your code that you have written the PI. This then tells us that it won't matter which branch of m == 1 or 2 we go down when running the program - all the preprocessor editing has already been completed!
One way to get the program built in a certain mode would be to use a flag when compiling, for example -D DEBUG. Note that we cannot use this to select mode in an already compiled program.
Preprocessor Options:
-D=
Adds an implicit #define into the predefines buffer which is read before the source file is
preprocessed.

The preprocessor if #if can only interpret values which are known at proprocessing time, which is even before compile time.
It cannot read values from variables like your u32 m.
On the other hand, a preprocessor #define is also only done at preprocessing time, it will not be influenced by being within the "then" branch or the "else" branch of an if.
Doing #defines within code blocks (e.g. if branches), or even within a function, is there for not recommended.
You did not specify how your code misbehaves, but I would not be surprised, if the #if always acts admin mode. There has been a #define m 1 before in the file (no matter what path runtime execution took), so the proprocessor will take the first option.

In the C language, al the directives starting with "#" are used by the preprocessor. The preprocessor scans your file before compilation so that "variable" m is hardcoded and you can't change it in runtime (when you're running the program).
Also, the "m" variable is declared but not used.
To change the behaviour of the program on runtime, you should use a standard variable and use a switch-case to check for the variable's value and run the appropriate code.
I would also recommend using standard types defined by the language like "int" or "char" as they have better portability through the different architectures.
Your code could be like this
#include <stdio.h>
int main (void)
{
int m;
do
{
printf("\nWelcome\nPress 1 for Admin mode\nPress 2 for User Mode\nYour Choice:");
scanf("%d",&m);
if (m == 1)
{
printf("Welcome to admin mode");
return 0;
}
else if (m == 2)
{
printf("Welcome to user mode");
return 0;
}
else
{
printf("\nInvalid number \nPlease Try again");
}
}while(m != 1 || m != 2);
return 0;
}

Related

how to include several lines of C code in one line of source code (AVR-GCC)

Is there a way to add an identifier that the compiler would replace with multiple lines of code?
I read up on macros and inline functions but am getting no where.
I need to write an Interrupt Service Routine and not call any functions for speed.
Trouble is I have several cases where I need to use a function so currently I just repeat all several lines in many places.
for example:
void ISR()
{
int a = 1;
int b = 2;
int c = 3;
// do some stuff here ...
int a = 1;
int b = 2;
int c = 3;
// do more stuff here ...
int a = 1;
int b = 2;
int c = 3;
}
The function is many pages and I need the code to be more readable.
I basically agree with everyone else's reservations with regards to using macros for this. But, to answer your question, Multiline macros can be created with a backslash.
#define INIT_VARS \
int a = 1; \
int b = 2; \
int c = 3;
#define RESET_VARS \
a = 1; \
b = 2; \
c = 3;
void ISR()
{
INIT_VARS
// do some stuff here ...
RESET_VARS
// do more stuff here ...
RESET_VARS
}
You can use inline function that will be rather integrated into place where it is called in source instead of really being called (note that behavior of this depends on several things like compiler support and optimizations setup or using -fno-inline flag feature). GCC documentation on inline functions.
For completeness - other way would be defining // do some stuff here... as pre-processor macro which again gets inserted in place where called; this time by preprocessor - so no type safety, harder to debug and also to read. Usual good rule of thumb is to not write a macro for something that can be done with function.
You are correct - it is recommended that you not place function calls in an ISR. It's not that you cannot do it, but it can be a memory burden depending on the type of call. The primary reason is for timing. ISRs should be quick in and out. You shouldn't be doing a lot of extended work inside them.
That said, here's how you can actually use inline functions.
// In main.c
#include static_defs.h
//...
void ISR() {
inline_func();
// ...
inline_func();
}
// In static_defs.h
static inline void inline_func(void) __attribute__((always_inline));
// ... Further down in file
static inline void inline_func(void) {
// do stuff
}
The compiler will basically just paste the "do stuff" code into the ISR multiple times, but as I said before, if it's a complex function, it's probably not a good idea to do it multiple times in a single ISR, inlined or not. It might be better to set a flag of some sort and do it in your main loop so that other interrupts can do their job, too. Then, you can use a normal function to save program memory space. That depends on what you are really doing and when/why it needs done.
If you are actually setting variables and returning values, that's fine too, although, setting multiple variables would be done by passing/returning a structure or using a pointer to a structure that describes all of the relevant variables.
If you'd prefer to use macros (I wouldn't, because function-like macros should be avoided), here's an example of that:
#define RESET_VARS() do { \
a = 1; \
b = 2; \
c = 3; \
while (0)
//...
void ISR() {
uint8_t a=1, b=2, c=3;
RESET_VARS();
// ...
RESET_VARS();
}
Also, you said it was a hypothetical, but it's recommended to use the bit-width typedefs found in <stdint.h> (automatically included when you include <io.h> such as uint8_t rather than int. On an 8-bit MCU with AVR-GCC, an int is a 16-bit signed variable, which will require (at least) 2 clock cycles for every operation that would have taken one with an 8-bit variable.

Checking the status of the GPIO even before main starts in embedded programming

I have two version of the boards , where a particular portion of the code gets executed based on the value of the #define BIAS_VOLTAGE
if(vol < BIAS_VOLTAGE)
{
//Execute this
}
else if (vola >= BIAS_VOLTAGE)
{
//Execute This
}
Now BIAS_VOLTAGE is #defined in a header file (#define BIAS_VOLTAGE 3)
but for a different board it is 5(5V).
The only way to detect this is by polling one GPIO status (which remains High or low after GPIO initialization in main .This is done just once).
If it is high , BIAS_VOLTAGE 3 other wise 5
Since #BIAS_VOLTAGE is used at many places , how can i know the status of GPIO at the startup ( even before main) and fix the #define value.
I know #define gets fixed at the compile time , but I need to fix this constant value at the runtime.(and this will remain forever)
Update : tool chain is IAR and microcontroller is STM32F4
You may be making a simple thing complicated:
Given:
#define BIAS_3V0 3
#define BIAS_5V0 5
int getBiasVoltage()
{
static int bias_voltage = 0 ;
// Initialise on first use...
if( bias_voltage == 0 )
{
bias_voltage = boardId() ? BIAS_3V0 : BIAS_5V0 ;
}
return bias_voltage ;
}
where boardId() is the GPIO read to identify the variant (replace with your own code as required), then your code becomes:
if(vol < getBiasVoltage() )
{
//Execute this
}
else if (vola >= getBiasVoltage() )
{
//Execute This
}
The board identity is checked once on first use and thereafter the previously determined value will be returned. Because the variable is hidden inside the function, it is read-only too.
Smells like something that should be done very early on. If so, you have to either tweak your current "CRT" (library start-up code) or write it all yourself, which is a job I would only recommend to veteran embedded devs.
Most tool chains do unfortunately come with a CRT which is useless beyond hobbyist projects. Some advice for how it should be written properly can be found here: https://stackoverflow.com/a/47940277/584518. If your current CRT doesn't resemble the advise given there - particularly if it lets the CRT run the whole of .data/.bss setup using the default internal RC oscillator, and with no wdog enabled, you should ask your tool vendor why they let incompetent quacks write the CRT.

Check only last 3 digits of sensor output

I have a library from WiringPi for DHT11 sensor and I need to modify condition which checks if the value read from sensor is good.
Sometimes the library reads bad values which are 255.255,255.255 or 55,255.255 etc.
sample output
There is the condition in the library:
if(counter==255)
break;
But it doesn't work if the value is e.g. 55,255.255
How can I modify this condition the check last 3 digits of output?
If the output is wrong, there are always "255" at the end of value.
I tried to add conditions like
if(counter==255)
break;
else if(counter==255.255)
break;
But it doesn't solve all possible situations and I realy don't know anything about C/C++
Here is the whole library:
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAX_TIME 85
#define DHT11PIN 7
#define ATTEMPTS 5
int dht11_val[5]={0,0,0,0,0};
int dht11_read_val()
{
uint8_t lststate=HIGH;
uint8_t counter=0;
uint8_t j=0,i;
for(i=0;i<5;i++)
dht11_val[i]=0;
pinMode(DHT11PIN,OUTPUT);
digitalWrite(DHT11PIN,LOW);
delay(18);
digitalWrite(DHT11PIN,HIGH);
delayMicroseconds(40);
pinMode(DHT11PIN,INPUT);
for(i=0;i<MAX_TIME;i++)
{
counter=0;
while(digitalRead(DHT11PIN)==lststate){
counter++;
delayMicroseconds(1);
if(counter==255)
break;
}
lststate=digitalRead(DHT11PIN);
if(counter==255)
break;
// top 3 transistions are ignored
if((i>=4)&&(i%2==0)){
dht11_val[j/8]<<=1;
if(counter>16)
dht11_val[j/8]|=1;
j++;
}
}
// verify checksum and print the verified data
if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF)))
{
printf("%d.%d,%d.%d\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);
return 1;
}
else
return 0;
}
int main(void)
{
int attempts=ATTEMPTS;
if(wiringPiSetup()==-1)
exit(1);
while(attempts)
{
int success = dht11_read_val();
if (success) {
break;
}
attempts--;
delay(500);
}
return 0;
}
No single variable in your code can hold "255.255", that would require a string or a float. You are obviously referring to the output of
printf("%d.%d,%d.%d\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);.
This printf can never produce a three-value output like 55,255.255.
I assume that your output would be 55.255,255.255.
This in turn means that in case of error you will find the "last three digits" in dht11_val[3].
If my assumption is not correct please provide much more detail on the error circumstances.
On the other hand, I suspect that looking for that value is not the solution for your problem either. The function is more complicated. The value of 255 seems the result of an endless loop which is detected by breaking early at counter = 255. So I am pretty sure that checking "the last three digits" is a LESS precise check than what is already implemented.

C language, giving value to char in an if-else statement?

I am trying to use define like this
`printf ("1st Account:");
scanf("%i",&AN1);
printf ("Value of 1st Account:");
scanf("%f",&VAN1);
printf ("2nd Account:");
scanf("%i",&AN2);
printf ("Value of 2nd Account:");
scanf("%f",&VAN2);
system("pause");
system("cls");
if (AN1==101)
#define CAN1 "Cash"
else if (AN1==102)
#define CAN1 "Accounts Receivable"
else if (AN1==104)
#define CAN1 "Notes Receivable"`
and so on
Obviously, it didn't work since define is for the whole program and is not read only within the if statement.
Does anyone know how to make it work?
I need to display it later so like so
`printf ("Your 1st account name is: %s with the value of %.2f.\n",CAN1,VAN1);
printf ("Your 2nd account name is: %s with the value of %.2f.\n",CAN2,VAN2);`
Use variable instead of define:
const char *can1 ="unknown";
if (AN1==101)
can1 = "Cash";
else if (AN1==102)
can1 = "Accounts Receivable";
else if (AN1==104)
can1 = "Notes Receivable";
define is processed in compile time while your value is only known in runtime.
As you correctly observed, #define statements and preprocessor directives in general are evaluated before compile time. The preprocessor processes the file, outputs the preprocessed one, and passes it to the compiler, which eventually generates object files and/or executables.
The preprocessor has no notion of scopes, braces, grammar, or language constructs. It just parses the source file, substitutes macro occurrences, and performs other meta-stuff.
As a replacement, you can use string literals:
const char* ptr;
if (that)
ptr = "that";
else
ptr = "else";
String literals cannot go out of scope because they exist for the whole runtime of the program; they are usually stored within the very core image of the executable.
define is handled in preprocessing, at compile time. You can't conditionally define things at runtime.
You can assign constants to a pointer though:
#include <stdio.h>
int main(void)
{
char *can1;
int an1 = 0;
if (an1 == 0)
can1 = "Cash";
else if (an1 == 102)
can1 = "Accounts Receivable";
else if (an1 == 104)
can1 = "Notes Receivable";
printf("%s\n", can1);
}

Using ENUMs as bitmaps, how to validate in C

I am developing firmware for an embedded application with memory constraints. I have a set of commands that need to processed as they are received. Each command falls under different 'buckets' and each 'bucket' gets a range of valid command numbers. I created two ENUMs as shown below to achieve this.
enum
{
BUCKET_1 = 0x100, // Range of 0x100 to 0x1FF
BUCKET_2 = 0x200, // Range of 0x200 to 0x2FF
BUCKET_3 = 0x300, // Range of 0x300 to 0x3FF
...
...
BUCKET_N = 0xN00 // Range of 0xN00 to 0xNFF
} cmd_buckets;
enum
{
//BUCKET_1 commands
CMD_BUCKET_1_START = BUCKET_1,
BUCKET_1_CMD_1,
BUCKET_1_CMD_2,
BUCKET_1_CMD_3,
BUCKET_1_CMD_4,
//Add new commands above this line
BUCKET_1_CMD_MAX,
//BUCKET_2 commands
CMD_BUCKET_2_START = BUCKET_2,
BUCKET_2_CMD_1,
BUCKET_2_CMD_2,
BUCKET_2_CMD_3,
//Add new commands above this line
BUCKET_2_CMD_MAX,
//BUCKET_3 commands
...
...
...
//BUCKET_N commands
CMD_BUCKET_N_START = BUCKET_N
BUCKET_N_CMD_1,
BUCKET_N_CMD_2,
BUCKET_N_CMD_3,
BUCKET_N_CMD_4,
//Add new commands above this line
BUCKET_N_CMD_MAX,
}cmd_codes
When my command handler function receives a command code, it needs to check if the command is enabled before processing it. I plan to use a bitmap for this. Commands can be enabled or disabled from processing during run-time. I can use an int for each group (giving me 32 commands per group, I realize that 0xN00 to 0xN20 are valid command codes and that others codes in the range are wasted). Even though commands codes are wasted, the design choice has the benefit of easily telling the group of the command code when seeing raw data on a console.
Since many developers can add commands to the 'cmd_codes' enum (even new buckets may be added as needed to the 'cmd_buckets' enum), I want to make sure that the number of command codes in each bucket does not exceed 32 (bitmap is int). I want to catch this at compile time rather than run time. Other than checking each BUCKET_N_CMD_MAX value as below and throwing a compile time error, is there a better solution?
#if (BUCKET_1_CMD_MAX > 0x20)
#error ("Number of commands in BUCKET_1 exceeded 32")
#endif
#if (BUCKET_2_CMD_MAX > 0x20)
#error ("Number of commands in BUCKET_2 exceeded 32")
#endif
#if (BUCKET_3_CMD_MAX > 0x20)
#error ("Number of commands in BUCKET_3 exceeded 32")
#endif
...
...
...
#if (BUCKET_N_CMD_MAX > 0x20)
#error ("Number of commands in BUCKET_N exceeded 32")
#endif
Please also suggest if there is a more elegant way to design this.
Thanks, I appreciate your time and patience.
First fix the bug in the code. As mentioned in comments, you have a constant BUCKET_1 = 0x100 which you then assign CMD_BUCKET_1_START = BUCKET_1. The trailing enums will therefore get values 0x101, 0x102, ... and BUCKET_1_CMD_MAX will be 0x106. Since 0x106 is always larger than 0x20, your static assert will always trigger.
Fix that so that it actually checks the total number of items in the enum instead, like this:
#define BUCKET_1_CMD_N (BUCKET_1_CMD_MAX - CMD_BUCKET_1_START)
#define BUCKET_2_CMD_N (BUCKET_2_CMD_MAX - CMD_BUCKET_2_START)
...
Assuming the above is fixed, then you can replace the numerous checks with a single macro. Not a great improvement, but at least it reduces code repetition:
#define BUCKET_MAX 32 // use a defined constant instead of a magic number
// some helper macros:
#define CHECK(n) BUCKET_ ## n ## _CMD_N
#define STRINGIFY(n) #n
// the actual macro:
#define BUCKET_CHECK(n) \
_Static_assert(CHECK(n) <= BUCKET_MAX, \
"Number of commands in BUCKET_" STRINGIFY(n) "_CMD_N exceeds BUCKET_MAX.");
// usage:
int main (void)
{
BUCKET_CHECK(1);
BUCKET_CHECK(2);
}
Output from gcc in case one constant is too large:
error: static assertion failed: "Number of commands in BUCKET_1_CMD_N exceeds BUCKET_MAX."
note: in expansion of macro 'BUCKET_CHECK'
EDIT
If combining the bug fix with the check macro, you would get this:
#define BUCKET_MAX 32
#define CHECK(n) (BUCKET_##n##_CMD_MAX - CMD_BUCKET_##n##_START)
#define STRINGIFY(n) #n
#define BUCKET_CHECK(n) \
_Static_assert(CHECK(n) <= BUCKET_MAX, \
"Number of commands in BUCKET " STRINGIFY(n) " exceeds BUCKET_MAX.");
int main (void)
{
BUCKET_CHECK(1);
BUCKET_CHECK(2);
}
First of all, preprocessor commands do not work that way. The C preprocessor is able to "see" only names instruced by the #define statement or passes as compiler flags. It is not able to see constants defined as part of an enum or with the const keyword. You should use _Static_assert to validate the commands instead of the preprocessor.
As for the commands, I would suggest to have all the commands numbered in the range 0..0x20:
enum {
BUCKET_1_CMD_1,
BUCKET_1_CMD_2,
...
BUCKET_1_CMD_MAX,
};
enum {
BUCKET_2_CMD_1,
BUCKET_2_CMD_2,
...
BUCKET_2_CMD_MAX,
};
Then you need only a single guard value to check if all the commands are in valid range:
#define MAX_COMMAND 0x20
_Static_assert(BUCKET_1_CMD_MAX <= MAX_COMMAND, "too many bucket 1 commands");
_Static_assert(BUCKET_2_CMD_MAX <= MAX_COMMAND, "too many bucket 2 commands");
To use the commands, bitwise-or them together with the bucket "offset":
enum {
BUCKET_1 = 0x100,
BUCKET_2 = 0x200,
};
...
int cmd = BUCKET_2 | BUCKET_2_CMD_1;

Resources