PDA

View Full Version : PBP migration from 16F88 to 16F1827



RussMartin
- 25th February 2010, 00:32
Okay, I'm overlooking something. This program worked (albeit slowly) on a 16F88.

5 analog pins sample and (after manipulation) produce a high or low to a pin. Here's the correspondence:

AN0 to B5
AN1 to B4
AN2 to B3
AN3 to B2
AN4 to B1

AN5 and AN6 each have the wiper of a different pot on them.

Now, only AN4 to B1 works correctly. B5 is stuck high all the time (from power-up), even with no signal on AN0. The three in between are off if there is no signal but stick high as soon as a small signal is applied and remain that way until power-down.

The pot on AN5 has the correct effect on the one working channel but AN6 does not appear to be working.

Here's what I had in the (totally working) 16F88 version:

DEFINE OSC 8

ANSEL= %01111111
CMCON= %00000111
OSCCON= %01110000
TRISA= %01111111
TRISB= %11000001

ADCON1.7=1

DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 5
DEFINE ADC_SAMPLEUS 12

. . . and here's what I have for the 16F1827:

DEFINE OSC 32

ANSELA= %00011111
ANSELB= %11000000
OSCCON= %11110000
TRISA = %01111111
TRISB = %11000001

ADCON1.7 =1
CM1CON0.7=0
CM2CON0.7=0

DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 6
DEFINE ADC_SAMPLEUS 12

What thing(s) am I failing to do?

RussMartin
- 25th February 2010, 04:58
I discovered the capacitive sensing module and have added:

CPSCON0.7=0 to turn it off.

The effect was that the one working channel continues to work.

The pot on AN6 also now works.

But now all the other four channels lock high at power-up, even with no signal, and stay there.

I guess that's a tiny speck of progress.

mackrackit
- 25th February 2010, 05:23
I have had trouble in the past with the built in ADC commands.
You may want to try the method used here.
http://www.picbasic.co.uk/forum/showpost.php?p=79832&postcount=16

RussMartin
- 25th February 2010, 05:50
I've also tried to make sure the CCP/ECCP modules were off by adding:

CCP1CON=%00000000
CCP2CON=%00000000
CCP3CON=%00000000
CCP4CON=%00000000

No change from previous result.

Darrel Taylor
- 25th February 2010, 20:01
What thing(s) am I failing to do?

Well, you failed to include the part that reads the A/D, "Manipulates" it, then outputs it to a pin. :confused:
<br>

RussMartin
- 25th February 2010, 20:41
I didn't include anything else because (a) everything ran fine on the '88 and (b) one of the five identically-processed channels is working just fine.

All five channels are handled like this (different VARs, of course) in a loop, with the interrupt enabled:

FOR SAMPLX=4 TO 1 STEP -1
ADCIN 2,INMD
IF INMD>TEMPMD THEN TEMPMD=INMD
NEXT SAMPLX
INMD=TEMPMD
IF MODE=1 THEN GOTO HOP3
IF INMD>341 THEN
INMD=(INMD-342)*3
ELSE
INMD=0
ENDIF
HOP3:
IF INMD<10 THEN COMP=0
IF INMD<THRES THEN INMD=THRES+INMD+COMP
INMD=INMD+COMP
IF INMD>1023 THEN INMD=1023
TEMPMD=0
XMD=INMD/2

The INT_INT handler looks like this:

STATE:
FOR INDEX=511 TO 1 STEP -1
IF INDEX=XLO THEN OLO=1
IF INDEX=XLM THEN OLM=1
IF INDEX=XMD THEN OMD=1
IF INDEX=XMH THEN OMH=1
IF INDEX=XHI THEN OHI=1
NEXT INDEX
OLO=0 : OLM=0 : OMD=0 : OMH=0 : OHI=0
@ INT_RETURN

RussMartin
- 25th February 2010, 21:57
Here it is:

@ __config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF & _BOREN_OFF & _FCMEN_OFF
@ __config _CONFIG2, _STVREN_OFF & _LVP_OFF

OLO VAR PORTB.5
OLM VAR PORTB.4
OMD VAR PORTB.3
OMH VAR PORTB.2
OHI VAR PORTB.1

DEFINE OSC 32

ANSELA= %00011111
ANSELB= %11000000
CCP1CON=%00000000
CCP2CON=%00000000
CCP3CON=%00000000
CCP4CON=%00000000
OSCCON= %11110000
TRISA = %01111111
TRISB = %11000001

MAIN:
OLO=1 : PAUSE 1000 : OLO=0
OLM=1 : PAUSE 1000 : OLM=0
OMD=1 : PAUSE 1000 : OMD=0
OMH=1 : PAUSE 1000 : OMH=0
OHI=1 : PAUSE 1000 : OHI=0
GOTO MAIN

END

No ADCs, no triac output, nothing but outputs low to high and back.

Results:

Each channel comes on in succession. The first four, however, than simply stay on. The fifth goes on and off exactly as you would expect.

I even tried this on a "fresh" '1827. No difference.

This is why I remain convinced that the problem hides in how I'm configuring something that affects B.2 through B.5 but permits B.1 to operate normally.

Darrel Taylor
- 25th February 2010, 22:03
Try this Russ,


OLO VAR LATB.5
OLM VAR LATB.4
OMD VAR LATB.3
OMH VAR LATB.2
OHI VAR LATB.1

<br>

RussMartin
- 25th February 2010, 22:43
Sonofagun! It works. Thanks!

What did we just do?

And why was PORTB.1 working but not the others?

Archangel
- 25th February 2010, 23:48
Sonofagun! It works. Thanks!

What did we just do?

And why was PORTB.1 working but not the others?
. . . and what is the "real" difference between LATB & PortB ?
I am sensing a RMW issue . . . Thanks Darrel, in advance.

Darrel Taylor
- 26th February 2010, 00:30
It's the old R-M-W issue (Read-Modify-Write).

PIC's can't write to individual Pins in a PORT. It's not possible for the hardware to just set a pin high or low directly.
It has to Read the entire PORT, Modify the bit it wants to change, then Write the value back to the Entire PORT.
When it Reads the PORT, it actually reads the state of the Pins, not the state it was told to be in last.

In your code ...

MAIN:
OLO=1 : PAUSE 1000 : OLO=0
OLM=1 : PAUSE 1000 : OLM=0
OMD=1 : PAUSE 1000 : OMD=0
OMH=1 : PAUSE 1000 : OMH=0
OHI=1 : PAUSE 1000 : OHI=0
GOTO MAIN

The OLM=1 statement is executed immediately(125nS) after the OLO=0 statement.
If the voltage on the OLO pin has not reached the level required to register a 0, then it reads OLO as 1 and writes that back to the PORT, ignoring that fact that you just told it to be 0.
Capacitance on the Pin will increase the amount of time it takes to reach the requested state.
Solderless breadboards can add quite a bit. LED's add some too.

Just like the 18F's, the 16F1's have LATx (DATA LATCH) registers.
If you use PORTB.0, it does the RMW on the PORT, then writes it to the LATB register which controls the pins state.

If you write directly to LATB.0, it doesn't read the port first.
It still does a read-modify-write, but what it reads is the LATB value (last requested state), not the state of the Pins.

DO NOT! use HIGH, LOW, TOGGLE, or any other PBP commands like SERIN/OUT, PULSIN/OUT etc. with LATx.x as a Pin.
It will cause big problems.

But writing to the LATx bits directly with a 1 or 0 can eliminate the dreaded R-M-W problem.

hth,

RussMartin
- 26th February 2010, 00:40
Then:

The reason the old PORTB.1 worked is that little scootch of additional time between OHI=0 and OLO=1 caused by the GOTO?

Were there Olympic Gold for PBP help, you'd get it!

Darrel Taylor
- 26th February 2010, 01:27
Then:

The reason the old PORTB.1 worked is that little scootch of additional time between OHI=0 and OLO=1 caused by the GOTO?
Exactly!

<table><tr><td align=right>
Were there Olympic Gold for PBP help, you'd get it!
Hmmm, I could go for some gold ... :D &nbsp; &nbsp;</td><td> http://www.export-forum.com/europe/golden-beer/images/golden-beer-7.9%25-s.jpg</td></tr></table>


<br>

Macgman2000
- 19th June 2010, 01:15
I came across the R-M-W issue today, I thought I was losing my mind. I am glad I searched the archive for 16F1827 because for the life of me I couldn't get the darn ports to set and reset after a pause statement.

Has this problem been reported? Will it be fixed in the next PBP version update?

I am sorry for the 20 questions, it is just that I spent 2hrs troubleshooting my hardware. When that didn't pan out I dove into getting rudimentary features to work before seeking help. All in all a dang port toggle ate up 4hrs of my day...sigh.

Nick:(

Darrel Taylor
- 19th June 2010, 01:29
Has this problem been reported? Will it be fixed in the next PBP version update?It's not an issue with PBP.

It's just the way the PIC Hardware works.
And I assume it's why Microchip eventually added the LATx registers in the 18F's, and now the 16F1's.

Just keep it in mind when you try to change pin states really fast and they don't work (or they affect other pins in the same port).
Usually a minor change can fix it, even with 16F's.

Macgman2000
- 19th June 2010, 01:33
Thanks Darrel for the explanation. I guess it's good I cut my teeth on this problem early on. My next (week) project is using an 18F.....good to know what I am in store for.

Nick:)

Macgman2000
- 21st June 2010, 17:29
Hello Darrel,

I have some more weirdness going on. I got my code to work, but not the way I want it to.

When I read PortB using LatB, I can't seem to detect a set bit on B1. When I write directly to the
variable in my case statement I can step through the values and the outputs are correct. I can't
what is wrong with what I have. Code below.

ASM
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__config _CONFIG2, _PLLEN_OFF & _LVP_OFF & _LVP_OFF & _STVREN_OFF

ENDASM

DEFINE OSC 8



;************************************************* ******************************
;************************************************* ******************************
; System hardware configuration
;************************************************* ******************************
;************************************************* ******************************

OSCCON = %01110000 ' 8MHz internal
ANSELA = %00000000 ' all digital. A/D disabled
ANSELB = %00000000
TRISB = %00111111 ' set port directions 0 = output, 1 = input
TRISA = %00000000

Servo1 var byte
Servo2 var byte


srv2 VAR LATA.1
srv1 VAR LATA.0
PrtB VAR LATB

Program_init:
PortA = 0
POrtB = 0


Main_Loop:



Servo1 = PrtB and %00000111
gosub Servo_update1

Servo2 = PrtB and %00111000
gosub servo_update2

pause 10

goto main_loop


Servo_update1:

select case Servo1
case 0
srv1 = 1 : pauseus 1000 : srv1 = 0

CASE 1
srv1 = 1 : pauseus 1143 : srv1 = 0

case 2
srv1 = 1 : pauseus 1286 : srv1 = 0

case 3
srv1 = 1 : pauseus 1429 : srv1 = 0

CASE 4
srv1 = 1 : pauseus 1572 : srv1 = 0

case 5
srv1 = 1 : pauseus 1715 : srv1 = 0

Case 6
srv1 = 1 : pauseus 1858 : srv1 = 0

Case 7
srv1 = 1 : pauseus 2000 : srv1 = 0

END SELECT

return


Servo_update2:

select case Servo2
case 0
srv2 = 1 : pauseus 1000 : srv2 = 0

CASE 8
srv2 = 1 : pauseus 1143 : srv2 = 0

case 16
srv2 = 1 : pauseus 1286 : srv2 = 0

case 24
srv2 = 1 : pauseus 1429 : srv2 = 0

CASE 32
srv2 = 1 : pauseus 1572 : srv2 = 0

case 40
srv2 = 1 : pauseus 1715 : srv2 = 0

Case 48
srv2 = 1 : pauseus 1858 : srv2 = 0

Case 56
srv2 = 1 : pauseus 2000 : srv2 = 0

END SELECT

return

Darrel Taylor
- 21st June 2010, 17:47
When I read PortB using LatB, I can't seem to detect a set bit on B1.
The LATx registers only control the Output state of the pins.
When you Read LATx, you are reading the requested Output state.

If the pin is in Input mode, you need to read PORTx to see the state of the PIN.

Macgman2000
- 21st June 2010, 18:02
When I switch to portB instead of LATB to read, I get nothing from my code.

BTW I have 20K pull downs and dip switches tied to +vcc to switch in the bit pattern. There should
be NO case when the output is nothing....even if pullups or pulldowns are messed up.

Nick

Darrel Taylor
- 21st June 2010, 18:09
>Servo1 = PrtB and %00000111

Try it with a bitwise & instead of a logical AND.

Macgman2000
- 21st June 2010, 18:14
You are absolutely correct !!! Thanks for the fresh pair of eyes :)
Nick