Searching \ for '[PIC]: defining pins in c' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/languages.htm?key=c
Search entire site for: 'defining pins in c'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: defining pins in c'
2012\04\02@173038 by eMyListsDDg

picon face
new to using hi-tech c and would like to know which is preferred way to define a pin for use.

one can use TRIS, PORT or LAT bits to define a pin to put a LED on, yes?
does one use one of the above or is it as simple as this?

  #define LED1 RA0

i'm a bit unsure which of the SFRs such as listed above that one would use. i'm using 16f88

2012\04\02@184440 by Matt Bennett

flavicon
face
On Mon, April 2, 2012 4:34 pm, eMyListsDDg wrote:
> new to using hi-tech c and would like to know which is preferred way to
> define a pin for use.
>
> one can use TRIS, PORT or LAT bits to define a pin to put a LED on, yes?
>
> does one use one of the above or is it as simple as this?
>
>    #define LED1 RA0
>
>
> i'm a bit unsure which of the SFRs such as listed above that one would
> use. i'm using 16f88

On a PIC16F88, I would use:

#define LED1 PORTAbits.RA0

TRIS defines the direction (TRIState), PORT is the I/O, LAT defines an
output LATch (but isn't on the PIC16F88- it was introduced on later PICs,
like the PIC18Fxxxx and the PIC24, dsPICs, etc).

Matt Bennett
Just outside of Austin, TX
30.51,-97.91

The views I express are my own, not that of my employer, a large
multinational corporation that you are familiar with

2012\04\02@190825 by Sergey Dryga

flavicon
face
eMyListsDDg <emylistsddg <at> gmail.com> writes:

>
> new to using hi-tech c and would like to know which is preferred way to define
a pin for use.
>
> one can use TRIS, PORT or LAT bits to define a pin to put a LED on, yes?
>
> does one use one of the above or is it as simple as this?
>
>    #define LED1 RA0
>
> i'm a bit unsure which of the SFRs such as listed above that one would use.
i'm using 16f88
> Yes, it is that simple. Make sure that you set corresponding TRIS bit to output, in your case: TRISA = 0bxxxxxxx0;

where x - 0 or 1

for simple use no need to do anything else.  You should #include <htc.h> file,
it defines all different SFRs for the processor you use.  
Sergey Dryga
http://beaglerobotics.com




2012\04\02@193944 by Joe Wronski

flavicon
face
On 4/2/2012 7:08 PM, Sergey Dryga wrote:
{Quote hidden}

So, it's not that simple, since you also need to set the tris bit to the right state.  Which could involve another macro statement, like:
#define LED1_TRIS_BIT SomeTrisBitUnion.SomeTrisBit  And maybe another level of macro like #define ENABLE_LED (some code)

It is good to know that rather than set the whole tris reg, in the case where some other code has already set it up, you can just (re)set the individual bit with a bit instruction or a bitwise AND or OR.

Joe W

2012\04\02@202918 by Sergey Dryga
flavicon
face
Joe Wronski <jwronski <at> stillwatereng.net> writes:


> So, it's not that simple, since you also need to set the tris bit to the
> right state.  Which could involve another macro statement, like:
> #define LED1_TRIS_BIT SomeTrisBitUnion.SomeTrisBit  And maybe another
> level of macro like #define ENABLE_LED (some code)
>
Sure, one can make life as complicated, or as simple, as one wishes.  For the OP question, the whole program can be as simple as:

#include <htc.h>

//define XTAL_FREQ, needed for __delay_ms()
#define _XTAL_FREQ 20000000

#define LED1 RA0

__CONFIG(FOSC_HS & LVP_OFF & WDTE_OFF );

void main() {
 TRISA = 0;
 while(1) {
   LED1 ^= 1;
   __delay_ms(200);
   };
}

or, one can define a whole set of macros and write several functions to turn LED
on and off.  It all depends on one's style and needs of the project (and also on
one's definition of "simple" :-) ).

Best,
Sergey Dryga
http://beaglerobotics.com


2012\04\02@203548 by David Meiklejohn

face
flavicon
face
Joe Wronski wrote:
{Quote hidden}

Yes, this is something I've struggled with when writing my tutorials -
deciding what the best advice to give is.  There's certainly a need to teach
good practices, such as defining pins using macros, whether at the start of
the program or in a header, making the code far more maintainable - I make
the point that pin assignments can and do change, and you don't want to be
ferreting around trying to find everywhere you've referred to each LED.  On
the other hand, you can end up with so many macros that the code becomes
lost and so does the point I'm trying to explain.

So I've ended up with a compromise.  I define macros for individual pins
like this, and/or for the shadow equivalents of them, but not TRIS - or
others such as enabling pull-ups or interrupt on change (it can go on and
on).  Instead I keep all port configuration in a single initialisation
routine.  So, if a pin assignment changes later, I only need to make two
changes - a macro at the start of the program, and in the initialisation
code - which could be much more than changing one TRIS expression.  Maybe
the new pin has an analog input that has to be disabled, while the old one
didn't.

But of course there are always exceptions.  If you have some code that
flipping a pin between input and output (say multiplexing a switch with an
output), then sure it's best practice to define macros for the TRIS bits and
changing them one at a time to avoid affecting anything else, as you say.

At the end of the day, some level of judgement has to apply.  There can't be
one rule fits all.

Regards,

David Meiklejohn
http://www.gooligum.com.au

2012\04\02@203949 by David Meiklejohn

face
flavicon
face
Sergey Dryga wrote:
>
> //define XTAL_FREQ, needed for __delay_ms() #define _XTAL_FREQ 20000000

Slightly off-topic, but - that can't work can it?  The whole line is a
comment.

Don't you need:
#define _XTAL_FREQ 20000000   //define XTAL_FREQ, needed for __delay_ms()

?


Regards,

David Meiklejohn
http://www.gooligum.com.au

2012\04\02@214827 by Sergey Dryga

flavicon
face
David Meiklejohn <david <at> gooligum.com.au> writes:

>
> Sergey Dryga wrote:
> >
> > //define XTAL_FREQ, needed for __delay_ms() #define _XTAL_FREQ 20000000
>
> Slightly off-topic, but - that can't work can it?  The whole line is a
> comment.
>
> Don't you need:
> #define _XTAL_FREQ 20000000   //define XTAL_FREQ, needed for __delay_ms()

Yes, you are right.  Typo.
Sergey Dryga
http://beaglerobotics.com

2012\04\02@215339 by Sergey Dryga

flavicon
face
David Meiklejohn <david <at> gooligum.com.au> writes:

> So I've ended up with a compromise.  I define macros for individual pins
> like this, and/or for the shadow equivalents of them, but not TRIS - or
> others such as enabling pull-ups or interrupt on change (it can go on and
> on).  Instead I keep all port configuration in a single initialisation
> routine.  So, if a pin assignment changes later, I only need to make two
> changes - a macro at the start of the program, and in the initialisation
> code - which could be much more than changing one TRIS expression.  Maybe
> the new pin has an analog input that has to be disabled, while the old one
> didn't.

It's good to know how other people do it.  I have come to exactly the same
practice (although I do not have to teach others PIC programming).  I also put
all pin definitions in an include file, and provide description of pin
functions, so that even without looking at the schematics, it is clear what a
pin does.
Regards,
Sergey Dryga
http://beaglerobotics.com

2012\04\02@220440 by eMyListsDDg

picon face
Thanks David, Sergey, Joe & Matt, et.el.,

really good help/education you provided me on this, thanks for taking the time to explain this and unravel my confusion on the subject.


i just saw your tutorial site David, i'll be reading up more there.

cheers,
wb

2012\04\03@023156 by Wouter van Ooijen

face picon face
> On a PIC16F88, I would use:
> #define LED1 PORTAbits.RA0

In most cases this will put you at the mercy of the Read-Modify-Write problem. Better define a bit in a porta-shadow register, chacge that bit, and copy it to PORTA after each change of any bit.

--
Wouter van Ooijen

-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu
C++ on uC blog: http://www.voti.nl/erblog

2012\04\03@043302 by eMyListsDDg

picon face
not sure i fully understand your suggestion. could you provide a a few lines of code for me to view?

thank you


{Quote hidden}

-- Bill
Key fingerprint = DB4D 251B FE8A BDCD 2BE4  E889 13F1 78D0 A386 B32B

2012\04\03@060027 by Ruben Jönsson

flavicon
face
Read-Modify-Write - Something that every PIC programmer should be aware of.

Whenever you write a bit on any register, including port registers, the CPU actually reads the whole register, modifies the bit you want to set/clear and then writes the whole register back. When you write a port pin it sets a latch on that port but when you read it, it is the actual voltage on the port pin that is read.
This would all be fine in an ideal world. However, it can take some time for the actual voltage on a port pin to rise from a 0 to a 1 (or vice versa). This is depending on the capacitive and resistive load on that pin.

Before the port pin output voltage have reach the threashold value for a digital 1 on the input circuitry for that pin it will be read as a 0. So even if you have set the port pin latch to a 1, it can take some time before the port register bit for that pin will be read back as a 1.

Now, if you set two bits on the same port right after each other, the second write can reset the first because the output pin for the first bit has not settled to a high level yet (as read by the input circuitry).

There are a couple of ways to solve this.

On newer pics, each port actually has two registers, the port pin register itself that sees the voltage on the port pin and also the latch register that holds the value last written to the port. The latch register is always a 1 when it has been set to a 1 even if the voltage on the port pin hasn't reached its final voltage yet (and ofcourse vice versa for a 0). Therefor you should use the latch register when writing individual bits to a port since a read on that register always reflects what was last written.

Older pics can't read the latch register so there you have to solve the problem by not writing individual bits to a port register one at a time but instead always write all bits at once. You do this by using a shadow register (which works the same way as the latch register). Set and clear individual bits to the shadow register and then copy this whole register to the actual port register. This way, writing an individual bit to an outport, never involves a read on that port.

/Ruben  

{Quote hidden}

> -

2012\04\03@062655 by cdb

flavicon
face
Here is an example of using a dummy port variable. This code is for a standard LCD.

void display(unsigned char *tmpPtr)
{
       
 unsigned char currentCH;  //THIS IS THE SHADOW PORT VARIABLE
   rs=0;                                        //RS in Command mode for position byte
    while(*tmpPtr)                //LCD Data on bits D4-D7 of PORT
   {
           currentCH=*tmpPtr; //DATA IS COPIED TO SHADOW PORT VARIABLE
           LCDPORT&=0x0F;                //THIS IS THE REAL PORT, #define LCDPORT PORTB                
           LCDPORT|=(currentCH&0xF0);        //Mask off upper nibble  REAL PORT COPIES SHADOW PORT VARIABLE CONTENTS.
           sendit(rs);
           currentCH<<=4;                                //Now select lower nibble
           LCDPORT&=0x0F;
           LCDPORT|=currentCH;
           sendit(rs);
           t40();
         rs=1;                                                //make sure RS is in data mode
           tmpPtr++;                                        //get next character
}

Colin        --
cdb, spam_OUTcolinTakeThisOuTspambtech-online.co.uk on 3/04/2012
Web presence: http://www.btech-online.co.uk   Hosted by:  http://www.justhost.com.au
 This email is to be considered private if addressed to a named  individual or Personnel Department, and public if addressed to a blog,  forum or news article.

2012\04\03@071131 by David Meiklejohn

face
flavicon
face
eMyListsDDg wrote:
>
> not sure i fully understand your suggestion. could you provide a a few
> lines of code for me to view?

This was after Wouter wrote:
> >
> > In most cases this will put you at the mercy of the Read-Modify-Write
> > problem. Better define a bit in a porta-shadow register, chacge that
> > bit, and copy it to PORTA after each change of any bit.

You'll find a number of examples in my tutorials
(http://www.gooligum.com.au/tutorials.html) - I use shadow registers pretty
consistently.

Here's one example, showing how I've set up a shadow register as a union,
making it possible to refer to the whole register ("GPIO = sGPIO.port") or
to individual shadow bits with logical names ("sFLASH = 1").  Don't be
scared off - the lessons start simpler than this!


/************************************************************************
*                                                                       *
*   Description:    Lesson 3, example 4                                 *
*                                                                       *
*   Demonstrates use of Timer0 in counter mode                          *
*                                                                       *
*   LED flashes at 1 Hz (50% duty cycle),                               *
*   with timing derived from 32.768 kHz input on T0CKI                  *
*                                                                       *
*************************************************************************
*                                                                       *
*   Pin assignments:                                                    *
*       GP1   = flashing LED                                            *
*       T0CKI = 32.768 kHz signal                                       *
*                                                                       *
************************************************************************/

#include <htc.h>
#include <stdint.h>


/***** CONFIGURATION *****/
// ext reset, no code protect, no watchdog, int RC clock
__CONFIG(MCLRE_ON & CP_OFF & WDT_OFF & OSC_IntRC);

// Pin assignments
#define sFLASH  sGPIO.GP1           // flashing LED (shadow)


/***** GLOBAL VARIABLES *****/
union {                             // shadow copy of GPIO
   uint8_t         port;
   struct {
       unsigned    GP0     : 1;
       unsigned    GP1     : 1;
       unsigned    GP2     : 1;
       unsigned    GP3     : 1;
       unsigned    GP4     : 1;
       unsigned    GP5     : 1;
   };
} sGPIO;


/***** MAIN PROGRAM *****/
void main()
{
   // Initialisation
       // configure port        TRIS = 0b111101;                // configure GP1 (only) as an output
       // configure timer        OPTION = 0b11110110;            // configure Timer0:
            //--1-----                 counter mode (T0CS = 1)
            //----0---                 prescaler assigned to Timer0 (PSA =
0)
            //-----110                 prescale = 128 (PS = 110)
            //                         -> increment at 256 Hz with 32.768
kHz input
                    // Main loop
   for (;;)
   {
       // TMR0<7> cycles at 1 Hz, so continually copy to LED
       sFLASH = 0;                 // assume TMR<7>=0 -> LED off
       if (TMR0 & 1<<7)            // if TMR0<7>=1
           sFLASH = 1;             //   turn on LED
               GPIO = sGPIO.port;          // copy shadow to GPIO
           }   // repeat forever
}

2012\04\03@130919 by eMyListsDDg

picon face
Hello Wouter, ( &Ruben, &David)

ok, i see this a bit clearer now. appreciate the explanation and code example (it helps).


thanks
wb

More... (looser matching)
- Last day of these posts
- In 2012 , 2013 only
- Today
- New search...