Learning to program the PIC16LF1823

JohnInTX

Joined Jun 26, 2012
4,787
The assembler knows how to resolve the differences between LATA and PORTA as long as you, the programmer, know the differences. For now, it is sufficient to use PORT only for actual inputs (switches etc.) and LAT for everything else. Trust me on this one.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
My reasoning is pure and my strident insistence on same is derived from hard experience.
and I'm guessing the operative word of that last statement is "hard" ... :D

dude ... I've been there and done that ... I've gone through countless migraines and spent endless hours trying to bug-out stupid mistakes and overlooked details while learning this sort of stuff ... you have no idea of how much I'm appreciating your help at this moment ... "thanks" doesn't quite say it ... :)

please ... don't leave me until I get through this :eek::eek: ... :D
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
The assembler knows how to resolve the differences between LATA and PORTA as long as you, the programmer, know the differences. For now, it is sufficient to use PORT only for actual inputs (switches etc.) and LAT for everything else. Trust me on this one.
I think I know what the difference is ... PORTA reads the physical state of the pins, while LATA reads what the user is telling the pin to do. For instance, if I write a 1 to the pin but then short it to ground, PORTA will read a 0, while LATA will read a 1 ... right?
 

JohnInTX

Joined Jun 26, 2012
4,787
and I'm guessing the operative word of that last statement is "hard" ... :D

dude ... I've been there and done that ... I've gone through countless migraines and spent endless hours trying to bug-out stupid mistakes and overlooked details while learning this sort of stuff ... you have no idea of how much I'm appreciating your help at this moment ... "thanks" doesn't quite say it ... :)

please ... don't leave me until I get through this :eek::eek: ... :D
Hard and expensive. And yup, been there with stupid mistakes. I actually have a billing code called 'dummy time' which is how I track stupid stuff that I can't in good conscience bill to clients. AAC has a lot of good PIC guys here so don't worry. PIC hardware can be *ahem* thorny but a lot of that is because they pack a lot of stuff into the chip. Once you get past that, the same programming skills from 8051 will apply.
 

JohnInTX

Joined Jun 26, 2012
4,787
I think I know what the difference is ... PORTA reads the physical state of the pins, while LATA reads what the user is telling the pin to do. For instance, if I write a 1 to the pin but then short it to ground, PORTA will read a 0, while LATA will read a 1 ... right?
Right!

Your understanding is correct, now consider the ramifications. When you do ANY r-m-w operation (bsf, bcf, iorwf,F ,incf F, etc.) the way the PIC does that is it reads the 8-bits of the register, does the operation then writes the 8 bits back. Two things should jump out here 1) reads the register and 2) 8 bits.

So for example, a bsf aBYTE,0 on RAM location 'aBYTE' reads the 8 bits of aBYTE, ORs it with 00000001 then writes the whole 8 bits back. Pretty simple. But the thing to keep in mind is that it works with the full 8 bit byte and that means it must read that 8 bits accurately to be able to restore the other 7 bits when it writes the byte back. Simple!

But consider what happens when you read a PORT. You are now reading the nasty, noisy, ugly outside world, all 8 bits of it. If you were reading the PORT as some switch input, you would of course do some signal conditioning on it, yes? Sure you would. Ugly stuff out there. Debouncing, deglitching, maybe a little digital filtering whatever but you sure wouldn't read the pin once and take it as gospel. At least I wouldn't..

But that's exactly what happens when you do something like bcf PORTx,x. It reads the entire 8 bits, clears one then writes the modified 8 bits back. If you are unlucky and you got hit with noise, a slow pin or lots of anything else, you could read a bad initial value from the PORT on any of the 7 other pins and write that back as a result of the bcf. This effect leads to problems like 'I turned off the LED on RA0 and the relay on RA5 turned ON - why??

I was a consultant for many years. I can an$wer that.

So.. the short answer is for inputs, read PORT, LAT for everything else. For PICs that have only PORT, don't use them. I have a whole essay on that too but time for a cocktail!

John

EDIT: same goes for TRIS. Never r-m-w on TRIS if any of the pins is shared by any peripheral. Always MOVWF TRISx. Ask me how I know this.
 
Last edited:

jpanhalt

Joined Jan 18, 2008
11,087
Because, the LATA register (or "file", in this stupid thing) does NOT have an RA0 bit, but rather a LATA0 bit ... the compiler should've reported that as an error ...
You wrote:
upload_2018-7-10_20-6-10.png
I suggested (#34)
Edit: On further review, you need to disable ANSELA for your digital inputs and outputs (RA0, RA1). As for setting a "pre" state, Since the input pin has a weak pullup, it is already high. I don't believe setting it to 1 will affect it. Output drivers are disabled on it. Finally, you will probably get by with reading and writing to the port, but since that chip has output latches, it is preferred to write to the latch (i.e, LATA) and read the port.
I didn't pay a lot of attention to how you identified the bits on that port, they typically are like RA0, RA1, etc.
upload_2018-7-10_20-12-5.png

In my experience, if you use an incorrect name, the Assembler will tell you. The bit names as you now know are RA0... Some chips (mostly the 12F5xx and 12F6xx), call then differently, namely GP0, GP1, etc. (GP is short for GPIO =general purpose I/O).

Glad it worked for you.

John

Edit: In most cases, you can just use a number, e.g, LATA,0. Remember, the number is the port name, not the pin number.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Something VERY strange is going on ... the voltage shown at the output pin R0 is very unstable, and is zero when it should be 3.3V ... but then, when I touch the chip with my finger, it suddenly jumps to 3.3V, then goes down to about 1.7V and stays there, very unsteadily ... if I press the button it goes down as it should, but when I release it it goes back up and starts to swing again ... what gives?

Here's the latest code, with the corrected "bsf LATA, LATA0" and "bcf LATA, LATA0" instructions in the end

Code:
;*****************************************************************************************
;                                   10 JUL 2018, 10:23:51 AM:  
;                            Generator controller for the PIC10LF322
;    The following program reads the state of the R1 pin and outputs it at the R0 pin
;*****************************************************************************************

       list          p=PIC10LF322                ;list directive to define processor
       #include      p10lf322.inc                ;processor specific variable definitions
       radix         dec

       ; - Flash memory self-write protection off     (default state)
       ; - Brown-out reset low trip point is selected (default state)
       ; - Low-power Brown-out Reset is enabled       (default state)
       ; - High Voltage on MCLR pin must be used for programming
       ; - Program memory code protection disabled    (default state)
       ; - MCLR pin set as digital input
       ; - Power-up Timer disabled                    (default state)
       ; - Watchdog timer disabled
       ; - Brown-out reset is enabled                 (default state)
       ; - Internal oscillator is activated
      
       __CONFIG _LVP_OFF & _MCLRE_OFF & _WDTE_OFF & _FOSC_INTOSC


;*****************************************************************************************
;                       Reset and Interrupt program memory locations
;*****************************************************************************************
RESET_VECTOR  ORG    0x000                       ;processor reset vector
              goto Init                          ;go to beginning of program

INT_VECTOR    ORG    0x004                       ;interrupt vector location
              retfie                             ;return from interrupt

;*****************************************************************************************
;                                   Main program start
;*****************************************************************************************
Init

       ;the reference Clock output bit CLKROE is disabled by default, we'll leave it that way
       ;set the internal oscillator frequency to 31 KHz (the lowest possible), this is done
       ;by clearing the IRCF bits, which belong in bit locations 4, 5 and 6, respecively

       movlw b'10001111'  ;the W register has been loaded with the IRCF bits as zeroes
       andwf OSCCON, f    ;AND the W register with OSCCON, storing the result in OSCCON

       clrf   INTCON      ;make sure that all interrupts are disabled

;************************************* I/O definitions ***********************************
       CLRF ANSELA       ;clear the analog select register, which for some stupid reason
                         ;is enabled by default ... otherwise the digital i/o function
                         ;won't work
                        
       ; - set RA1 as an input, active low ... this means that we also have to enable its
       ;   internal weak pull-up
       ; - set RA0 as an output, active high ... leave RA2 as an input ... RA3 can ONLY be
       ;   an input
      
       ;BANKSEL PORTA  ;this instruction is not necessary with the 10LF322, since it only
       ;has one bank of SFRs
       movlw b'00000011' ;set appropriate pin states BEFORE enabling their i/o functions
       movwf LATA        ;R0, will be set as an output, with its startup state as one, R1
                         ;will be set as an active-low input with an internal pull-up
                         ;enabled, therefore it must be latched as one ... all other bits
                         ;are inconsequential

       ;10 JUL 2018, 5:57:17 PM: By the advice of JohnInTx, the following function has been
       ;cancelled, and a complete movwf to TRISA will be used instead
      ;bcf TRISA, TRISA0 ;clear bit TRISA0 located at the TRISA register, effectively setting
                         ;R0 as an output, all other bits remain in their defualt (1) state
       movlw b'00001110'
       movwf TRISA
                        
      ;the following instruction is unnecessary, since all internal weak pull ups are enabled
      ;by default when a pin is configured as an input
      ;bsf WPUA, WPUA1   ;activate the internal weak pull-up of the RA1 pin
      

ProgramLoop

      ;RA1 is an input, active low, which will go low when the button is pressed and connects
      ;it to ground ... therefore under the next logic, RA0 will remain high until the button
      ;is pressed
    
       btfss PORTA, RA1 ;skip next instruction if the button is unpressed
       goto Clr_Ra0
       goto Set_Ra0
      
       ;yeah, I know that this logic structure can be imporved substantially, but hey, I'm
       ;learning here!

       ;10 JUL 2018, 6:01:16 PM: again, the very sympathetic JohnInTx recommended using LATA
       ;instead of PORTA for all rmw (such as bsf and bcf) for some obscure and obnoxious
       ;reason. BUT the datasheet says that writing to PORTA and writing to LATA are the same
       ;thing ... the difference lies when *reading* from those registers ... the read
       ;instruction does not result in the same thing
Set_Ra0
       bsf LATA, LATA0
      goto ProgramLoop ;loop endlessly through this logic
    
Clr_Ra0
       bcf LATA, LATA0
      goto ProgramLoop ;loop endlessly through this logic
    
     END
 

JohnInTX

Joined Jun 26, 2012
4,787
Line 76, the weak pullup config is commented out? Plus you have to enable the whole shebang in OPTION_REG:WPUEN

Measure the digital input voltages on the switch pin?
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Line 76, the weak pullup config is commented out? Plus you have to enable the whole shebang in OPTION_REG:WPUEN
Yes it is ... because it's apparently unnecessary, according to the datasheet ... I'm gonna un-comment it, and see what happens...

EDIT, I just did, and the situation hasn't changed ... gonna check the PCB, pin by pin, and node by node ...
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Here's an interesting observation ... I'm very much in love with Programmer's Notepad 2 for all of my editing work. I'm using it and not the default editor included in MPLAB X. But the editor in MPLAB X upgrades the file being shown if it was modified and saved from my PM2 software... it's like if both programs have no problem working with each other.
 

JohnInTX

Joined Jun 26, 2012
4,787
De hecho, soy el hombre en lo que respecta a PIC.

Glad it's working!

EDIT: BTW, have you bought the AC244045 debug header for this? Well worth the money.
 

JohnInTX

Joined Jun 26, 2012
4,787
If using Interrupts the Retfie is return and interrupt enable.
When servicing an interupt it prevents any other interupt from happening until the retfie.
Max.
Your comment in the code says 'Why return and not retfie?' To answer, it's because with no interrupt service routines, there should be no interrupts at all. If there are, it is an error. The solution I posted was to disable all interrupts then just return. RETFIE returns and reenables interrupts so the problem would be restored. Note that to get to the interrupt vector at all you have to have made a mistake in your coding. You want to tamp it out right there.
 

MaxHeadRoom

Joined Jul 18, 2013
28,702
@cmartinez
I got in the habit of adding the colon on labels, it helps in the process when doing a search for example and the label is used in a few places in the code.
Max.
Code:
Main:
               bsf        ADCON0,GO_DONE    ; start an A-to-D conversion
               call    InitLCD            ; Initialize LCD Special Function Registers
               clrf     Counter
               clrf    TMR1L
              clrf    TMR1H

Loop:
              btfss    INTCON,T0IF        ; TMR0 is preloaded so than this loop is exited every 23.4ms
              goto    Loop
 
Top