#define question

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm trying to do

#define LEDPIN				PORTB,1
#define SETBIT(reg,bit)		(reg |= (1<<bit))

{
	SETBIT(LEDPIN);
}

But it gives me an error saying "macro "SETBIT" requires 2 arguments, but only 1 given"

Does the preprocessor look at the macro defines first? Is there anyway to what I want?

Edward

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have to make that a two-stage process:

#define LEDPIN            PORTB,1
#define SETBIT_(reg,bit)      (reg |= (1<<bit))
#define SETBIT(mac)       SETBIT_(mac)

{
   SETBIT(LEDPIN);
}

(Moderator's note: moved to generic AVR forum as this is completely
compiler independent.)

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any idea ? If I want to make macro for clear bit, from these define.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Basic C language. Make a new define based on the setbit stuff, and replace the

|=

with

&=~

.

- Jani

EDIT: That is by they way quite nice way of defining IO bits by functionality. I've never thought of it that way. I just made a shell script to expand my definitions to define macros..

so basically I make a file with following lines:

#  type name   port pin 
pin_inp BUTTON A     4
pin_out LED    B     3

and the script spits out a .h file:

#define CTL_BUTTON_PORT PORTA
#define CTL_BUTTON_DIR  DDRA
#define CTL_BUTTON_PIN  PINA
#define CTL_BUTTON_BIT  PA4
#define CTL_BUTTON_MASK (1<<CTL_BUTTON_BIT)
#define CTL_BUTTON_INPUT() (CTL_BUTTON_DIR &=~CTL_BUTTON_MASK)
#define CTL_BUTTON_READ() (CTL_BUTTON_PIN&CTL_BUTTON_MASK)

#define CTL_LED_PORT PORTB
#define CTL_LED_DIR  DDRB
#define CTL_LED_BIT  PB4
#define CTL_LED_MASK (1<<CTL_LED_BIT)
#define CTL_LED_OUTPUT() (CTL_LED_DIR |= CTL_LED_MASK)
#define CTL_LED_SET() (CTL_LED_PORT |= CTL_LED_MASK)
#define CTL_LED_CLR() (CTL_LED_PORT &=~ CTL_LED_MASK)

- Jani

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> That is by they way quite nice way of defining IO bits by functionality.

Others might call this technique a "HAL" (hardware abstraction layer).
Symbolically, you can use mnemonic names without really caring for how
the low-level implementation is done. It could even be done in a
completely different manner (like, on a completely different controller
type), the application itself would not notice. Yet, since it's all done
in macros, it's as efficient as manually coding all the low-level
register access directly in the application layer code.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perfect, works like a charm.
Just trying to figure out why it works though. Does the preprocessor go through the macro #defines first then the constant defines, lather, rinse, repeat until none left in the code?

Edward

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> Does the preprocessor go through the macro #defines
> first then the constant defines ...

They are *all* `macro' defines, because #define introduces
a macro. No, there's no distinction between when function-like
and object-like macros are being resolved. It's just that the
process of resolving includes repeated preprocessing. The
details are written in the C standard, but reading that is a
dull job. Just keep in mind that in order for a macro
replacement to be expanded into another macro call, you have
to have two stages.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Will do. I just thought it would iterate through them line by line so that the "#define LEDPIN PORTB,1" would be evaluated first.

Edward

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a very similar I/O question actually which is if i set:
DDRA = 0x15;
PORTA = 0x15;

so that the port is set to 00010101 (3 output pins hi asserted, 5 input ports lo) why is it that when i physically link say pin1 to pin2 (simple switch) to set pin2 high, and then try to read pin2 with:
either
if(PINA == 0x17) //00010111 binary
{
do something
}

or
if(PINA == 0b00010111) //0x17 hex
{
do something
}

i get something which compiles fine but never works when i use the switch, I even tried storing PINA into an integer and sending it to the LCD to see what was going on :] Any Ideas?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shinto, if you just want to test one bit, use the & operator to look at the bit of interest.

ie:

IF (PINA & 0b00000010)
{

}
or
if (PINA & (1<<1))
{

}
This ensures you're only interested in one bit, whereas doing an equality test, you're looking at all bits.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

IF (PINA & 0b00000010)
{
}
i am afraid does not work and neither does the safer:
if((PORTA & 0b00000010)==1)
{
}
or

if((PINA & 0b00000010)==1)
{
}

or with && instead of &
i hope there is nothing wrong with my board :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shinto, you're starting to guess rather than concentrate on the problem.

if((PORTA & 0b00000010)==1)
and
if((PINA & 0b00000010)==1)

have got no hope of working as the result would either be 0 or 2, it will never equal 1, test for 0 or non zero. Nor using && as this suggests you don't understand the difference between && and &.

I suggest you spend some time with the AVRStudio simulator where you can step through your code and simulate the input to see what happens.

You may have a hardware problem, you may have the DDR register set incorrectly etc. Blindly trying things won't get you a result, so when things stop making sense. STOP! Then work through the problem logically. The simulator is always a good place to start.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I take your point and it is a good one about not getting too distracted about what i am doing but i still fail to see what is wrong with code i am trying to make work like this for example:

DDRA = 0x00;
PORTA = 0x00;
bit_clear(DDRA,BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7));
bit_clear(PORTA,BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7));
bit_set(DDRA,BIT(0)|BIT(2)|BIT(4));
bit_set(PORTA,BIT(0)|BIT(2)|BIT(4));

bit_clear(PINA , BIT(1));
if(bit_get(PINA , BIT(1)) &= 0)
{
LCD4_Clear(); // Clear LCD Screen
LCD4_Home();
LCD4_PutS("switch on");

/* physical connect pins 0 and 1 */

delay_ms(1000); // delay loop
}

The code is a bit messy but it is for testing purposes of my switch between pin 1 and 0 only. Is the Imagecraft C (ICC) compiler i am using to blame or my novice skiils? If i just use:

if(bit_get(PINA , BIT(1)))
{
as before
}
it does not work either and i am at a loss as to why. More time on the simulator for me i think but I have found that the only reliable port commands so far are simple ones like DDRA = 0x03; and the like.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Um,

DDRA = 0x00;

and:

bit_clear(DDRA,BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7));

Do EXACTLY the same thing (personally I fnid the first of those far more readable than the second).

Same goes for your accesses to PORTA to set all the bits to 0.

The only valid stuff is where you set the state of 0/2/4 in the two registers. In fact, because the documented default is for the two registers to have 0 then why bother with anything but the:

bit_set(DDRA,BIT(0)|BIT(2)|BIT(4)); 
bit_set(PORTA,BIT(0)|BIT(2)|BIT(4));

In fact, if you want to be sure the other 5 bits in each register are 0 then why not just:

DDRA = (1<<PA0) | (1<<PA2) | (1<<PA4);
PORTA = (1<<PA0) | (1<<PA2) | (1<<PA4);

Oh and:

bit_clear(PINA , BIT(1));

does not make any sense - it's an input, you can't clear it's state from "inside" the chip. Its state is set by the voltage applied to the PA1 pin.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I managed to solve my problem not by programming, but instead by using a hardware solution - i.e. making my keypad switches switch between pins set to high and the ground pin. I would have prefered to have switches that switched between pins that were set to lo and pins set to high (i wanted to set the lo pins high with a connection to high or the high pins low with a connection to low) but for some reason that does not work on my board.

Thanks for the help anyways folks. :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a similar problem!
I am using the AVR-GCC compiler and I want to redefine/rename portpins to have more meaningful names in my program. I believe by doin this I only need to change at one place if my design need to change.

I possible :roll: I would like to assign these pins to bits of one variable(type int/char)....to be able to test only one variable.

Any of you geniuses done this before??

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure what you really want here. As such, the definitions in declare the ports /timers etc as variables, ie ; PORTB, so you access these like any other variable, so as to why you want to reassign these to another variable for the purpose of meaningful names I don't quite understand. Just doing a #define like shown at the beginning of this thread simply gives another name to , say , PORTB (as mentioned, the preprocessor does the text subsititution so the compiler itself sees the same thing).

As for renaming ports etc, that was discussed above.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Kartman!
I have managed solve most of my problems. Maybe you can assist me with another.
Using the #define, I created macro to test pins.

#define STATION1 PIND,0
#define bittest(reg,bit) (reg & (1<<bit));
#define C_bittest(mac) bittest(mac);

but when I used this with the 'if' statement:

if(C_bittest(STATION1))

the compiler generates error:

.. error: expected ')' before ';' token

Perhaps know why?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have a semi-colon inside your define - never a great idea

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please explain cause when omit the semicolon here:

#define bitset(reg,bit) (reg |= (1<<bit))
#define bitclr(reg,bit) (reg &= ~(1<<bit));
#define C_bitset(mac) bitset(mac)
#define C_bitclr(mac) bitclr(mac)

I get compilation error

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
if(C_bittest(STATION1))

will expand to:

if(bittest(PIND, 0);)

will expand to:

if((PIND & (1<<0));;)

The compiler therefore says:

.. error: expected ')' before ';' token 

as you have two spurious semi-colons inside the conditional test.