| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| respected 
 
 
 Joined: 16 May 2006
 Posts: 95
 
 
 
			    
 
 | 
			
				| Changeable PIN name |  
				|  Posted: Thu Nov 23, 2017 6:28 am |   |  
				| 
 |  
				| Hi; 
 i want to write driver code. But something is wrong.
 
 output_bit(pin, shift_right(&data,1,0));
 
 This line has problem. Other lines are good. There is no problem.
 When i change pin as below, it is OK.
 
 Where is problem?
 
 output_bit(PIN_A0, shift_right(&data,1,0));
 
 
  	  | Code: |  	  | void onewire_reset(int16 pin) {
 output_low(pin);
 delay_us( 500 );
 output_float(pin);
 delay_us( 500 );
 output_float(pin);
 }
 
 
 void onewire_write(int data,int16 pin)
 {
 int count;
 for (count=0; count<8; ++count)
 {
 output_low(pin);
 delay_us( 2 );
 output_bit(pin, shift_right(&data,1,0));
 delay_us( 60 );
 output_float(pin);
 delay_us( 2 );
 }
 }
 | 
 |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 23, 2017 7:25 am |   |  
				| 
 |  
				| The code will compile as posted. Nothing wrong from that point of view. But it hasn't got a hope of working. The problem is _time_. Onewire is a timing critical bus. Using a variable as a pin name, massively slows down the I/O function. A bit set or clear on a pre-defined pin, is a single assembly instruction. One using a variable for the on/off immediately takes about four instruction times. The shift adds a few more, but using a variable for a pin name, takes it up to using several dozen instructions. It has to actually calculate the bit offset needed, and extract the register address for every single operation. Being too generic here just destroys the possibility of getting the timings to work.
 
 Have a look at this thread where the basics of changing the functions to support more than one pin were discussed:
 <http://www.ccsinfo.com/forum/viewtopic.php?t=36953&highlight=onewire+variable+pin>
 
 It is actually possible to code it in a different way, by extracting the register and bit number just once at the start of the loop. Only worth doing this though if you needed to access a lot of pins. The version shown in the thread above is much simpler.
 |  | 
	
		|  | 
	
		| Mike Walne 
 
 
 Joined: 19 Feb 2004
 Posts: 1785
 Location: Boston Spa UK
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 23, 2017 7:26 am |   |  
				| 
 |  
				| How does the compiler KNOW which pin to operate on for these  lines? 
 
  	  | Quote: |  	  |  	  | Code: |  	  | output_low(pin);
 .
 .
 .
 output_float(pin);
 .
 
 
 | 
 | 
 
 Mike
 |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 23, 2017 7:50 am |   |  
				| 
 |  
				| 'pin' is a variable he is passing to the function. This will work, but the time involved is far too long to be used for OneWire.... |  | 
	
		|  | 
	
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 23, 2017 8:07 am |   |  
				| 
 |  
				| As others have said Dallas One wire protocol is very 'time sensitive' ! The easy way, the 'cheat', the way I did it was to just copy the 'one wire' driver 4x ,renaming variables as required to control the 4 pcs of DS18B20s temperature devices for a greenhouse controller project.
 
 While 'one wire' does allow 'daisy chaining'  of multiple devcies on one bus,since the sensors were 'all over' the greenhouse , it was far simpler to have a 2pole connector for each and dedicate a pin per device.
 
 Code space is not an issue, PICS have tons of memory these days.
 
 Jay
 |  | 
	
		|  | 
	
		| newguy 
 
 
 Joined: 24 Jun 2004
 Posts: 1924
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 23, 2017 8:34 am |   |  
				| 
 |  
				|  	  | temtronic wrote: |  	  | Code space is not an issue, PICS have tons of memory these days. | 
 
 You'll be lamenting your PIC's lack of resources if you write an NMEA 2000 compliant CAN driver.
  |  | 
	
		|  | 
	
		| respected 
 
 
 Joined: 16 May 2006
 Posts: 95
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 23, 2017 8:35 am |   |  
				| 
 |  
				| I don't want to use this.  But I think the only way to do this 
 
 
  	  | Code: |  	  | #define ONE_WIRE_PIN1 PIN_A0 #define ONE_WIRE_PIN2 PIN_E1
 #define ONE_WIRE_PIN3 PIN_A5
 #define ONE_WIRE_PIN4 PIN_B1
 /////////////// 11111111111111111111111111111////////////////////////
 void onewire_reset1()
 
 {
 output_low(ONE_WIRE_PIN1);
 delay_us( 500 );
 output_float(ONE_WIRE_PIN1);
 delay_us( 500 );
 output_float(ONE_WIRE_PIN1);
 }
 
 void onewire_reset2()
 
 {
 output_low(ONE_WIRE_PIN2);
 delay_us( 500 );
 output_float(ONE_WIRE_PIN2);
 delay_us( 500 );
 output_float(ONE_WIRE_PIN2);
 }
 .
 .
 .
 
 | 
 |  | 
	
		|  | 
	
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Nov 23, 2017 8:43 am |   |  
				| 
 |  
				| Yes, that's what I did several years ago. As I said it's a clean, simple and it works. It's also very easy to use 'find/replace' to make copies of the driver. I used 'OW' for 'one wire' as I'm a terrible typist.
 |  | 
	
		|  | 
	
		|  |