RandoSY / jallib

Automatically exported from code.google.com/p/jallib
0 stars 0 forks source link

Flipping a pin with the 18F PICs #169

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
Failing 'alternative' blink-a-led program with an 18F (18F67k90).

This works:

 forever loop
    led = true                      -- on
    _usec_delay(250_000)
    led = false                     -- off
    _usec_delay(250_000)
 end loop

This doesn't work (the LED doesn't blink):

 forever loop
    led = !led                      -- flip
    _usec_delay(250_000)
 end loop

I thought that we agreed on the principle: always read from PORTx and  always 
write to LATx (for PICs which have LATx registers). 
Therefore in the Jallib device files of the 18F and extended midrange PICs a 
read from a port or pin always uses the PORTx register, while a write to a port 
or pin always uses the LATx register (via pseudo variables). 

The first case above there are only writes to the pin involved (to LATx 
register), so there is no read involved.

In the second case however the pin has to be read before it can be flipped 
properly. Thus the current state of the led-pin is read from the PORT register 
and the flipped state written to the LAT register. But this seems not to work 
(in this case).

When writing to a pin it has probably(!) been configured (via TRIS) for output. 
The question is: must in this case the PORT register be read or the LAT 
register?

Original issue reported on code.google.com by robhamerling on 16 Nov 2011 at 9:52

GoogleCodeExporter commented 8 years ago
For a test I used a modified device file such that for a read of the led-pin 
the LAT register is used (in my case for pin_A0 the contents of LATA_LATA0 is 
returned). And now also the second blink program works properly!

It might be necessary to modify the device files is such a way that for the 
read of a port or pin the TRIS register must be consulted: when configured for 
input read the PORT register, when configured for output read the LAT register. 

Original comment by robhamerling on 16 Nov 2011 at 9:58

GoogleCodeExporter commented 8 years ago

Hi gentlemen,
I appreciate your comments, but would like to keep these together in the 
issue-section of GoogleCode. So please do not 'reply' to the messages which are 
send by GogleCode to Jallib, but rather add your comments online in issue 169 
of GoogleCode.

Here a copy of your contributions so far:  

Kiste:

> It might be necessary to modify the device files is such a
> way that for the read of a port or pin the TRIS register
> must be consulted: when configured for input read the PORT
> register, when configured for output read the LAT register.

Hummm... This is not an easy subject. A pin can change its function and be both 
input and output while running a program. So this decision would have to be 
made at runtime. That would cost some code space, and, what concernes me more, 
execution time. I wouldn't want such basic tasks like reading a pin take more 
time than neccessary. 

The read-modify-write-problems are extensively described in the PIC datasheets, 
as well as the fact that a loaded pin may read not back the value it is 
driving. 

My opinion would be, that the program using 

led=!led

is simply faulty. If one is programming a microcontroller, he should have at 
least some knowledge about electronics. If he doesn't want to care about 
hardware, programming a computer would be the choice.

------------------
Matt:

> My opinion would be, that the program using
>
> led=!led
>
> is simply faulty. If one is programming a microcontroller, he should have at 
least some knowledge about electronics. If he doesn't want to care about 
hardware, programming a computer would be the choice.
I disagree, this is not a faulty program. Flipping a led should be
allowed just like any other variable. If it is left as it is, some
libraries will not work.

----------------------------
Joep:

This is an interesting issue.

IIRC the (some?) 16F chips suffer from the RMW issue. This means that although 
an output pin is set to low, it might read back high due to load or capacity. 
If you change an other pin on the same port, the operation to set that 
particular bit might flip bits of other pins.

However, inverting the pin means RMW at 'user level' and I'd say this is always 
prone to the RMW issue, since you tell to read the pin, invert the value and 
write it again.

Microchip fixed the RMW issue (due to bit-operations) with the LAT register.

I don't understand what's happening here. A led is no heavy load and 250ms 
handles the capacity. So why is the value of the pin not equal to its driven 
value?

PS Actually, this happend to me quite a few times. It always turned out the pin 
was set as analog, so reading its digital level was not supported.

PPS I would not be in favor of additional overhead to check pin direction and 
select source on that. We're not trying to exceed the Arduino library overhead, 
are we? ;) 

Original comment by robhamerling on 16 Nov 2011 at 3:18

GoogleCodeExporter commented 8 years ago
Matt:
>I disagree, this is not a faulty program. Flipping a led should be allowed 
just like any other variable.

A LED is not a variable, but a device connected to a peripheral, a port in this 
case. A pin configured as input can not be flipped, neither can read- or 
write-only bits be flipped (think of TXREG or the like). 

A LED can be a heavy load. Ports F,G,H and bits 0-5 of port A can sink or 
source 2mA, ports D,E and J can sink or source 8mA. Only ports B,C and bits 6-7 
of port A can sink or source the "usual" 25mA. 

To reliably read "low", the voltage must be below about 0.8V. Driving one of 
the "strong" outputs low, the voltage will rise to a max of 0.6V at 8.5mA - 
while LEDs are often driven with much more than 8.5mA. Thus the datasheet does 
not state clearly that a pin driving a value at more than 8.5mA can reliably 
read the driven value back.

Does the LED blink if you're using a resistor of, say, 5kOhm? You'll have to 
look closely... ;-)

Original comment by karlki...@yahoo.com on 16 Nov 2011 at 5:55

GoogleCodeExporter commented 8 years ago
Thank you Kiste, it looks like you hit the nail on the head! Without checking 
the datasheet I assumed pin_A0 could drive a normal 10-20 mA LED. And it seems 
to do so, but this is beyond specifications. Section 31.0 of datasheet 39957D 
tells me that it can source and sink only 2 mA! 
With the led on pin_C2 the program (with led = !led) works fine! 
I didn't try the 5K resistor suggestion.

I think this issue doesn't need a fix and can be closed as 'user error'. Agreed?

Original comment by robhamerling on 16 Nov 2011 at 8:04

GoogleCodeExporter commented 8 years ago
I guess my statement 'a led is not a heavy load' was wrong in this particular 
case or - more specific - the led load is out of spec. This explains why this 
happens and as far as I am concerned, issue close.

Joep

Original comment by jsu...@gmail.com on 16 Nov 2011 at 9:38

GoogleCodeExporter commented 8 years ago
Are the blink a led samples still considered good on pin_a0 for these PIC's?

Matt.

Original comment by mattschi...@hotmail.com on 17 Nov 2011 at 3:07

GoogleCodeExporter commented 8 years ago
If we would define the "standard blink circuit" as a low-current-LED and a 
2.2kOhms resistor, we would not overload even the weakest port pins. Reading 
back the right value is guaranteed by the datasheet with such a light load even 
on the weak pins. 

Original comment by karlki...@yahoo.com on 17 Nov 2011 at 6:52

GoogleCodeExporter commented 8 years ago
Currently the blink samples do not specify any circuitry requirements.  
I'm afraid the MPLAB files do not contain info about maximum pin current, 
otherwise I could easily select a 25 mA pin for the blink samples!
I like the suggestion of Kiste to recommend using a low current led and 
appropriate series resistor because the chosen pin may not drive an ordinary 
led.

Original comment by robhamerling on 17 Nov 2011 at 8:12

GoogleCodeExporter commented 8 years ago
In the next version of the blink samples I'll add the following comment:
suggestion to use a low-current led with 2.2k series resistor to be safe.

-- A low current (2 mA) led with 2.2K series resistor is recommended
-- since the selected pin may not drive an ordinary 20mA led.

Issue closed.  Rob.

Original comment by robhamerling on 23 Nov 2011 at 7:49