CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Passing PINs to functions

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jgschmidt



Joined: 03 Dec 2008
Posts: 184
Location: Gresham, OR USA

View user's profile Send private message Send e-mail Visit poster's website

Passing PINs to functions
PostPosted: Wed Dec 03, 2008 1:58 am     Reply with quote

How do I pass a pin, for example PIN_B0, to a function?

I want to read several temperature sensors (DS18B20). All the driver code examples I have looked at define the pins used as global constants, however I would like to call the ds1820_read function with a pin as a parameter.

I tried redefining the function as
float ds1820_read(int16 pin_dq) {...}
and then calling it via
temperature1 = ds1820_read(PIN_B0);

but that does not seem to work. Any help would be appreciated.

Thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 03, 2008 2:01 am     Reply with quote

1. Post a link to the source code for the ds1820_read() function.

2. Post your compiler version.

3. Post your PIC.
jgschmidt



Joined: 03 Dec 2008
Posts: 184
Location: Gresham, OR USA

View user's profile Send private message Send e-mail Visit poster's website

Passing PIN as a parameter - code listings
PostPosted: Wed Dec 03, 2008 9:57 am     Reply with quote

Compiler is PCH 4.082
PIC is 18F4620 on the CCS Embedded Ethernet board
Here is the code:
Code:

// picens1.h
//
// CCS Embedded Ethernet Board PIC18F4620 Rev 3
//
// 2008.11.27 - Jurgen Schmidt
//
#define POT          PIN_A0   
// PIN_A1
// PIN_A2
// PIN_A3
#define BUTTON       PIN_A4    // press=low
#define LED_GREEN    PIN_A5   
// PIN_A6
// PIN_A7
//
// PIN_B0
// PIN_B1
// PIN_B2
// PIN_B3   CS_EEPROM
#define LED_YELLOW   PIN_B4   
#define LED_RED      PIN_B5   
// PIN_B6   ICSP_PGC
// PIN_B7   ICSP_PGD
//
// PIN_C0
// PIN_C1
// PIN_C2
// PIN_C3   CLK: EEPROM, MMC, ETH
// PIN_C4   SO: EEPROM, MMC, ETH
// PIN_C5   SI: EEPROM, MMC, ETH
// PIN_C6   RS232_IN    (tip)
// PIN_C7   RS232_OUT   (middle)
//
// PIN_D0
// PIN_D1   CS_ETH
// PIN_D2
// PIN_D3   CS_MMC
// PIN_D4   LCD_D4
// PIN_D5   LCD_D5
// PIN_D6   LCD_D6
// PIN_D7   LCD_D7
//
// PIN_E0   LCD_RS
// PIN_E1   LCD_RW
// PIN_E2   LCD_EN
//

//
#include <18f4620.h>
#use delay(clock=10M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#fuses HS, NOWDT, NOLVP, NODEBUG


// LCD PINS for flex_lcd2x16.c
#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_D5
#define LCD_DB6   PIN_D6
#define LCD_DB7   PIN_D7

#define LCD_E     PIN_E2
#define LCD_RS    PIN_E0
#define LCD_RW    PIN_E1

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

#define USE_LCD_RW   1     

//#define ONE_WIRE_PIN PIN_B0



Code:


#include "picens1.h"

#include <flex_lcd2x16.c>

//#include <mlcd.c>
#include <1wire.c>
#include <ds1820.c>

#define  DQ1   PIN_B0
#define  DQ2   PIN_B2

void main()
{
   float temperature1, temperature2;
   
   lcd_init();
   
   printf(lcd_putc,"\fHello.");
   printf(lcd_putc,"\nGoodbye JGS.");
   delay_ms(1000);

   while (TRUE)
   {
      output_low(LED_GREEN);
      delay_ms(500);
      output_high(LED_GREEN);
      delay_ms(500);
     
      temperature1 = ds1820_read(DQ1);
      temperature2 = ds1820_read(DQ2);
      lcd_gotoxy(1,1);
      printf(lcd_putc,"TEMP1: %3.1f ", temperature1);
      lcd_putc(223);
      lcd_putc("C    ");
     
      printf(lcd_putc,"\ntemp2: %3.1f ", temperature2);
      lcd_putc(223);
      lcd_putc("C    ");
     

      delay_ms(1000);
   }
}

Code:

//  1wire.c
//
//  CCS Forum Code Library #28425
//
// (C) copyright 2003 j.d.sandoz / jds-pic !at! losdos.dyndns.org
//
// released under the GNU GENERAL PUBLIC LICENSE (GPL)
// refer to http://www.gnu.org/licenses/gpl.txt
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//=============================================================================

//  1Wire Class
//  Description: This class handles all communication
//  between the processor and a single 1wire sensor
//
// 2008.12.02 - Jurgen G. Schmidt  Paramterized version - variable PIN input
//

//-------------------------------------------------------------------
//------ initiates the 1wire bus
// PARAMETERS: pin for DQ
// RETURNS:    none

void onewire_reset(int16 pin_dq)
{
 output_low(pin_dq);
 delay_us( 500 );       // pull 1-wire low for reset pulse
 output_float(pin_dq);  // float 1-wire high
 delay_us( 500 );       // wait-out remaining initialisation window.
 output_float(pin_dq);
}

//-------------------------------------------------------------------
//------ writes a byte to the sensor
//
// Parameters: byte16 - DQ pin
//             byte - the byte to be written to the 1-wire */
// Returns:    none

void onewire_write(int16 pin_dq, int data)
{
 int count;

 for (count=0; count<8; ++count)
 {
  output_low(pin_dq);
  delay_us( 2 );        // pull 1-wire low to initiate write time-slot.
  output_bit(pin_dq, shift_right(&data,1,0)); // set output bit on 1-wire
  delay_us( 60 );       // wait until end of write slot.
  output_float(pin_dq); // set 1-wire high again,
  delay_us( 2 );        // for more than 1us minimum.
 }   
}

//-------------------------------------------------------------------
//------ reads the 8-bit data via the 1-wire sensor
// PARAMETERS: pin for DQ
// RETURNS:    8-bit (1-byte) data from sensor 

int onewire_read(int16 pin_dq)
{
 int count, data;

 for (count=0; count<8; ++count)
 {
  output_low(pin_dq);
  delay_us( 2 );           // pull 1-wire low to initiate read time-slot.
  output_float(pin_dq);    // now let 1-wire float high,
  delay_us( 8 );           // let device state stabilise,
  shift_right(&data,1,input(pin_dq)); // and load result.
  delay_us( 120 );         // wait until end of read slot.
 }

 return( data );
}

Code:

// ds1820.c
//
//  CCS Forum Code Library #28425
//
// read 1wire thermometer
//
// 2008.12.02 - Jurgen G. Schmidt  Paramterized version - variable PIN input
//
float ds1820_read(int16 pin_dq)
{
 int8 busy=0, temp1, temp2;
 signed int16 temp3;
 float result;

 onewire_reset(pin_dq);
 onewire_write(pin_dq,0xCC);
 onewire_write(pin_dq,0x44);

 while (busy == 0)
  busy = onewire_read(pin_dq);

 onewire_reset(pin_dq);
 onewire_write(pin_dq,0xCC);
 onewire_write(pin_dq,0xBE);
 temp1 = onewire_read(pin_dq);
 temp2 = onewire_read(pin_dq);
 temp3 = make16(temp2, temp1);
 
// result = (float) temp3 / 2.0;   //Calculation for DS18S20 with 0.5 deg C resolution
 result = (float) temp3 / 16.0;  //Calculation for DS18B20 with 0.1 deg C resolution
 
 delay_ms(200);
 return(result);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 03, 2008 12:59 pm     Reply with quote

To discover what the compiler is doing, make a little test program which
concentrates only on one thing -- in this case, passing a CCS pin constant
to a function.

Then look at the .LST file to see the ASM code created by the compiler.
Look at the massive amount of code that is required to an turn a CCS pin
constant into a pin i/o operation, when it's passed as a variable.

Because the one wire code depends upon accurate delays, the insertion
of massive hidden delays such as this will ruin the code operation.
Code:
.................... void onewire_write(int16 pin_dq, int data) 
.................... { 
....................  int count; 
.................... 
....................  for(count=0; count<8; ++count) 
00072:  CLRF   09
00074:  MOVF   09,W
00076:  SUBLW  07
00078:  BNC   00FE
....................  { 
....................   output_low(pin_dq); 
0007A:  MOVFF  06,0A
0007E:  CLRF   0B
00080:  MOVLW  0F
00082:  MOVWF  0D
00084:  MOVLW  89
00086:  MOVWF  0C
00088:  RCALL  0004
0008A:  MOVFF  06,0A
0008E:  CLRF   0B
00090:  MOVLW  0F
00092:  MOVWF  0D
00094:  MOVLW  92
00096:  MOVWF  0C
00098:  RCALL  0004
....................   delay_us( 2 );         
0009A:  BRA    009C
0009C:  BRA    009E
0009E:  NOP

// Here's the routine at 0004, that is called by the code above.
00004:  MOVF   0A,W
00006:  ANDLW  07
00008:  MOVWF  00
0000A:  RRCF   0A,W
0000C:  MOVWF  01
0000E:  RRCF   01,F
00010:  RRCF   01,F
00012:  MOVLW  1F
00014:  ANDWF  01,F
00016:  MOVF   01,W
00018:  ADDWF  0C,W
0001A:  MOVWF  FE9
0001C:  MOVLW  00
0001E:  ADDWFC 0D,W
00020:  MOVWF  FEA
00022:  CLRF   01
00024:  INCF   01,F
00026:  INCF   00,F
00028:  BRA    002C
0002A:  RLCF   01,F
0002C:  DECFSZ 00,F
0002E:  BRA    002A
00030:  MOVF   0B,F
00032:  BZ    003A
00034:  MOVF   01,W
00036:  IORWF  FEF,F
00038:  BRA    0040
0003A:  COMF   01,F
0003C:  MOVF   01,W
0003E:  ANDWF  FEF,F
00040:  RETLW  00
00042:  MOVF   0A,W
00044:  ANDLW  07
00046:  MOVWF  00
00048:  RRCF   0A,W
0004A:  MOVWF  01
0004C:  RRCF   01,F
0004E:  RRCF   01,F
00050:  MOVLW  1F
00052:  ANDWF  01,F
00054:  MOVF   01,W
00056:  ADDWF  0B,W
00058:  MOVWF  FE9
0005A:  MOVLW  00
0005C:  ADDWFC 0C,W
0005E:  MOVWF  FEA
00060:  MOVFF  FEF,01
00064:  INCF   00,F
00066:  BRA    006A
00068:  RRCF   01,F
0006A:  DECFSZ 00,F
0006C:  BRA    0068
0006E:  GOTO   00F4 (RETURN)
 


Code:
#include <18F4620.H>
#fuses HS,NOWDT,NOPROTECT, PUT, BROWNOUT, NOLVP   
#use delay(clock=10000000)                           
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

void onewire_write(int16 pin_dq, int data)
{
 int count;

 for(count=0; count<8; ++count)
 {
  output_low(pin_dq);
  delay_us( 2 );         
  output_bit(pin_dq, shift_right(&data,1,0)); 
  delay_us( 60 );       
  output_float(pin_dq);
  delay_us( 2 );         
 }   
}

//=========================
void main()
{
onewire_write(PIN_B0, 0x55);


while(1);
}
jgschmidt



Joined: 03 Dec 2008
Posts: 184
Location: Gresham, OR USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Dec 03, 2008 3:43 pm     Reply with quote

Thanks for the feedback -I'll try something more efficient.
MarcosAmbrose



Joined: 25 Sep 2006
Posts: 38
Location: Adelaide, Australia

View user's profile Send private message

PostPosted: Wed Dec 03, 2008 3:44 pm     Reply with quote

Use a switch/case statement in your function.
Code:

void MyFunction(int16 PinToUse)
{
    switch(PinToUse)
   {
      case PIN_B0:
         output_high(PIN_B0);
         break;
      case PIN_B1:
         output_high(PIN_B1);
         break;
   }
}





Quote from CCS compiler help:
Code:

The pin argument for built in functions like OUTPUT_HIGH need to be known at

compile time so the compiler knows the port and bit to generate the correct code.

 

If your application needs to use a few different pins not known at compile time consider:

 

switch(pin_to_use) {

    case PIN_B3  : output_high(PIN_B3); break;

    case PIN_B4  : output_high(PIN_B4); break;

    case PIN_B5  : output_high(PIN_B5); break;

    case PIN_A1  : output_high(PIN_A1); break;

    }

 

If you need to use any pin on a port use:

 

#byte portb = 6

#byte portb_tris = 0x86  // **

 

portb_tris &= ~(1<<bit_to_use);  // **

 

portb |= (1<<bit_to_use);  // bit_to_use is 0-7

 

If you need to use any pin on any port use:

 

*(pin_to_use/8|0x80) &= ~(1<<(pin_to_use&7)); // **

 

*(pin_to_use/8) |= (1<<(pin_to_use&7));

 

In all cases pin_to_use is the normal PIN_A0... defines.

Code:
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 03, 2008 3:50 pm     Reply with quote

Quote:

The pin argument for built in functions like OUTPUT_HIGH need to be
known at compile time.

That's true for version 3. Version 4 allows variable parameters for the
i/o functions. The switch-case method will generate much more compact
code. However, the .LST file should still be checked to verify if the
overhead is sufficiently small to work with the one-wire code's timing
requirements.
MarcosAmbrose



Joined: 25 Sep 2006
Posts: 38
Location: Adelaide, Australia

View user's profile Send private message

PostPosted: Wed Dec 03, 2008 3:57 pm     Reply with quote

PCM programmer wrote:
That's true for version 3. Version 4 allows variable parameters for the i/o functions.

Bugga - Now I have a excuse to upgrade my compiler Smile
crystal_lattice



Joined: 13 Jun 2006
Posts: 164

View user's profile Send private message

PostPosted: Thu Dec 04, 2008 2:47 am     Reply with quote

The sad irony is that Dallas has spent lots of money to produce a device with a unique 64bit serial number and various other functions/features to enable the master to communicate with a single device amongst hundreds of others on the same network and yet people want to use seperate io pins to accomplish the same task...

I understand that there are some exceptions to the rule, but why don't you use the search and match rom functions to communicate with the correct device? It is really not that hard to implement.
Ttelmah
Guest







PostPosted: Thu Dec 04, 2008 4:05 am     Reply with quote

A quick search here, will find posted code, to give input/output on a variable pin, using V3 compilers.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group