Microcontroller Architecture - Part 3 Simple Microcontroller (PIC10F200)
Hi again and welcome back! In this PIC microcontroller tutorial, I will provide more detailed information about the PIC10F200 microcontroller so you understand exactly what we’re doing and why. The datasheet for this microcontroller is found here: PIC10F200/202/204/206 Data Sheet
This datasheet is extremely helpful and I strongly encourage you to become at least somewhat familiar with it. The biggest challenge is that it’s big, complicated, and confusing. I’ll go over some of the most important things but if there are questions that I don’t answer in this tutorial, the data sheet is where to find it.
PIC10F200 - High Level Features
In the first microcontroller tutorial, I mentioned some characteristics, like the flash memory volume which is 256 words, and the number of supported instructions, which is 33.
If you are attentive you might notice that I said the ATMega328P has 32 kbytes, while the PIC10F200 has 256 words. Why? The reason is that PIC microcontrollers have a constant instruction length, which is 12 bits for PIC10 family, or a total of twelve 1’s and 0’s. What does this mean? It means that all 33 instructions use the same volume of flash memory – 12 bits. And these 12 bits are called words in the world of PIC microcontrollers. So the real capacity of the PIC10F200 microcontroller is 256 x 12 / 8 = 384 bytes, but this value doesn’t tell us anything - we want to know how many instructions we can write, and from this perspective, knowing how many words you have is much more informative. Unlike PICs, other microcontrollers such as the ATMega328P have variable instruction length which can be from 1 to 4 bytes in length.
8 bits = 1 byte
PIC10F200 uses an internally calibrated oscillator with 4 MHz frequency, meaning it oscillates back and forth 4,000,000 times a second. As the execution of each command requires 4 clock “ticks”, the real productivity is “just” 1,000,000 instructions per second.
The Watchdog Timer (WDT) is a free running on-chip oscillator which runs separately from the main clock. This means that the WDT will still run even if the main processor clock will stop. When the counter of the WDT reaches the time-out value, the WDT generates an interrupt or a system reset.
The PIC10F200 has some peripheral devices from which we might be using an 8-bit real-time clock or counter, and watch-dog timer. As PIC10F200 doesn’t support interrupts (yeah, no interrupts at all - this is a *very* simple microcontroller) the value of the timer is doubtful; maybe it’s useful as a counter though.
An interrupt is a method that causes the processor to jump and execute an interrupt service routine (ISR) whenever an external or internal interrupt source occurs.
General Purpose Input/Output pins are frequently referred to as GPIO’s - these can be setup to act as either an input or as an output.
PIC10F200 has 3 general purpose input/output pins, and one input-only pin. Not many but it’s enough for the applications I mentioned in the introduction tutorial.
Let’s now consider the pinout of the PIC10F200 in different packages. As mentioned in a previous tutorial, there is an 8 pin microcontroller option with the DIP and DFN packages and there is a 6 pin microcontroller option with a SOT23 package:
You can read the full pin description in Table 3-2 of the data sheet. I will mention just the most important pins:
- VDD – positive supply which is 2.0V to 5.5V
- VSS – negative supply, ground pin
- GP0, GP1, GP2 – general purpose input/output pins
- GP3 – general purpose input pin
- MCLR, ICSPCLK, ICSPDAT – pins used for programming the microcontroller.
These may look like random letters, but they all stand for very specific things. In this case, we have:
MCLR - Master CLeaR (Master Clear Pin External Reset)
ICSPCLK - In Circuit Serial Programming CLocK (the clock that your programmer uses for microcontroller programming)
ICSPDAT - In Circuit Serial Programming DATa (the data line for microcontroller programming)
I will skip most of the internal structure of the microcontroller, as it is quite involved and would require a separate tutorial. Also, you can easily find it in the data sheet. For now, let’s imagine that the microcontroller is the black box which consists of the processor, flash memory and RAM, some peripheral units, and a set of buses that connect all these units.
Buses are communication systems, usually a dedicated set of communication lines.
We will, however, discuss the memory organization, as we will use the memory and thus need to understand how it works.
The program memory organization is shown in Figure 1.
As you can see, the User Memory Space consists of 256 words that are located at addresses from 0000h to 00FFh.
If there's an 'h' at the end of a number, it means that number is hexadecimal.
The first address in the User Memory Space is the Reset Vector, which is the address from which execution of the program starts after the reset of the microcontroller. As you can see, the program starts from the lowest address 0000h.
At the very top of the memory spaces, you can see something called PC. This is the “Program Counter”. It is a special register which contains the address of the next instruction to execute. For instance, after the microcontroller resets, the PC contains 0000h, which means that the instruction that is written in the cell under address 0000h will be executed. After this instruction is done, the PC is incremented and has the value 0001h, which means that the instruction under address 0001h is about to execute, and so on and so forth. But the flow of the execution can be manually changed by a “branch” instruction, something we will learn about very soon.
A register is a memory cell which might have specific name and perform the specific role, like the PC. It can be general purpose though, thus not named, just an address.
The last thing you can see in the memory is the “stack”, which is 2 levels in a PIC10F200. So, what is the stack and what is it used for? The stack is used to store the PC during execution of the subroutines. When you call a subroutine, the current PC value is stored in the stack, so that the program remembers where it was before jumping into the subroutine. Then the PC is loaded with the address where the subroutine is located. After execution of the subroutine is done, the old PC value is restored from the stack, and the execution of the code continues from the address after the subroutine call. As the stack is 2-level, this means that you can call a subroutine from within another subroutine if needed but only one nesting is allowed. Remember this or your program will break! This is where the term "stack overflow" comes from.
Next, we will discuss the data memory organization. This data memory contains the data which is lost when you power down the microcontroller. Program memory, what we just discussed, stays with the microcontroller all the time but data memory is the temporary memory that is used by the program and includes things like variables. Its organization is shown in Figure 2.
You can see that data memory spans addresses from 00h to 1Fh. But you should remember that these addresses are different from the addresses of the program memory, they are totally different memory spaces.
Memory that is erased when power is lost is called volatile memory and memory that is NOT erased when power is lost is called non-volatile memory.
Special Function Registers (SFR)
You may notice that addresses from 00h to 07h have special names. These are so-called special function registers (SFR) and are used to configure the microcontroller. We need to consider them a little more in-depth as we will use them directly and quite often. The SFRs allow us to control the processor or the peripheral states and to check the status of operation. By programming these registers you make the microcontroller do what you need.
The summary of the SFR is listed in table 4-1 of the data sheet, but I will put it here as it is very important.
You don’t need to know all of them right now but I will briefly explain the most important and widely used registers.
- Registers INDF (00h) and FSR (04h) are used for indirect addressing; we will consider them later, for now it’s too difficult to explain and not that important for what we’re doing.
- Register TMR0 (01h) contains the current value of the 8-bit timer/counter. Again, as there are no interrupts, its usage is more limited than with other microcontrollers but can still be used for counting and timing.
- Register PCL (02h) consists of the lower 8 bits of the PC. As we will not load a value into it directly, you can just take note of it for later usage and not worry about it now.
- The STATUS (03h) register is very important; it consists of the bits that indicate the state of the arithmetic and logic unit (ALU) of the processor, and the reset status. For now we will need just two of the bits – Z and C.
- Bit Z indicates that the result of the previous operation was 0.
- Bit C indicates that the carry or borrow event occurred during the previous addition or subtraction operations correspondingly.
Again, for now just keep this in mind; I will explain them when we see them in the code.
- Register OSSCAL (05h) allows you to adjust the frequency of the internal clock generator. We will not do this, so don’t worry about it.
- Register GPIO (06h) is the one that we will use the most often. It allows you to directly control the inputs/outputs of the microcontroller. By writing 1 into a certain bit (GP2, GP1, GP0) we can set the corresponding output pin to the high voltage level. Writing 0 into these bits, we set the output pin to the low voltage level. For those attentive readers who want to ask why I didn’t mention the GP3 bit, I want to remind that GP3 is an input only pin and you can’t change its state via code. Also, by reading the bit of this register we can find out the physical state of the corresponding pin. This action can be applied to all four pins regardless of whether the pin is an input or output.
- Register CMCOM0 (07h) is not used for the PIC10F200 microcontroller.
- Register TRISGPIO is another frequently used register. This is how you change the input/output pin direction. If the bit of this register is 0 then the corresponding pin acts as an output, if the bit is 1 then the pin acts as an input. By default, after powering up, this register is all “1”s, and thus all pins act as inputs.
- Register OPTION is so you can enable pull-up resistors on some pins, control the 8-bit timer/counter, as well as some other functions. I will not consider them here, and will explain certain bits when we meet them in the code.
That’s about it for the SFR, or Special Function Registers. Again, these special function registers are a subset of the data memory and they can be changed to affect the operation of the microcontroller.
As you can see from Figure 2, addresses from 08h to 0Fh are unimplemented, that they are always read as 0, and thus there is no sense to use them. We can just ignore them.
Addresses 10h – 1Fh contain the “general purpose” registers, this is actually the RAM of the microcontroller. You can use these registers to store your variables. It’s not difficult to calculate that there are only 16 general purpose registers, which means that the available RAM volume is just 16 bytes. Note that I used the word “byte”, because the length of the registers is 8 bits not 12 - unlike the words for instructions.
And that’s it! I realize that there is a lot of information which can be hard to understand now, but when you start writing your own program you will see that it’s quite clear and logical. I highly recommend coming back to this tutorial a few times after you’ve done a few practical examples. But for now, your homework before the next tutorial will be to recall, or learn about number systems, Boolean logic, and logic operations. The next time we will consider the basics of the Assembly language for the PIC microcontrollers. We’re almost to the first practical example - let's move on to the next microcontroller tutorial!
Get the latest tools and tutorials, fresh from the toaster.