Learning to program the PIC16LF1823

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
It has to do with the 14-bit core that can only accommodate so much addressing in an instruction. There are 31 banks (2^5-1). Many of the higher numbered banks are virtually vacant, but as peripherals get added, those banks get filled with SPF registers. Look at the 16F18856 and similar newer chips. Bank19 or maybe even higher have SPF registers.
So they're there (at least in th 16LF1823) for compatibility purposes, regardless of their being useless?
 

OBW0549

Joined Mar 2, 2015
3,566
So they're there (at least in th 16LF1823) for compatibility purposes, regardless of their being useless?
More likely, the various PICs within a given family all use the same (or very similar) CPU core and address-generation mechanism, and each individual PIC populates the address space differently according to the particular peripherals it's endowed with. Some use more addresses/banks, while others use fewer.
 

jpanhalt

Joined Jan 18, 2008
11,087
cmartinez said:
So they're there (at least in th 16LF1823) for compatibility purposes, regardless of their being useless?
I suspect so but really am not very knowledgeable about the evolution. If you go way back and look at the 12-bit core devices (e.g., 12F509) there was only one Bank, no interrupts, and limited peripherals. Early 14-bit core devices with interrupts had 4 banks that were switched by bits 5 and 6 in the STATUS register (RP0 and RP1) and more peripherals. Newer devices like you are using have banksel/movlb and the top 3 bits of STATUS are null. They have a large selection of peripherals. For bank switching, each series seems unique.

There is some backward compatibility that is evident in the instruction sets that build on one another. Code for a 12F509 might easily be adapted to a 12F1840, but not the other way around. For example, the 12F509 does not have an addlw, but the later devices do. So, you would need 4 instructions to addlw with the 12F509 (movwf regA, movlw, addwf regA, movf regA,w).

I used to be stuck at the 12F509 and 12F683 (14-bit core) level. Except for repairs or inability to get the enhanced mid-range or later chips, I see no reason to ever use those chips again. Unfortunately, going from 8-bit to 16 bit (24F chips) is quite a jump. I bought some 24F chips, but every time I look at doing Assembly with them, I decide I can do it with an 8-bit chip and not kill any cells in my shrinking brain.
 

OBW0549

Joined Mar 2, 2015
3,566
Yes, going from the 8-bit PICs to the 16-bit (dsPIC30F and dsPIC33EP, in my case) was quite a jump, and somewhat intimidating; but I've found that once "over the hump," they're actually easier to work with in assembly language than the 8-bit devices.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Some of my reasons for liking the 16-bit PICs are listed in this post from 4 years ago.

Also, in the context of our discussion here, with the 16-bit PICs you can say bye-bye to banking and paging. Not needed.
Yeah ... I remember that discussion now... it's been ages for me... knowing what I know now compared to what I thought I knew back then. Other than the almost mandatory whatsapp app, this is the only "social network" (if AAC can be called that) in which I hang out. I have no facebook, no instagram... nothing else whatsoever. It's discussions like this one (and at the off topic section, of course) with people of similar interests that makes this place my personal intellectual refuge.
 

OBW0549

Joined Mar 2, 2015
3,566
Other than the almost mandatory whatsapp app, this is the only "social network" (if AAC can be called that) in which I hang out. I have no facebook, no instagram... nothing else whatsoever.
I don't participate in any of that "social media" crap, either. Even so, I don't consider AAC my "home" for anything but electronics. I've got another "home" for political discussions, and yet another one for firearms talk. But here, it's just electronics (and the occasional OT topic).
 

jpanhalt

Joined Jan 18, 2008
11,087
... a few hours ago I figured that banksel is not really an instruction but rather a macro that generates a movlb instruction accordingly.
I do not know whether MPLABX has as complete description of the Assembler as DS33014L has. I suspect it does, but in case not, here's a link: http://ww1.microchip.com/downloads/en/DeviceDoc/33014L.pdf

Somewhere around page 320 is a list of other Assembler macros.* Some are quite useful, such as the "skip" and "branch" macros (skpnc,skpc,skpnz,skpz, bc,bnc), which translate to skip on no carry, skip on carry, etc. Many longtime coders use them. I do not and mention that source just in case you come across them.

*Appendix A: 12-bit/14-bit ...Pseudo Instructions
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
It's no mystery that, MCUs-wise, the only chip that I'm truly experienced with (but have in no way completely mastered) is the 8051, specifically the AT89LP family.

Anyway, said family of chips is quite versatile, but when it comes to working power, they're still in the stone age compared to most PICs.

So my programming skills regarding the latter devices are still a work in progress. IE, last week I discovered that the only way to copy a single bit in a register (or file, as the PIC assembly manual likes to call them) is to assume a given value for the destination bit (say, we start by clearing said bit), and then test the contents of the source bit, and then setting the destination bit or leaving it as is depending on the result.

The previous procedure takes three instructions in PIC assembly. It's kind of strange, but it does the job just as efficiently as the 8051, in which one has to copy the contents of the source bit into the C (Carry) bit, and then copy them again from C into the destination bit. And although it's only two instructions, each of them takes two clock cycles to perform. So the number of cycles executed in both MCU's is practically the same.

Anyway, what I can't seem to wrap my head around is, what's the best way to save a source routine's context when calling another routine? In the 8051 architecture such thing is quite simple. All one has to do is PUSH the desired register into the stack when entering the latter routine, and then POP it back into place just before returning.

But I'm seeing that is not so in the PIC12 architecture ... so the question is, what's the best coding practice in order to save a routine's context?
 

jpanhalt

Joined Jan 18, 2008
11,087
IE, last week I discovered that the only way to copy a single bit in a register (or file, as the PIC assembly manual likes to call them) is to assume a given value for the destination bit (say, we start by clearing said bit), and then test the contents of the source bit, and then setting the destination bit or leaving it as is depending on the result.
Setting single bits on the Y-axis comes up often with graphical displays (GLCD). I only know three ways to do it with 8-bit PICS:
1) BSF/BCF bit number (not very useful), and you have to convert bit number to value or visa versa.
2) Use a table
3) Rotations

Although a table is the fastest compared to rotations, assume you want to set 2 adjacent bits. In that case rotations are my preferred method.

As an example, let's say you are plotting a variable like temperature, and a change of 1° = 1 pixel is no big deal. But lets say when the change is 2 or 3 degrees or more, that equals the same number of pixels vertically. You want to print the whole column , and that may very well involve more that one page. I think that approach looks better. It could be done with tables and be very fast, but tables use lots of program memory. In that case, I have opted for rotations and include the "target page" plus a page above or below depending on the direction of change. Of course, that limits me to a maximum of 16 degrees change, but that has not been an issue. If it were, that issue could be addressed by adding more pages to the rotation.

On the X-axis, such considerations have never been a problem.

EDIT: I should also add that dealing with a GLCD that you can read changes the problem. The GLCD I am using has SPI interface and cannot be read.
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Ok, here's another question. What's the best way for the PIC16LF1823 to measure the voltage (and hence life expectancy) of a battery powering it?

Intuition tells me it should go something like this.

1590529021333.png

  • The reason there's two power sources is because the PIC is working at 3.3V being delivered from a regulator, whilst the main power source are four AAA batteries in series.
  • The voltage divider would be comprised of high accuracy resistors, and is there to prevent over voltage from being delivered to the MCU's pin in a worst case scenario.
  • The nFet is there so that the circuit won't waste precious power until a sample is needed.

Makes sense?
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Yup.

Only one problem: with M1 turned off, current will still flow down through R1 into the PIC ADC input pin, where it will forward-bias the pin's upper ESD clamp diode.
What if I place a 100k pull down resistor at the fet's gate, and then config both mcu's pins as high-z inputs when unused?
 

OBW0549

Joined Mar 2, 2015
3,566
What if I place a 100k pull down resistor at the fet's gate, and then config both mcu's pins as high-z inputs when unused?
Doesn't make any difference. Current will still flow from the +6V battery through R1 into the upper ESD protection diode of the PIC's ADC input.

If you want to prevent that, you need a high-side switch between the battery and your voltage divider, not a low-side switch between the divider and ground.
 
Top