I'm trying to make sort of a pocket calculator using pic16f84a. Right now i got to the stage of using buttons (ra0 --- ra3) and trying to output to PORTB. Later i will use a display
I want to bit-check every pins ra3, ra2, ra1 in this order so that pressing ra3+ra1 = 5 (an operand for my addition) so i want to rotate right PIN_I with every loop :
basic ideea of the code:
PIN_I equ 0Eh
....
begining movlw 0x04
movwf PIN_I
...
btfsc PORTA, PIN_I ; <<<<<<<<<<<<< compiled and simulated the value of PIN_I doesn't change ; with every loop (in gpsim i get a constant)
rrf PIN_I, 1
btfss STATUS, 0
....
goto begining
the compiler gives me this warning
keyboard_leds.asm:63:Warning [202] Argument out of range. Least significant bits used.
(whitch shouldn't bother me, i think, because PIN_I has values 4, 2 or 1)
full source code is attatched.
Thanks, Andrei
Added after 50 seconds:
i can't upload as attatchment, here is the source code
Non of your code actually shows what chip you are using, but assume it is a 16F type.
When you use ' PIN_I equ 0Eh ' it actually places PIN_I at memory location 0x0E which is normally a system register area. Most 16F user registers start much higher.
If you allocate it as a normal user register, then loading in the value 0x04, the idea of rotating it does work.
cblock 0x40 ; - if using a 16F690
PIN_I
endc
If you use the #include pic16Fxxxx statement then there is no need to define your system registers like TRISA etc - assuming you are using Mplab assembler ?
Edit Correction - should be #include pic16fxxxx.inc
You are misunderstanding, the picture shows what is expected.
It depends on the context you use it in, just imagine for now that whenever you use PIN_I you substitute 0Eh in it's place.
so:
"movwf PIN_I" becomes "movwf 0Eh" which is an instruction that stores the W value in address 0Eh.
and:
"btfsc PORTA, PIN_I" becomes "btfsc PORTA,0eh" which tests bit 0Eh on PORTA.
As PORTA only has bits 0 to 4 and the instruction can only test one bit at a time, it fails. The only numbers allowed in a btfsc instruction are 0 through 7.
The "rrf" instruction you use later is like the movwf one, it expects address as the operand so the contents of address 0Eh are rotated.
Hello everybody, thanks for your posts.
(sorry for neglecting to say that i am using pic16f84a, gpasm assembler and gpsim simulator)
the line "PIN_I equ 0eh" means that the character string "PIN_I" actually means "the number stored at 0Eh location"
after that, i load PIN_I with value 04h or whatever, then
movlw 04h
movwf PIN_I; means that location 0Eh contains the value 04h
(i've seen this in the simulator) and the warning is about the fact that the number 04h is a byte and PORTA is less bits long. It discards the most significant bits, whitch are 0, so i don't care.
To try to make my problem clearer, the standard usage of condition branches is something like
ex: btfsc PORTA, 3 ; this tests bit 3 from PORTA register.
i just want to use a variable instead of "3", so in one loop i have "4", then i'd have "2", "1", when it reaches "0" start again and load the variable with number 4 again.
btfsc PORTA, VAR ; problem is this actually means something like btfsc PORTA, 00000100b (?)
I know from the simulator that my single problem is
btfsc PORTA, PIN_I
if i replace with (for example)
btfsc PORTA, 1
my program works as i want it (i get input from portA and get output to portB)
i just want to test PORTA against a variable number, and i don't know how.
After a bit of help think I can hopefully make things clearer for you.
When you btfss PORTA - it is PORTA that is the instructions File Register and anything following that can only refer to PORTA bits 0 -7 , eg PORTA,2
You cannot use 2 file registers in most instructions.
The EQU statement simply substitutes PIN_I for the number 0Eh.
So when you PORTA, PIN_I it compiles as PORTA,0Eh - which is a totally invalid number.
You are saying that you have put 04h into the file register PIN_I, yes, but translated that means the memory location 0Eh contains 04h , PIN_I still Equates to 0Eh
So afraid , unless anyone can come in with another way, you can only circle around the input pins by addressing them individually - porta,1, porta,2 etc or using EQU as shown in this example.
Code:
KEY_PORT Equ PORTB ;keypad port
KEY_TRIS Equ TRISB
Col1 Equ 0 ;pins used for keypad inputs
Col2 Equ 1
Col3 Equ 2
Col4 Equ 3
btfss KEY_PORT, Col4
goto Press
incf key, f
btfss KEY_PORT, Col3
goto Press
incf key, f
btfss KEY_PORT, Col2
goto Press
incf key, f
btfss KEY_PORT, Col1
goto Press
incf key, f
decfsz rows, f
goto Scan
will set or reset the Z flag in the STATUS register depending on whether the bit in PIN_I and the same bit in PORTA are the same. You still have to put a valid bit mask in PIN_I rather than the actual bit number though.
you've all been very helpfull, Brian's solution is the what i have been looking for. I don't really know how to put that in to code yet, but if i have my varibale PIN_I from 04h to 01h, and substract if from PORTA, at some point i will have Z set. This has to work, i haven't coded it and tested it yet.... maybe that's just the same thing... Anyway, it's like solved.
About btfsc: (From PICmicro mid-range MCU family reference manual)
BTFSC Bit Test, Skip if Clear
[ label ] BTFSC f,b
Syntax:
0 ≤ f ≤ 127
Operands:
0≤b≤7
Operation: skip if (f) = 0
Status Affected: None
Encoding: 01 10bb bfff ffff
Description: If bit 'b' in register 'f' is '0' then the next instruction is skipped.
If bit 'b' is '0' then the next instruction (fetched during the current instruction execu-
tion) is discarded, and a NOP is executed instead, making this a 2 cycle instruction.
So, btfsc and btfss can use only a 3 bit number (as b) ! I tried setting PIN_I to EEh to see if it truncates most significant bits -- it doesn't. it simply can't handle anything else than 3 bits.
PS: i use gpasm because mplab doesn't run on linux. And i'm trying to learn linux also.