Learning to program the PIC16LF1823

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Dang it! ... I missed the updates on this thread and I've just read the last three messages... the chips are gone.

But no matter, I found them from a few different suppliers in China and I've already ordered quite a few. Also, I found the much harder to get 16LF1825, which is exactly like the 23, but has 1024 bytes of SRAM instead of just 128
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
A quick question.

Is the instruction incf FSR0, f legit? ... I mean, the instruction does compile without reporting an error. But will the entire 16 bit value of FSR0 will be incremented? ... Would the same instruction work for the EEADR register? The reason I ask is because said instruction also compiles without reporting an error,
 

John P

Joined Oct 14, 2008
2,026
I'm pretty sure this won't work, because the INCF assembly instruction just works on an 8-bit register. For the FSR0 register though, you could fake it using the MOVIW instruction, "Move Indirect FSRn to WREG with pre/post inc/dec modifier". You don't actually have to make any use of the data that's put into WREG.
 

MaxHeadRoom

Joined Jul 18, 2013
28,698
One method from PicMicro forum.

read_loop:
; ...
incfsz EEADR
bra read_loop
or
read_loop:
; ...
incf EEADR
movf EEADR,w
sublw k
bnz read_loop
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
I also would like the answer, I pondered on it today using a 18F series pic EEADR.
I use this:

Code:
infsnz  EEADR,F            ; bump EE physical address
incf    EEADRH,F
It would work on FSRxL and FSRxH as well.

16F1xxxx doesn't have infsnz but you can cheat it out like this:
Code:
incf FSRxH,F ; pre-increment high byte
incfsz FSRxL,F ; increment low byte and if it rolled to 00, leave high byte incremented
decf FRxH,F ; else no rollover of low byte, decrement high byte to previous value

; or
 incf FSRxL,F ; bump low byte
 btfsc STATUS,Z ; iff it rolled over to 00..
 incf FSRxH,F ; bump high byte
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Here's a little trick I'd like to share that some of you might appreciate. Maybe you've already used this technique, @nsaspook ?

I use the MCP2221A USB to UART converter in practically all of my projects. Unfortunately, the default Tx (RA0) and Rx (RA1) pins in the PIC16LF1823 also correspond to the CSPDAT and CSPCLK lines which are used for programming the device. That means that every time I need to program the MCU, I have to physically remove the MCP2221A from the circuit so it won't interfere with the programming process. An error is usually reported by MPLAB X IDE if such is the case.

I know that the Tx and Rx UART pins are re-mappable, but doing so usually leaves me with the same problem in a design that makes use of every single pin available in the device. If I were to move the Tx and Rx functions to some other pins, I would have to connect something else to the original pins anyway. And whatever I were to connect to them also runs the risk of interfering with the programming process.


1656353705643.png

A few months ago, after giving some thought about how the Tx and Rx lines are supposed to work in both devices, I decided to try and place a BAT54 Schottky diode in each line so as to block the flow of current in the wrong direction in the MCP2221A. And lo and behold! ... my little tweak did the trick! ... I am now able to program the PIC without having to remove the MCP2221A from the circuit! ... One of my life's pet peeves has been solved and squashed... :)
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Here's another important question, this one related to the PIC16LF1825,


In example, in memory banks 0 and 1, the available addresses for GP RAM are 020H to 06FH for bank 0, and 0A0H to 0EFH for bank 1.

Will this set of instructions work?

Code:
VarA  EQU 0x21   ;VarA is located in register bank 0
VarB  EQU 0xA1   ;VarB is located in register bank 1

movlb 0          ;set register bank 0
movf VarA, w     ;copy the contents of VarA into VarB
movwf VarB
I've been playing with the FSR pointers lately, and I noticed that whenever I want to point anywhere in banks 0 and 1, FSRH ← 0x00 ... and then If I wanted to point to banks 2 and 3, then FSRH ← 0x01 ... and so on.

So it seems to me that when it comes to accessing registers between different banks, you can do it directly without having to change the active bank as long as their banks belong to the same "pair" of banks, such as bank 0 and bank 1, and then bank 2 and bank 3, and then bank 4 and bank 5, and so on
 

MMcLaren

Joined Feb 14, 2010
861
Your example will simply write the contents of VarA back into VarA (on the "enhanced mid-range" devices). Byte-oriented file register operations (like movf and movwf) only include 7 bits of the file register address within their 14 bit opcode.

The banksel pseudo instruction actually generates a movlb instruction and you can use movlb in place of banksel if you divide the file register address in the operand by 128. Example;

Code:
    radix   dec

;   banksel VarA            ; bank 00               |00
    movlb   VarA/128        ; bank 00               |00
    movf    VarA,W          ;                       |00
;   banksel VarB            ; bank 01               |01
    movlb   VarB/128        ; bank 01               |01
    movwf   VarB            ;                       |01
Have fun. Cheerful regards, Mike
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Your example will simply write the contents of VarA back into VarA (on the "enhanced mid-range devices"). Byte-oriented file register operations (like movf and movwf) only include 7 bits of the file register address within their 14 bit opcode.

The banksel pseudo instruction actually generates a movlb instruction and you can use movlb in place of banksel if you divide the file register address in the operand by 128. Example;

Code:
    radix   dec

;   banksel VarA            ; bank 00               |00
    movlb   VarA/128        ; bank 00               |00
    movf    VarA,W          ;                       |00
;   banksel VarB            ; bank 01               |01
    movlb   VarB/128        ; bank 01               |01
    movwf   VarB            ;                       |01
Have fun. Cheerful regards, Mike
Dang it! ... I keep forgetting that this device works using a 14-bit architecture and its limitations ... excellent explanation, MM ... thanks for clarifying.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Quick question.

What would happen if the MCU's interrupt feature is enabled, an interrupt flag is raised and therefore the program immediately branches to the ISR, the code is executed, but the corresponding interrupt flag IS NOT cleared before returning from the servicing routine? ... would the ISR be immediately executed again and again in an endless loop?
 

nsaspook

Joined Aug 27, 2009
13,312
Quick question.

What would happen if the MCU's interrupt feature is enabled, an interrupt flag is raised and therefore the program immediately branches to the ISR, the code is executed, but the corresponding interrupt flag IS NOT cleared before returning from the servicing routine? ... would the ISR be immediately executed again and again in an endless loop?
Yes, if the flag is not cleared (there are times when this is the desired behaviour with an ISR state machine) but some interrupt flags are cleared by actions like reading a USART buffer.

26.1.2.3 Receive Interrupts
The RCIF interrupt flag bit of the PIR1 register is set whenever the EUSART receiver is enabled and there is an unread character in the receive FIFO. The RCIF interrupt flag bit is read-only, it cannot be set or cleared by software
 

nsaspook

Joined Aug 27, 2009
13,312
interesting ... does an example come to mind?
It's for code timing tricks where almost all processing happens in an ISR and/or DMA and main is just a idle loop.

It's likely not very clear what happening here but this code loops high/low priority interrupts using timers and DMA for NTSC scan line generation.
https://raw.githubusercontent.com/nsaspook/vtouch_v2/eadogs/q43_board/q43_ntsc.X/ntsc.c

https://forum.allaboutcircuits.com/threads/pic18-q43-ntsc-b-w-video-signal-demo.175611/post-1586729
The remaining problem is dynamic updates to the video memory. All of the memory bandwidth (something in short supply with the simple DMA architectures seen in most 8-bit controllers) is being used by DMA so excessive processing during DMA will affect H/V timing causing tearing and loss of sync. The fix for that is to only process mainline code during the scanlines with no video around the H sync pulse. For that we need a simple task manager that uses the high/low priority interrupt structure and a 'hold' flag.

Setup a Low priority timer ISR as the 'idle' loop; This idle loop can be interrupted by High priority DMA completion and other module interrupt requests so those time critical processes get the cpu they need during the NTSC FSM. The 'idle' loop can also set a task time duration for the main task that will interrupt the main task back to the low priority idle loop during the critical timing periods. This means I can step into the main application code execution when I want it to run it and control how long I want one processing time slice to be.
 
Top