ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 14.06.2025

Просмотров: 488

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

You cannot have two labels with the same name either. That confuses the assembler because it does not know which particular label you are referring to and this also generates an error.

Don’t get too worried about error messages. They are simply there to help you find problems with the way you wrote your code.

You will also receive warning messages at times. These are generated to tell you that you may be doing something wrong, like forgetting to set a page bit.

Warning [205]: Ensure page bits are set.

If you are certain that your code is correct, you can ignore them. We will talk about page bits later.

start

movlw 0x04

;

simple code

movwf 0x06

goto start

;

do this loop forever

Code that is written like this is called a loop. That is because the code executes until the goto start instruction forces the processor to begin at the start label again. This particular code will loop forever or until you remove power from the chip. Your code will always have some sort of loop even if you did not create one.

How is this so I hear you ask. Well, if you only write this code line...

start

movlw 0x04

; simple code

...what happens after it is executed. The PIC doesn’t stop just because you didn’t write anything else. It will happily increment to the next code address and execute whatever is there - in this case nothing.

As a matter of fact nothing will be programmed into the rest of the ROM space either. They will all be blank and these will have the value0x3FFF in them.

The PIC processor actually decodes 0x3FFF as ADDLW 0xFF. This means to add the value 0xFF to the W register, or ADD Literal to W. So even though you only wrote one code line the PIC will execute ADDLW 0xFF 1023 times and then the program counter will wrap around back to 0x0000 and execute your code line again.

So what exactly does this small piece of code do?

start

movlw 0x04

;

simple code

movwf 0x06

goto start

;

do this loop forever

DIY K81 Project - Page 17

Remember our LED flash problem?

The LED was connected to pin RB2 which is PORTB pin 2.

If we had to turn the LED on we have to write a Logic 1 to this pin. Remember that once we have done this, 5 volts will appear on the pin if it is set as an output.

What value should we write to PORTB if we want to set only pin RB2 to Logic 1?

Here is a small sample of a binary table.

Decimal Binary

000000000

100000001

200000010

4

00000100

16

00010000

47

00101111

If we consider that pin RB2 is represented by bit 2 in this table we can see that we need to write decimal value 4. Bit 0 is the far right binary bit, bit 7 is the far left.

Another thing you must consider here, is that we can do this because nothing else is connected to PORTB If other devices were connected to the other PORTB pins, we need to be more specific about the value we write to PORTB so that we do not upset their operation.

In our case, to turn the LED on, we can write the value 0x04 to PORTB, and to turn the LED off we can write 0x00 to PORTB. So just how do we do this? If you look at the original code, this is the first line.

start movlw 0x04 ; simple code

First we have a label called start, followed by the instruction movlw 0x04.

movlw means to move a literal value into the W register. A literal value is any value that can fit into 8 bits. Remembering that the PIC is an 8 bit device, this means a literal value can be any value from 0 to 255, (0x00 to 0xFF). In this case it is the value 4, or 0x04. This instruction can also be written as

movlw b’00000100’

; binary notation

movlw d’4’

; decimal notation

movlw 4h

; another type of hex notation.

movlw

04h

;

another

type

of hex notation.

movlw

0x04

;

another

type

of hex notation.

Binary notation is quite good for writing to the ports because any bits in the value that are 1 means the corresponding output port pin will be at 5 volts, and any that are 0 will be at 0 volts.

DIY K81 Project - Page 18


The exception is pin RA4 which is at a high impedance state when it is at Logic 1 because it is an Open Collector output.

Looking back at the code, the next line is

movwf 0x06

movwf means to move the contents of the W register to the file register specified. In this case it is RAM address 0x06.

If you look at the 16F84A data sheet, and most other PICs for that matter, you will see that RAM address 6 is PORTB. So in other words, this instruction moves the contents of W to PORTB.

This seems a lot of effort. Why can’t we just write 1 toPORTB? Unfortunately the PIC does not function like that. You cannot directly write any 8 bit values to any RAM locations. You have to use the W register to do the transfer. That is why it is called the W or Working Register.

Mnemonics

This is a funny looking word. You pronounce it

Nem On Icks.

These items are quite a powerful concept in programming because they provide an interface between us mere mortals and computers. It can become very confusing to write software if we have to refer to RAM addresses and data values by their binary numbers. Mnemonics makes it a lot easier for us to understand what we are writing by allowing us to assign names and labels to instructions, RAM locations and data values.

As an example, what do you think this means?

0000100000000011

Any ideas?

What about this?

0803h

DIY K81 Project - Page 19

Try this.

movf 03h, 0

Lets change it to something we can understand using mnemonics.

movf STATUS, W

That’s a little easier to understand don’t you think. It is exactly the same thing as the original binary number except the first way the computer understands, the second and third ways we may understand, but the fourth way is quite easy to understand.

It means...

Move the contents of file register [Status] into W.

It’s all too easy. Of course we still need to understand whatMOVF, STATUS and W mean, but that will come soon.

The assembler is used to generate code that the PIC can understand by translating these mnemonics into binary values and store them as a hex data file ready for a programmer to use. The standard assembler for a PIC is called MPASMwin. This is a free program and is available from the Microchip web site.

Labels

We mentioned the use of labels before. With an assembler, we have the luxury of being able to create our own label names and we can use these to define things like general RAM addresses, special RAM locations, port pins and more.

As an example of this concept we can change our original code...

start

movlw

0x04

; simple code

movwf

0x06

into this...

start

movlw

TurnOnLED

; simple code

movwf

PORTB

By writing your code in this way, you can just about comprehend the meaning of these two code lines.

Get a value and write it to PORTB to turn on a LED.

DIY K81 Project - Page 20


Now this is all very fine except for one thing. How does the assembler know the meaning of the labels TurnOnLED and PORTB?

The assembler has the inbuilt ability to understand all of the PIC instructions like movlw, and it also knows what labels are generally, but you, as the programmer, have to tell the assembler the meaning of any labels thatyou create.

To do this you use the equ assembler directive. This tells the assembler that the label on the left of the equ directive has the value on the right side.

TurnOnLed

equ

0x04

;

value

to turn

on LED with RB2

PORTB

equ

0x06

;

PORTB

address

You should note something here, and that is the first equate assigns a value to a label that will be used as a literal, and the second equate assigns a value to a label that will be used as a RAM address. These values are quite interchangeable by the way because the labels just represent simple numerical values.

For example...

start

movlw PORTA

;

simple code

movwf TurnOnLED

goto start

;

do this loop forever

This new piece of code is quite valid and still makes sense to the assembler, however when the PIC executes this code it will now get the literal value 0x06 and place it in W, and then it will get this value from W and place it into RAM address 0x04. The assembler does not care what we write because its only concern is that it can successfully assemble this code.

Now that we know about labels, this is how we can rewrite the original code listing and make it more readable

Title "Simple Program"

list p=16F84A

; processor type

;

;-------------

;PROGRAM START

;-------------

TurnOnLed equ 0x04 ; value to turn on LED with RB2

PORTB

equ 0x06

; PORTB address

org 0h

; startup address = 0000

start

movlw TurnOnLed

; simple code

movwf PORTB

goto start

; do this loop forever

end

DIY K81 Project - Page 21


Quite simple isn’t it.

One thing to note is that label names must start in the first column on a separate line, you cannot have spaces or TABs before them.

Now each time the assembler comes across a label called TurnOnLED it will substitute it for the value 0x04.

When it comes across a label calledPORTB it will substitute it for the value 0x06.

The assembler does not care in the least what these labels mean, they are there just to make it easier for us to read our code. Lets have a quick look at how the assembler turns the source code into a hex file.

When the assembler begins working, it creates a symbol table which lists all the labels you created and then links the values you associated with them.

TurnOnLed

equ

0x04

;

value

to turn

on LED with RB2

PORTB

equ

0x06

;

PortB

address

The assembler generates a symbol table that will look like this.

SYMBOL TABLE

LABEL

VALUE

PORTB

00000006

TurnOnLed

00000004

The assembler also has a ROM address counter which is incremented by 1 each time it assembles a line of code with an instruction in it.

This next line is an assembler directive and it tells the assembler to set this counter to ROM address 0h.

org 0h

; startup address = 0000

The next code line has an address label attached to it so the assembler also adds this to its symbol table. At this stage the ROM address counter equals 0 so the start label gets the value 0.

start movlw TurnOnLed ; simple code

The symbol table will look like this.

SYMBOL TABLE

LABEL

VALUE

PORTB

00000006

TurnOnLed

00000004

start

00000000

DIY K81 Project - Page 22

Next on this code line is movlw. If you look in the PIC data book, the MOVLW instruction has a binary number associated with it.

Remember about computers only understanding 1’s and 0’s. This is also how the

PIC understands instructions.

MOVLW in binary = 11 00XX kkkk kkkk

We need to decipher this instruction a bit.

The 1100XX is the part of the instruction that tells the processor that it is a

MOVLW instruction. The ‘XX’ part means that it doesn’t matter what value these two bits are. They can be either 1’s or 0’s and the PIC will still decode the instruction as MOVLW. The kkkk kkkk represents the 8 bits of data and will be the actual literal value.

Now knowing what the actual instruction is, the assembler will look up its symbol table and find the label called TurnOnLED and return with its value of 4. It will then insert this information into the MOVLW instruction data.

Therefore the complete instruction becomes 11 0000 0000 0100 which is 3004h.

Notice there are 14 bits for the instruction, and that the instruction itself is represented with the literal data combined. In this way each PIC instruction only occupies 1 single ROM address in the chip. Therefore the 16F84A with 1K of ROM space, can store 1024 instructions in total.

The assembler is now finished with this code line because it does not care about the comment, so it increments it’s address counter by 1 and continues with the next line.

movwf PORTB

MOVWF = 00 0000 1fff ffff

00 0000 1 are the bits that define the MOVWF instruction and fff ffff are the bits that define the RAM address where the W register contents will end up. The assembler looks up PORTB in it’s symbol table and returns with its value of 6.

Therefore the complete instruction becomes 00 0000 1000 0110 which is 0086h.

This is the next line.

goto start

; do this loop forever

DIY K81 Project - Page 23