| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| jgschmidt 
 
 
 Joined: 03 Dec 2008
 Posts: 184
 Location: Gresham, OR USA
 
 
			        
 
 | 
			
				| Passing PINs to functions |  
				|  Posted: Wed Dec 03, 2008 1:58 am |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Dec 03, 2008 2:01 am |   |  
				| 
 |  
				| 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
 
 
			        
 
 | 
			
				| Passing PIN as a parameter - code listings |  
				|  Posted: Wed Dec 03, 2008 9:57 am |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Dec 03, 2008 12:59 pm |   |  
				| 
 |  
				| 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
 
 
			        
 
 | 
			
				|  |  
				|  Posted: Wed Dec 03, 2008 3:43 pm |   |  
				| 
 |  
				| Thanks for the feedback -I'll try something more efficient. |  |  
		|  |  
		| MarcosAmbrose 
 
 
 Joined: 25 Sep 2006
 Posts: 38
 Location: Adelaide, Australia
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Dec 03, 2008 3:44 pm |   |  
				| 
 |  
				| 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.
 
 
 | 
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Dec 03, 2008 3:50 pm |   |  
				| 
 |  
				|  	  | 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Dec 03, 2008 3:57 pm |   |  
				| 
 |  
				|  	  | 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
  |  |  
		|  |  
		| crystal_lattice 
 
 
 Joined: 13 Jun 2006
 Posts: 164
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Dec 04, 2008 2:47 am |   |  
				| 
 |  
				| 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
 
 
 
 
 
 
 
			
			
			
			
			
			
			
			
			
 
 | 
			
				|  |  
				|  Posted: Thu Dec 04, 2008 4:05 am |   |  
				| 
 |  
				| A quick search here, will find posted code, to give input/output on a variable pin, using V3 compilers. 
 Best Wishes
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |