Explanation of PIC 16F84A processor data sheet Part 2: More on the PIC This is the second of the three part overview of the PIC processor. We will first discuss the timer module and prescalar. We will also review the hexadecimal representation. Then we will cover memory and IO. Timer Module and Prescalar Many applications of the PIC require that the processor fulfill timing requirements. For example, in the Blinking LED 2 example, the program required a 1 second delay function. This function was implemented by having it call another function, which had a 1ms delay. The millisecond delay function was written so that it uses approximately 1000 clock cycles. The problem with this approach is that the programmer must carefully count the number of machine instructions. An alternative approach is to use a timer circuit which indicates how much time has elapsed. The PIC has such a circuit called TIMER0. It is an 8 bit timer/counter, and in many cases can be accessed like a variable. It can be configured so that it will increment every clock cycle. Next is a naive example implementation of using TIMER0. It is a delay function for a 100 us delay. It just checks when TIMER0 has reached the value 100. void delaynaive( ) // A delay of (approximately) 100 clock cycles { TIMER0 = 0; while (TIMER0 < 100); } This will not work because we have not configured TIMER0 before accessing it. We will discuss the configuration process a bit later but for now let us discuss how to make this delay longer. Note that TIMER0 is limited by its size, which is 8 bits. If we want a longer delay, we must use the prescalar. The prescaler slows TIMER0 down by reducing the clock signal rate to TIMER0. The options of rates are 1:2, 1:4, 1:8,..., or 1:256. Note that the step down values are all powers of two. The next delay function delaynaive2 has a delay of approximately 10,000 clock cycles. First, we configure the prescalar to 1:256. Thus, the timer will increment every 256 clock cycles. The function will terminate when TIMER0 = 40, i.e., after 40 x 256 = 10,240 clock cycles. Thus, delaynaive2 has a delay of approximately 10,000 clock cycles. void delaynaive2( ) // A delay of (approximately) 10000 clock cycles { TIMER0 = 0; // Configuring the step down rate of the TIMER0 to 1:256. // Now we set the OPTION_REG so that TOCS, TOSE, PSA, and PS2-PS1 are 0. OPTION_REG = 0b00000111; while (TIMER0 < 40); } 1
The line OPTION_REG = 0b00000111 is the configuration of TIMER0. (Section 5 of the PIC processor datasheet describes the TIMER0 module and how to configure it.) The module has two modes: Timer or Counter Mode. We want Timer Mode which uses the PIC s own clock signal for synchronization. (Counter Mode uses an external clock signal.) The TIMER0 module is configured by setting the bits of the 8 bit register OPTION_REG, which is shown in Figure 1. The register has bits TOCS (bit 5): TOCS determines if TIMER0 is in Timer or Counter Mode, where TOCS = 0 means Timer Mode. PSA (bit 3): The prescalar can be assigned to TIMER0 or the watch dog timer. Clearing PSA to 0 will assign the prescalar to TIMER0. PSA = 1 assigns TIMER0 to the watch dog timer. We want PSA = 0 for our delay function. PS2 PS0 (bits 2 0): Determines the step down rate of the prescalar. PS2 PS0 = 111 means 1:256, while PS2 PS0 = 000 means 1:2. Figure 1. Table 5 1 from the data sheet for the PIC. The other bits of OPTION_REG are irrelevant for our purposes. (For example, TOSE (bit 4) is used when TIMER0 is in Counter Mode, but we use Timer Mode.) Whenever TIMER0 is written to by a machine instruction (e.g., CLRF) then the prescalar is cleared to 000. This is why we set OPTION_REG after clearing TIMER0. The function delaynaive2 may not work. The OPTION_REG = 0b00000111 will set the prescalar by having PS2 PS0 to 111, and it sets the bits TOCS and PSA to 0. But it also clears bits 7 and 6 of OPTION_REG. The next implementation will set bits 0 5 of OPTION_REG without changing bits 7 and 6. void delaynaive3( ) // A delay of (approximately) 10000 clock cycles { unsigned n; TIMER0 = 0; // Initialize TIMER0. This clears the prescalar. // Now we set the OPTION_REG so that TOCS, TOSE, and PSA are 0, and set // the prescalar to 256:1. The prefix 0b means the number is binary n = OPTION_REG & 0b11000111; // Clear TOCS, TOSE, and PSA n = n 0b00000111; // Set prescalar to 256:1 OPTION_REG = n; while (TIMER0 < 40); } 2
The operation n = OPTION_REG & 0b11000111 is a bit wise AND operation with the bit string 11000111, which is the mask. The mask will clear bits 3, 4, and 5 to 0. These are the TOCS, TOSE, and PSA bits. The next line n = n 0b00000111 is a bit wise ORing the variable n with the bit string 00000111, which is another mask. This sets bits 2 0 to the value 111, which in turn will set the prescaler to 256:1. Then the instruction OPTION_REG = n properly sets OPTION_REG. Figure 2 shows the schematic diagram of the TIMER0 module and prescalar. CLOCKOUT is the internal clock of the PIC. Notice how it is routed through two multiplexers, then the prescalar (which is an 8 bit counter), and the prescalar s output is then routed to the TIMER0 register. Note that the 8:1 multiplexer selects a bit out of the prescalar s output. Also notice how the PSA and TOCS bits are used to route the signals through the 2:1 multiplexers, and the PS2 PS0 bits are used to control the 8:1 multiplexer. Figure 2. TIMER0 and prescaler circuitry. This comes from Figure 5 2 of the datasheet of the PIC. Timer Module and Prescalar Next we will go over memory in the PIC architecture. Figure 3 has a block diagram of the PIC. The Program Memory in the upper left corner is flash technology which can store 1024 instruction words. Recall that C language will compile to a longer machine program. So the PIC may be limited to just a couple hundred C instruction lines. 3
Attached to the Program Memory is the Instruction Register. This has the current instruction that is being executed. Program Counter, which is a counter circuit that points to the next instruction to be executed. In the middle of the figure is the Arithmetic Logic Unit (ALU). The ALU is the calculator for the CPU. It does much of the arithmetic and the bit wise logic operations such as AND and OR. Notice that the output of the ALU is a register W. This register can be accessed by certain machine instructions. The lower right in Figure 3 has the TIMER0 and IO ports. The upper middle of the block diagram has the RAM memory. Figure 4 shows the register map of the PIC. These registers include TIMER0, PORTA, TRISA, and OPTION_REG. It also includes general purpose registers. These general purpose registers are stored in RAM. Note that the registers have numbers assigned to them for identification. For example, register TIMER0 has the number 01h. These numbers are called register numbers, addresses, or indices. The suffix h indicates that the number is in hexadecimal representation, which is discussed below. In decimal representation, 01h is plain old 1. Hexadecimal Number Representation Hexadecimal representation is similar to binary or decimal representation, so let us discuss these first. Decimal representation of a value is a string of digits. For example, 423 is a three digit representation of the value four hundred twenty three. The base of decimal representation is the value 10. The representation 423 is a representation the formula 2 1 0 4 10 + 2 10 + 3 10. Notice that the digits are coefficients of powers of 10, which is the base. Each digit is a value ranging from 0 to 9 (10 possible values). Binary is similar except that the base is 2. The digits are called binary digits or bits. Each digit is a value ranging from 0 to 1 (2 possible values), and are coefficients of powers of 2, which is the base. Hexadecimal is another representation where the base is 16. Each digit is a value ranging from 0 to 15 (16 possible values). These digits are represented by the symbols: 0, 1, 2,... 9, A, B,..., F. Here, A represents the value 10, F represents the value 15, etc. Thus, the address 0Bh is hexadecimal for the value 11, and 82h is hexadecimal for the 1 0 value 8 16 + 2 10 = 130. Hexadecimal is used because it is a convenient way to represent binary numbers. To convert a binary number to hexadecimal, you must break up the bit string into chunks of 4 bits starting from the right. For example, the binary number 1001001111001101 is broken up into 1001 0011 1100 1101. Each chunk of 4 bits can be converted into a hexadecimal digit: 1001(=9) 0011(=3) 1100(=C) 1101(=D). The hexadecimal representation is 93CDh. This is much shorter and easier to recognize than the original bit string. To convert a hexadecimal number to binary, just convert each hexadecimal digit to its equivalent 4 bit binary representation. For the PIC, hexadecimal numbers are denoted by the suffix h. However, there are other ways to indicate hexadecimal. For example, the prefix 0x indicates hexadecimal, which we will use in lectures and homework. 4
Figure 3. Block diagram of the PIC. This is from Figure 1 1 in the datasheet for the PIC. 5
Figure 4. Register map. This is from Figure 2 2 of the data sheets. 6
Instruction Processing Cycle Like all computers, the PIC follows an instruction processing cycle, sometimes known as the Von Neumann processing cycle (named after a famous mathematician and computer scientist John Von Neumann). This cycle is basically what computers do continually. Figure 5 shows this cycle. It is a loop of: 1. Fetch instruction (from program memory). 2. Decode instruction (so that the CPU understands the instruction and what s to be done). 3. Execute instruction. Figure 6 has the portion of the block diagram of the PIC that is involved with fetch, decode, and execute instruction. To fetch the instruction, the CPU will use the Program Counter, which points to the next instruction to execute. This instruction is stored in Instruction Register. The output of the Instruction Register is connected to the circuitry called Instruction Decode and Control. This circuitry will first decode the instruction so that the CPU understands what the instruction is. Then given what the instruction is, the CPU will send control signals to the datapath of the computer to execute the instruction (note that the control lines are not shown, probably because it would make the diagram very messy to look at). Instruction Fetch Instruction Decode Instruction Execute Figure 5. Instruction Processing Cycle Figure 6. Portion of the PIC that has instruction fetch and decode. 7