Learning to program the PIC16LF1823

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Ok ... I found this VERY useful document after doing some googling, and it directed me to the contents of the p10lf322.inc file included in the mpasmx utility. This is the relevant section for what I want to dig into and thoroughly understand:


Code:
==========================================================================
;
;       Configuration Bits
;
;   NAME            Address
;   CONFIG            2007h
;
;==========================================================================

; The following is an assignment of address values for all of the
; configuration registers for the purpose of table reads
_CONFIG         EQU  H'2007'

;----- CONFIG Options --------------------------------------------------
_FOSC_INTOSC         EQU  H'3FFE'; INTOSC oscillator: CLKIN function disabled
_FOSC_EC             EQU  H'3FFF'; EC: CLKIN function enabled

_BOREN_OFF           EQU  H'3FF9'; Brown-out Reset disabled
_BOREN_SBODEN        EQU  H'3FFB'; Brown-out Reset controlled by the SBOREN bit in the BORCON register
_BOREN_NSLEEP        EQU  H'3FFD'; Brown-out Reset enabled while running and disabled in Sleep
_BOREN_ON            EQU  H'3FFF'; Brown-out Reset enabled

_WDTE_OFF            EQU  H'3FE7'; WDT disabled
_WDTE_SWDTEN         EQU  H'3FEF'; WDT controlled by the SWDTEN bit in the WDTCON register
_WDTE_NSLEEP         EQU  H'3FF7'; WDT enabled while running and disabled in Sleep
_WDTE_ON             EQU  H'3FFF'; WDT enabled

_PWRTE_ON            EQU  H'3FDF'; PWRT enabled
_PWRTE_OFF           EQU  H'3FFF'; PWRT disabled

_MCLRE_OFF           EQU  H'3FBF'; MCLR pin function is digital input, MCLR internally tied to VDD
_MCLRE_ON            EQU  H'3FFF'; MCLR pin function is MCLR

_CP_ON               EQU  H'3F7F'; Program memory code protection is enabled
_CP_OFF              EQU  H'3FFF'; Program memory code protection is disabled

_LVP_OFF             EQU  H'3EFF'; High-voltage on MCLR/VPP must be used for programming
_LVP_ON              EQU  H'3FFF'; Low-voltage programming enabled

_LPBOR_OFF           EQU  H'3DFF'; BOR disabled
_LPBOR_ON            EQU  H'3FFF'; BOR enabled

_BORV_HI             EQU  H'3BFF'; Brown-out Reset Voltage (Vbor), high trip point selected.
_BORV_27             EQU  H'3BFF'; Brown-out Reset Voltage (Vbor), high trip point selected.
_BORV_LO             EQU  H'3FFF'; Brown-out Reset Voltage (Vbor), low trip point selected.
_BORV_19             EQU  H'3FFF'; Brown-out Reset Voltage (Vbor), low trip point selected.

_WRT_ALL             EQU  H'27FF'; 000h to 1FFh write protected, no addresses may be modified by PMCON control
_WRT_HALF            EQU  H'2FFF'; 000h to 0FFh write protected, 100h to 1FFh may be modified by PMCON control
_WRT_BOOT            EQU  H'37FF'; 000h to 07Fh write protected, 080h to 1FFh may be modified by PMCON control
_WRT_OFF             EQU  H'3FFF'; Write protection off
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Normally, I would config the chip through directly accessing its appropriate register's bits. This because I like to keep a through and always-fresh understanding of its architecture. That's why I don't like 'directives'. They make things simpler and easier, but they also obscure the architecture's foundation... what's the point of programming in assembly if one doesn't go all the way down into the basics?
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
A simple question:

upload_2018-7-10_9-43-21.png

What does the previous table tell about the configuration word default reset value? That every bit is set as "1"? Why the "1/1" and "R/P" statements in the top row? Because the bit is both Readable and Programmable? What's the difference between "Writing" a bit and "Programming" a bit?
 

MaxHeadRoom

Joined Jul 18, 2013
28,696
As per post #18, it pays to check the INC file.

For example when getting to the higher end such as the 18F series. the CONFIG format has now been changed slightly.
Example:
Code:
;==========================================================================
;
;  IMPORTANT: For the PIC18 devices, the __CONFIG directive has been
;  superseded by the CONFIG directive.  The following settings
;  are available for this device.
;
;  Oscillator Selection bits:
;  FOSC = LP  LP oscillator
;  FOSC = XT  XT oscillator
;  FOSC = HSHP  HS oscillator (high power > 16 MHz)
;  FOSC = HSMP  HS oscillator (medium power 4-16 MHz)
;  FOSC = ECHP  EC oscillator, CLKOUT function on OSC2 (high power, >16 MHz)
;  FOSC = ECHPIO6  EC oscillator (high power, >16 MHz)
;
;etc
;  4X PLL Enable:
;  PLLCFG = OFF  Oscillator used directly
;  PLLCFG = ON  Oscillator multiplied by 4
;
;  Primary clock enable bit:
;  PRICLKEN = OFF  Primary clock can be disabled by software
;  PRICLKEN = ON  Primary clock enabled
;
;  Fail-Safe Clock Monitor Enable bit:
;  FCMEN = OFF  Fail-Safe Clock Monitor disabled
;  FCMEN = ON  Fail-Safe Clock Monitor enabled
;
Max.
 
Last edited:

OBW0549

Joined Mar 2, 2015
3,566
What does the previous table tell about the configuration word default reset value? That every bit is set as "1"?
Yes.

Why the "1/1" and "R/P" statements in the top row? Because the bit is both Readable and Programmable?
Yes.

What's the difference between "Writing" a bit and "Programming" a bit?
"Writable" = can be written to under program control at execution time (none of the bits are identified with a "W", so none of them can be written to in your program)

"Programmable" = can be set or reset by the IDE when a program is loaded.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Ok ... here's my first little snippet of code. Yay! ...

I want to: disable the watchdog timer, use the MCLR pin as a digital input, and use the device's internal oscillator and thus use the CLKIN pin as an I/O. Everything else stays in its default state.

Code:
;*****************************************************************************************
;                                   10 JUL 2018, 10:23:51 AM:   
;                            Generator controller for the PIC10LF322
;*****************************************************************************************

       list          p=10LF322                   ; list directive to define processor
       #include      <P10LF322.INC>              ; processor specific variable definitions

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

jpanhalt

Joined Jan 18, 2008
11,087
@cmartinez
That code snippet looks good.

Back to your rhetorical(?) question about changing configuration during runtime. My guess was that you cannot. As pointed out, programmable doesn't mean writable. But I tested it anyway:
Code:
;     movlb     31
     movlw     low(_Config1)
     movwf     count
     movf      high(_Config1),w
     movwf     temp
     nop
The first instruction does in fact return the correct location. For my chip (PIC16F1827) that is 0x8007, and 0x8007 was returned when both instructions were movlw. However, you cannot read the register at that location (i.e, movf high(_Config1)) returns 0x00. Changing the bank has no effect and FSR's do not reach past 0x7FFF . To test that, I loaded 0x8007 into FSR0 and INDF0 returned values, but they did not correspond to the expected values.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Ok,, here's my first complete attempt.

I want to:

1.- Set RA1 as an input (weak pull-up enabled) with a button that will short it to ground when pressed.
2.- Set RA0 as an output.
2.- Copy the state of RA1 into RA0. That is RA0 = 1 when button is not pressed, RA0 = 1, and RA0 = 0 when the button is pressed.

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=10LF322                   ; list directive to define processor
       #include      <P10LF322.INC>              ; processor specific variable definitions

       ; - 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  CODE   0x000                       ; processor reset vector
              goto   Init                        ; go to beginning of program

INT_VECTOR    CODE   0x004                       ; interrupt vector location
              goto   Init

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

;************************************* I/O definitions ***********************************
       ; - 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 PORTA       ;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

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

Set_Ra0
       bsf PORTA, RA0
      goto ProgramLoop ;loop endlessly through this logic
  
Clr_Ra0
       bcf PORTA, RA0
      goto ProgramLoop ;loop endlessly through this logic
  
     END
Question, are the instructions in lines 54 and 55 being used correctly?
 

jpanhalt

Joined Jan 18, 2008
11,087
Looks worth a try!

I understand that you are not enabling interrupts, but this structure:
Code:
[LIST=1]
[*]RESET_VECTOR  CODE   0x000                       ; processor reset vector
[*]              goto   Init                        ; go to beginning of program
[*]

[*]INT_VECTOR    CODE   0x004                       ; interrupt vector location
[*]              goto   Init
[/LIST]
would lead to problems if they were enabled. An interrupt is like a "call" , if you don't return from it, you will get a stack overflow and reset. At Line 5, use "retfie". That instruction returns from interrupt, thereby clearing the address, and resets GIE.

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.

John
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Looks worth a try!

I understand that you are not enabling interrupts, but this structure:
Code:
[LIST=1]
[*]RESET_VECTOR  CODE   0x000                       ; processor reset vector
[*]              goto   Init                        ; go to beginning of program
[*]

[*]INT_VECTOR    CODE   0x004                       ; interrupt vector location
[*]              goto   Init
[/LIST]
would lead to problems if they were enabled. An interrupt is like a "call" , if you don't return from it, you will get a stack overflow and reset. At Line 5, use "retfie". That instruction returns from interrupt, thereby clearing the address, and resets GIE.

John
Good call... I understand exactly what you're saying ... gonna correct the code right now
 

jpanhalt

Joined Jan 18, 2008
11,087
Try this, changes highlighted:
upload_2018-7-10_14-6-9.png

"Code" is a directive for relocatable code. You probably want "absolute."
Same goes for the vectors.
Helpful but not required to define radix as decimal. That's how my brain works. Default is hex, I think.
You may get an error at the config directive. Click on "configure" in the Assembler and be sure the correct device is selected. After those changes, it compiled fine for me.

Sorry my first review was so sloppy. Of course, getting something to compile is the lowest hurdle you will face.

Edit: My version of MPASM is 5.51. The device is covered in it, except there is no template for it.

Edit#2: @cmartinez
Are you using relocatable or absolute code. I get the feeling it is the former.
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Try this, changes highlighted:
View attachment 155963

"Code" is a directive for relocatable code. You probably want "absolute."
Same goes for the vectors.
Helpful but not required to define radix as decimal. That's how my brain works. Default is hex, I think.
You may get an error at the config directive. Click on "configure" in the Assembler and be sure the correct device is selected. After those changes, it compiled fine for me.

Sorry my first review was so sloppy. Of course, getting something to compile is the lowest hurdle you will face.

Edit: My version of MPASM is 5.51. The device is covered in it, except there is no template for it.
I was able to make it work as it is using MPLAB X IDE v4.20, which is the main program for the whole software ... of course, I don't like it one bit, but I still have to use it to load the program into the MCU using the PICkit3 device programmer. I'll let you know how it went.

Many thanks for all your help.
 
Top