|
|
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
|