![]() | ![]() | ![]() |
| | |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
| | Thread Tools | Display Modes |
| | (permalink) |
| Experienced Member | Ok this is EXTREMELY odd, I am making a PIC 16F84A programming, and I have it simulating like I wanting it, but when I load it onto my actually pic and test it, a certain part of the program randomly works correctly and randomly doesnt work correctly. Here is the code: Code: errorlevel -302 ;Suppress bank warning __config 3FFAh ; WDT Off, HS Oscillator, CP off ;**************************************************************************** ;* Set Up Varibles * ;**************************************************************************** STATUS equ 0x03 TRISA equ 0x85 TRISB equ 0x86 PORTA equ 0x05 PORTB equ 0x06 COUNT1 equ 0x08 COUNT2 equ 0x09 COUNT3 equ 0x0C CMDOUT equ 0x0D DATAIN equ 0x0E BTLOOP equ 0x0F BIT equ 0x10 WTEMP equ 0x11 ;**************************************************************************** ;* Set Up Ports * ;**************************************************************************** bsf STATUS,5 movlw 0x01 movwf TRISA ; RA0 - DATA INPUT ; RA1 - COMMAND OUTPUT ; RA2 - ATT OUTPUT ; RA3 - CLOCK OUTPUT movlw 0x00 movwf TRISB ; Button Outputs bcf STATUS,5 ;**************************************************************************** ;* Set Initial Conditions * ;**************************************************************************** movlw 0x0C movwf PORTA movlw 0x00 movwf PORTB ;**************************************************************************** ;* Main Program * ;**************************************************************************** call DELAY ; Delay bcf PORTA,2 ; Bring ATT Low call DELAY ; Delay movlw 0x01 ; Set the command to be sent as 0x01 movwf CMDOUT ; Move it into variable call START ; Send "Start" Command Byte 1 call DELAY call DELAY movlw 0x42 ; Set the command to be sent as 0x42 movwf CMDOUT ; Move into variable call REQUESTDATA ; Request Controller Data Byte 2 bsf PORTA,2 ; Bring ATT High movf DATAIN,w movwf PORTB LOOP movlw 0x00 goto LOOP ;**************************************************************************** ;* START - Send 0x01 to Controller * ;**************************************************************************** START movlw 0x08 ; Set up 8 Clock Cycles movwf BTLOOP ; movlw 0x01 ; Set up Bit Counter LOOP2 movwf BIT ; Move Bit andwf CMDOUT,w ; Is CMD high? skpz ; If not, skip next command bsf PORTA,1 ; Set CMD bit high bcf PORTA,3 ; Clock Low call DELAY ; Delay bsf PORTA,3 ; Clock High rlf BIT,w ; Shift for next bit bcf PORTA,1 ; Clear CMD bit call DELAY ; Delay decfsz BTLOOP goto LOOP2 return ;**************************************************************************** ;* REQUESTDATA - Sending 0x42 * ;**************************************************************************** REQUESTDATA movlw 0x08 ; Set up 8 Clock Cycles movwf BTLOOP ; movlw 0x00 movwf DATAIN movlw 0x01 ; Set up Bit Counter LOOP3 movwf BIT ; Move Bit andwf CMDOUT,w ; Is CMD high? skpz ; If not, skip next command bsf PORTA,1 ; Set CMD bit high bcf PORTA,3 ; Clock Low rrf PORTA,w ; Read bit from DATA in rrf DATAIN,f ; shift bit call DELAY ; Delay bsf PORTA,3 ; Clock High rlf BIT,w ; Shift for next bit bcf PORTA,1 ; Clear CMD bit call DELAY ; Delay decfsz BTLOOP goto LOOP3 return ;**************************************************************************** ;* Delay Loop 195.84ms (x5 Delay Multiplier) * ;**************************************************************************** DELAY movwf WTEMP movlw 0xFF ; Set Up Delay movwf COUNT1 movlw 0xFF movwf COUNT2 movlw 0x05 movwf COUNT3 movf WTEMP,w LOOP1 decfsz COUNT1,1 ; Decrease Count 1 1us x 255 = 255us goto LOOP1 ; until Count1 is zero 2us x 255 = 510us decfsz COUNT2,1 ; Repeat this process 1us x 255 = 255us goto LOOP1 ; 255 times 2us x 255 = 510us decfsz COUNT3,1 ; Repeat this process goto LOOP1 ; 5 times return ; Return (((3us * 255 times) * 255 times) + (3us x 255 times)) * 5 end It simulates just fine, so I dont have a clue on what could be going wrong. I'm sure my pic is hooked up correctly since everything else works fine and Ive never had this problem with any other programs ive made. And I'm sure there isnt anything wrong with the actual PIC itself since i've tested this on multiple (brand new) PICs with the same result. |
| | |
| | (permalink) | |
| Experienced Member | Quote:
Consecutive BSF, BCF, BTFSS, BTFSC, RRF, RLF and other commands on port direct will absolutely be asking for troubles. The first instruction changes port pin(s) status, but pin(s) level take time to change if there are capacitance connected to it. When the second instruction read the pin status, the wrong status will be read. Solution: Use a port shadow register or insert several NOPs between port change instructions.
__________________ L.Chung | |
| | |
| | (permalink) |
| Experienced Member | Hi, The one thing I could see is (in addition to the port problems) is that you have not defined the start pointer at the reset vector address, or the other interrupt vectors. It might not mean anything here, but its always a good practice to define startingpoints/ vectors. TOK |
| | |
| | (permalink) |
| Experienced Member | Never hear of the Read-Modify-Write limitation, do you mind pointing me to any documents/articles relate to it? Also, what is port shadowing? And do you mean put a few NOP each time I change a bit? Reguardless weather that bit is input/output? |
| | |
| | (permalink) |
| Experienced Member | While the RMW (read/modify/write) instructions can cause a problem, this is not your problem here. The problem you are seeing is due to the random nature of hardware when it is first turned on. Some of the RAM and SFRs are initialised into known states, such as the ports being set to input, the rest are random. Simulators, tend to set everything up and so produce the same result each time. Your problem is caused by 1 bit that is setup randomly - the carry bit. If at the top of your code, you add bsf STATUS,C then you will see that after the rlf BIT,w that W now contains 3, not 1 as you expected, because the carry bit has been shifted into bit zero. So, the easy fix is to add clrf STATUS at the top of your code. I would add, that your code is not very easy to follow. Take note of some of the suggestions above like putting an org at the start of your code. Your START routine, uses w to keep track of the bit even though you have a variable called BIT. Go back and have a look at the code MIKE,K8LH posted, it's much cleaner. HTH Mike. |
| | |
| | (permalink) |
| Experienced Member | Thanks for the suggestion. However, I put a clrf STATUS right after I set up the variables, and the randomness still occurs. |
| | |
| | (permalink) | |
| Experienced Member | Quote:
Instead, can you insert this. Code: START movlw 0x08 ; Set up 8 Clock Cycles movwf BTLOOP ; movlw 0x01 ; Set up Bit Counter LOOP2 movwf BIT ; Move Bit andwf CMDOUT,w ; Is CMD high? skpz ; If not, skip next command bsf PORTA,1 ; Set CMD bit high bcf PORTA,3 ; Clock Low call DELAY ; Delay bsf PORTA,3 ; Clock High bcf STATUS,C ; <<<<<<<<<<<<<<<<<<< inserted line. rlf BIT,w ; Shift for next bit bcf PORTA,1 ; Clear CMD bit call DELAY ; Delay decfsz BTLOOP goto LOOP2 return HTH Mike. | |
| | |
| | (permalink) |
| Experienced Member | Thanks! That worked. Do you mind explaining why I need to clear the carry bit each loop? |
| | |
| | (permalink) | |
| Experienced Member | Quote:
It was mentioned in the 16F84 datasheet but got deleted in the 16F84A datasheet so you might not have seen it. Why it is deleted I have no clue because the problem is still there. The insertion of NOPs is to give time for the pin to attain the correct logic level and depends on what is connected to the pin. A test by one user in the Microchip forum using just a 0.1uF capacitor on a port pin reveals it could take 10us or more for the pin level to match with the port latch. Within this time, there can be many PIC instructions and any read port instruction would return the wrong logic level. Port shadowing is to set aside a register to store the port bit and we change the bit value of the shadow register instead. After we made the change, the register value can be outputted to the port.
__________________ L.Chung | |
| | |
| | (permalink) | ||
| Experienced Member | Quote:
Would this only matter when doing a bit test on a input pin? Would the solution be put 10 NOP instructions before and after testing a particular bit? | ||
| | |
| | (permalink) | |
| Experienced Member | Quote:
Code: LOOP2 movwf BIT ; Move Bit andwf CMDOUT,w ; Is CMD high? skpz ; If not, skip next command bsf PORTA,1 ; Set CMD bit high <<<<< OK bcf PORTA,3 ; Clock Low <<<<< possible RMW problem There is more information in this thread, in the Microchip forum: "read-modify-write" problem
__________________ L.Chung | |
| | |