naming port pins

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

WinAVR C compiler, ATmega16.

I'm trying to name a port pin, so I can use that name in the code.

ex:

PD2 is called SCK
PD3 is called DATA

//----------------------------------------------------------------------------------
void s_transstart(void)
//----------------------------------------------------------------------------------
// generates a transmission start

{
DATA=1; SCK=0; //Initial state
_nop_();
SCK=1;
_nop_();
DATA=0;
_nop_();
SCK=0;
_nop_();_nop_();_nop_();
SCK=1;
_nop_();
DATA=1;
_nop_();
SCK=0;
}

Probably something stupidly simple, but I don't have much experience with C or AVR yet. Thanks.

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

The definition of the bits is easy:

#define SCK PD2
#define DATA PD3

However, since these are just constant bit numbers and not variables, you can't use them directly, as in:

SCK = 0;

Instead you have to use something like:

PORTD |= (1 << SCK); //set SCK
PORTD &= ~(1 << SCK); //clear SCK

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
PORTD |= (1 << SCK); //set SCK
PORTD &= ~(1 << SCK); //clear SCK

This always looks very ugly to me :(

#define SCK  (1 << PD2)
#define DATA (1 << PD3)

PORTD |=  SCK; //set   SCK
PORTD &= ~SCK; //clear SCK

Seems a much clearer expression of what you're actually trying to achieve... 8)

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
This always looks very ugly to me

I agree, but it seems to be the standard around here.

Regards,
Steve A.

The Board helps those that help themselves.

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

The convention seems to be a carry-over from AVR assembly programming.

There are very good reasons why most special-purpose bits are defined according to their position rather than their mask in AVR assembly, because of the implementation of most bitwise op-codes.

C does not have such a restriction. However, heritage can be a strong source of inertia. As well, maintaining the same convention tends to allow a single set of common headers carry over from C to ASM programming and vice-versa. (This is particularly important, for example, in gcc, which really does use exactly the same headers for its assembler and its C compiler.)

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

Try:

#include 
typedef struct { 
  unsigned char bit0:1; 
  unsigned char bit1:1; 
  unsigned char bit2:1; 
  unsigned char bit3:1; 
  unsigned char bit4:1; 
  unsigned char bit5:1; 
  unsigned char bit6:1; 
  unsigned char bit7:1; 
}io_reg; 

#define SCK   ((volatile io_reg*)_SFR_MEM_ADDR(PORTD))->bit2 
#define DATA  ((volatile io_reg*)_SFR_MEM_ADDR(PORTD))->bit3 

int
main(void)
{ 
 SCK = 0; 
 SCK = 1;
}

This generates the code:

390:        SCK = 0; 
+0000004B:   9892        CBI     0x12,2    Clear bit in I/O register
400:      	SCK = 1;
+0000004C:   9A92        SBI     0x12,2    Set bit in I/O register

(BTW, I'm not the originator of this technique but took a suggestion from someone else (who's name currently escapes me :( ) here on 'Freaks)

Cliff

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

That worked fine, now I have another problem.

I need to use DATA as both input and output. Other than changing DDRD, are there any other things I need to do?

ex:
//DDRD set for DATA as input
error=DATA;

The point is to set error to 1 if DATA is still high, 0 if it gets pulled low by external device. I used Clawson's method for naming the port.

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

I just assume its always set to IN... initialize it that way, and when you want to write to it, set it to out, write, then set it back to in

Imagecraft compiler user