Author Topic: Pic programming issue.  (Read 9380 times)

0 Members and 1 Guest are viewing this topic.

Offline RodHTopic starter

  • Newbie
  • Posts: 6
Pic programming issue.
« on: July 11, 2015, 10:24:32 pm »
I have an assembly program for the pic 16f84a. This program is for model railroaders to start and stop a railroad crossing signal. The program is intended to start when it receives a external pulse from a 555 chip acting as a switch debouncer. The program then causes two LED's to flash alternately and also count the external pulses. When it counts four pulses, it should stop flashing and return to stand bye mode. The program starts, flashes and appears to count pulses, but will not stop. Anyone have an idea?

Here is the Assembly code:

;======================================================
;   train crossing light control version 1.0
;
;======================================================
;   list   p=16f84a
;   include   "p16f84a.inc
   radix   hex
;======================================================
;       cpu equates (memory map)
tmr0   equ   0x01
status   equ   0x03
porta   equ   0x05
portb   equ   0x06
intcon   equ   0x0b
var1   equ   0x30
var2   equ   0x31

;
;======================================================
;       variables
;   store
;
;======================================================
;config_xt_osc
;
;
;======================================================


   org   0x00
   goto   start                      ;skip interrupt vector
;
start   org           0x004
   bcf           intcon,7             ;disable global interrupt
   movlw   b'11110000'   
   tris           portb      ;setup port b 1=in,0=out
   movlw   b'00000000'   ;clear port b
   movwf   portb      ;clear port b
   movlw   b'11010111'
   option
   bcf           status,2
pgm   btfsc           portb,6       ;test bit 6,port b
   call           init               ;starts lamps

   goto           pgm               ;repeat

;==========================================================
init
   movlw   b'00000001'
   movwf   var2               ;start sensor count
   goto   first
   



;=========================================================
first
   movlw   b'00000000'      
   movwf   var1                        ;inital load (0) store
   bsf           portb,0                ;set first lamp
   clrf           tmr0                        ;clear/start timer0
   goto           circle                        ;check timer flag
   btfsc           portb,6
   call           add1                ;check switch
   goto           second
   


;==========================================================
second
   bcf           portb,0               ;clear lamp 1
   bsf           portb,1               ;set set lamp 2
   movlw   b'00000000'
   movwf   var1                       ;clear store
   btfsc           portb,6
   call           add1               ;check switch
   goto           third


;===========================================================
circle
   btfsc           portb,6      ;check switch
   call           add1      
   btfss    intcon,2            ;check tmr0 flag,skip next on true
   goto           circle
   bcf           intcon,2            ;clear tmr0 flag
   clrf           tmr0               ;start tmr0
   incf           var1               ;add 1 to var1
   btfsc           portb,6      ;check switch
   call           add1
   movlw   5               ;place value in w
   nop
   subwf   var1,w      ;subtract var1 from w
   btfss           status,2
   goto           circle
   bcf           status,2               
   goto           second      ;lamp 1 to lamp 2

;===========================================================
add1

   incf           var2      ;add one to count
   
   return


;===========================================================
third

   btfss    intcon,2             ;check tmr0 flag,skip next on true
   goto           third
   bcf           intcon,2             ;clear timer flag
   clrf           tmr0                ;start timer0
   btfsc           portb,6        ;check switch
   call           add1
   incf           var1               ;add 1 to var1
   movlw   5               ;place value in w
   nop
   subwf   var1,w      ;subtract var1 from w
   btfss           status,2
   goto   third
   movlw   b'00000001'   ;preset port b with green lamp on
   movwf   portb      ;complete preset
   btfsc           portb,6
   call           add1      ;check switch
   clrw                         ;clear w
   movlw   4
   nop
   subwf   var2,w      ;checking switch count
   btfss           status,2   
   goto           first      
                             ;lights off back to preset
   goto    start

;=======================================================================
   end

 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 3302
  • Country: us
Re: Pic programming issue.
« Reply #1 on: July 12, 2015, 03:51:58 am »
Any reason you're not doing this in C.  It would be so much easier.

For example:
Code: [Select]
#include <xc.h>
#include <stdint.h>


// CONFIGURATION BITS
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (Power-up Timer is enabled)
#pragma config CP = OFF         // Code Protection bit (Code protection disabled)


#define _XTAL_FREQ 20000000L     // 20MHz clock
#define delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

uint8_t Xing=0;      // switch count
uint8_t LEDbits=3;   // portB bits 0 and 1 for LEDs (0=LED On, 1=LED Off)
uint8_t TRIGenable=1;
uint8_t frame=0;

void main()
{
   OPTION_REGbits.nRBPU=1;    // Port B pull-ups disabled

   TRISA = 0xff;        // Set Port A direction bits
   TRISB = 0xf0;        // Set Port B direction bits
   PORTB = LEDbits;

   // MAIN LOOP
   while (1) {

      // Look for external pulse
      if (PORTBbits.RB6 == 1 && TRIGenable) {
         Xing++;              // increment pulse count
         TRIGenable = 0;
      }
      else if (PORTBbits.RB6 == 0) {   // wait for pulse to go away
         TRIGenable = 1;
      }

      // Process RR Crossing LEDs
      if (Xing > 0) {
         // start LED flashing if both are off
         if (LEDbits == 3) {
            frame = 0;              // restart frame count
            LEDbits = 1;            // turn on one LED
            PORTB = LEDbits;        // output to portB
         }
         // toggle LEDs when frame count wraps
         else if (frame == 0) {
            LEDbits ^= 3;           // toggle LEDs
            PORTB = LEDbits;        // output to portB
         }
         // stop LED flashing if 4 pulses received
         else if (Xing >= 4) {
            Xing = 0;
            LEDbits = 3;            // turn off LEDs
            PORTB = LEDbits;        // output to portB
         }
         // increment frame count and wrap when time delay reached
         // toggle LEDs every second
         if (frame++ >= 25) frame = 0;
      }

      delay_ms(20);  // 50 Hz loop
   }
}

« Last Edit: July 12, 2015, 04:29:30 pm by MarkF »
 

Offline android

  • Regular Contributor
  • *
  • Posts: 135
  • Country: au
Re: Pic programming issue.
« Reply #2 on: July 12, 2015, 07:40:10 am »
I'm not sure if this helps, but the code in red will never be executed...
Quote
first
   movlw   b'00000000'     
   movwf   var1                        ;inital load (0) store
   bsf           portb,0                ;set first lamp
   clrf           tmr0                        ;clear/start timer0
   goto           circle                        ;check timer flag
   btfsc           portb,6
   call           add1                ;check switch
   goto           second
Lecturer: "There is no language in which a double positive implies a negative."
Student:  "Yeah...right."
 

Offline rolycat

  • Super Contributor
  • ***
  • Posts: 1103
  • Country: gb
Re: Pic programming issue.
« Reply #3 on: July 12, 2015, 08:10:50 am »
Other questions might include:

Why use a 555 timer to debounce your switch when it is connected to a microcontroller?

Why use a prehistoric chip like the 16F84A, rather than, say, the 16F1847, which is pin-compatible, doesn't require an external oscillator, has vastly more capability and costs three times less?


 

Offline picandmix

  • Frequent Contributor
  • **
  • Posts: 395
  • Country: gb
Re: Pic programming issue.
« Reply #4 on: July 12, 2015, 09:29:32 am »
There are a few set up errors with your code, the attached file has corrected them , though I have not gone though the actual logic of your main loop.

Could do that later if you are still stuck.

As said you can use the Pic to sense a switch, as long as its a voltage below 5v.
Use the btfss/c  PORTB,1 instructions to read in the signal,  and then use a small software delay of say 50 ms to debounce the input , then use the btfss/c again to ensure it is on.
Examples here  - http://www.winpicprog.co.uk/pic_tutorial2.htm

This site has a handy delay calculator.http://www.golovchenko.org/cgi-bin/delay

As Rolycat  mentions you can use more modern chips, but you will also need a modern programmer whereas you may well be using a simple  'el cheapo' programmer  that will do what you need on the 84A for now.
« Last Edit: July 12, 2015, 09:34:36 am by picandmix »
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Pic programming issue.
« Reply #5 on: July 12, 2015, 09:39:17 am »
I ran your code in MPLAB first thing that cropped up was that Watch dog timer had not been disabled . this timer will reset the pic continually, your file should have a config line, something like this...

Code: [Select]
LIST P=16F84a

#INCLUDE <P16F84a.INC>

__CONFIG H'3FF0' ; CP OFF (B13-B4): PWRT ENABLED: WD DISABLED
__BADRAM H'07', H'50'-H'7F', H'87'  ; XT= LP  or whatever ! ;


add this and see where you get .
« Last Edit: July 12, 2015, 10:10:11 am by 22swg »
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 

Offline picandmix

  • Frequent Contributor
  • **
  • Posts: 395
  • Country: gb
Re: Pic programming issue.
« Reply #6 on: July 12, 2015, 04:33:44 pm »
Missed one of the Bank1 registers, so you need to amend the code as follows to ensure the Option Register is used properly.

Also what frequency crystal or similar are you using ? your code contained XT_OSC so that indicates a crystal up to 4 Mhz
 
Is the code your own or from a web page, if so can you give a link ?

Code: [Select]
start 
   bcf    intcon,7             ;disable global interrupt
   movlw   b'11110000' 
   banksel TRISB
   movwf  TRISB                ;setup port b 1=in,0=out
   movlw   b'11010111'
   movwf   OPTION_REG

   banksel 0
   movlw   b'00000000'   ;clear port b
   movwf   portb      ;clear port b
 



With the above code corrections to the start up section your code , the whole program runs in a simulator.

When the switch is closed it will start flashing at about 1hz ( with a 4mhz oscillator, (not shown in the simulator diagram) )  but even with lots of on/offs from the switch nothing seems to stop the flashing.
Think a bit of work and you will be able to fix it ....?

« Last Edit: July 12, 2015, 08:46:56 pm by picandmix »
 

Offline Dinsdale

  • Regular Contributor
  • *
  • Posts: 77
  • Country: us
    • pretzelogic
Re: Pic programming issue.
« Reply #7 on: July 13, 2015, 04:44:08 pm »
You also have a call to "init" for which there is never a return. It does not hurt anything since that enters a loop that is never exited, but you have used up one stack level.
This can't be happening.
 

Offline RodHTopic starter

  • Newbie
  • Posts: 6
Re: Pic programming issue.
« Reply #8 on: July 14, 2015, 06:37:31 pm »
Thank you all for your comments.. However, the program runs in my emulator without problems. Where it does not run is in the circuit board I created to support it. In the circuit, it responds to the first pulse, the lights flash as desired; but it does not respond to any other pulses in order to stop it. That is the problem and why I asked for help. I had hoped someone would see a software issue that I have overlooked.
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2340
Re: Pic programming issue.
« Reply #9 on: July 14, 2015, 06:55:33 pm »
However, the program runs in my emulator without problems. Where it does not run is in the circuit board
Which strongly suggests either a problem with the hardware, or a mis-understanding of the real-world interface of the PIC. Can you give some more details of the hardware?
 

Offline picandmix

  • Frequent Contributor
  • **
  • Posts: 395
  • Country: gb
Re: Pic programming issue.
« Reply #10 on: July 14, 2015, 07:57:31 pm »
Thank you all for your comments.. However, the program runs in my emulator without problems. Where it does not run is in the circuit board I created to support it. In the circuit, it responds to the first pulse, the lights flash as desired; but it does not respond to any other pulses in order to stop it. That is the problem and why I asked for help. I had hoped someone would see a software issue that I have overlooked.

Because there were so many corrections needed to the set up part of the code, assumed that was the main cause of your problems and with the code I sent you would be able to resolve that last problem within your main loop.

Will take a further look at your code and see if I can spot the problem.

Am I correct with the schematic I showed above ?  and that it uses a 4mhz crystal ?
 

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 628
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: Pic programming issue.
« Reply #11 on: July 14, 2015, 10:05:11 pm »
Thank you all for your comments.. However, the program runs in my emulator without problems.
Perhaps you didn't simulate it thoroughly enough. I tried simulating your code in MPLAB 8 and found a problem here:-
Code: [Select]
circle
   btfsc          portb,6      ;check switch
   call           add1     
   btfss          intcon,2     ;check tmr0 flag,skip next on true
   goto           circle
If the switch is held closed then it will continuously add 1 to var2. This loop is only a few instructions so it counts very quickly (about 9us per count). When the switch is opened again at some later time, var2 will be a random number between 0 and 255.

This is  a problem because later you stop the flashing sequence only if var2 = 4...
Code: [Select]
   movlw   4
   nop
   subwf   var2,w      ;checking switch count
   btfss   status,2    ;<-- skpz = skip if zero (ie. if var2 = 4)
   goto    first     
                       ;lights off back to preset
   goto    start
...but since the value of var2 is random, there is only one chance in 256 of the sequence stopping!

Is the 'call add1' in 'circle' some kind of debounce timer? If so then perhaps you should only call add1 only after timer 0 overflows, stop counting (in add1) if/when it gets to 255, and use skpc instead of skpz when testing the switch count so that it will skip on a count which is equal to or higher than the debounce value you are comparing it to.       

When using mechanical switches you have to assume that the switch could be on or off for long periods of time, or even flicking between on and off.  When simulating a switch I set breakpoints at places in the code where the switch's action should trigger a response (eg. starting the flashing light sequence, turning the lights off and restarting). I then toggle the I/0 port to simulate turning the switch on and let the program run until it hits a breakpoint, then continue running from the breakpoint (without toggling the switch off) to see where it will end up next. This should show up any 'holes' in the program that let it fall through to places you don't want it to reach while the switch is held down.

A few notes on style:-

1. Use the official register names and bits defined in the device's include file, eg.  'bcf INTCON,TMR0IF'

2. Use built in macros such as 'skpz', rather than the obtuse 'btfss  status,2'

3.  Assign symbolic names to raw numbers wherever practicable, eg.  '#define SWITCH 6', 'btfsc PORTB, SWITCH'.

This will make your code easier to follow and more maintainable. It is much easier and less error prone to change one define, rather than having to hunt through all your code looking for a particular number just to change a port pin! 
   
« Last Edit: July 14, 2015, 10:10:40 pm by Bruce Abbott »
 

Offline picandmix

  • Frequent Contributor
  • **
  • Posts: 395
  • Country: gb
Re: Pic programming issue.
« Reply #12 on: July 14, 2015, 10:35:02 pm »
I should have given  your code a  better look earlier as afraid your code will not work in its present form, despite it appearing to run in a simulator, which is more by chance.

You are using Timer0 as your delay source but that can only divide the main frequency by 256 so even if using a watch crystal at 32khz that means  its maximum delay can only be  -   Fosc/4 / prescaler     =  32k/4 / 256  = 1/32 of a second.

You have two options , continue with Timer0 as the source to a larger software delay loop or use a pure sofware loop like the ones I pointed to in the link earlier.

Thats why you need to state what frequency oscillator /crystal you are using, as until thats given no timings can be established.

Can give you some help if you cannot see a way forwards by yourself as your code does need rewriting, but its not that complex to achive what you want to do.


Edit  - just to get you on the right track here is your code but with the start and flasher code rewritten using a 1 second software delay based on a 4mhz crystal ( value can be easily changed).

See what you think ...  Have some thoughts on how I would complete it, but think you might like to try it yourself first .. ?





 
« Last Edit: July 14, 2015, 11:23:02 pm by picandmix »
 

Offline picandmix

  • Frequent Contributor
  • **
  • Posts: 395
  • Country: gb
Re: Pic programming issue.
« Reply #13 on: July 15, 2015, 04:05:55 pm »
Below is a .hex file for the complete routine you might be able to simulate or run on your hardware.
Its based on a 4mhz crystal or r/c.   - frequency can be easily changed.

What it can also do, is act as a debouncer for your switch as it can handle any length of ON pulse * without affecting the flashing leds timings.
* currently based on a minimum ON pulse of 100ms, though that can be reduced if needed.

Have not included the source code yet, as perhaps you want to try and complete the coding yourself , as mentioned yesterday.
 

Offline jnz

  • Frequent Contributor
  • **
  • Posts: 593
Re: Pic programming issue.
« Reply #14 on: July 17, 2015, 03:34:46 am »

I find it fascinating that beginners will try and use ASM and deal with the issues over just learning basic C elements :)   It's the weird sharp curve where noobs and experts are likely to use assembly.

 

Offline RodHTopic starter

  • Newbie
  • Posts: 6
Re: Pic programming issue.
« Reply #15 on: July 17, 2015, 07:21:19 pm »
As a matter of fact, jnz I learned to use assembly language on the pic microcontrollers in a college course while earning my BS in engineering..  Your comment looks like one of those made by trolls on Facebook.
 

Offline picandmix

  • Frequent Contributor
  • **
  • Posts: 395
  • Country: gb
Re: Pic programming issue.
« Reply #16 on: July 17, 2015, 10:00:46 pm »

I find it fascinating that beginners will try and use ASM and deal with the issues over just learning basic C elements :)   It's the weird sharp curve where noobs and experts are likely to use assembly.

I must be really weird then, I started programming NatSemi micro chips in Machine Code ... :P.... ;D
 

Offline picandmix

  • Frequent Contributor
  • **
  • Posts: 395
  • Country: gb
Re: Pic programming issue.
« Reply #17 on: July 17, 2015, 10:02:08 pm »
As a matter of fact, jnz I learned to use assembly language on the pic microcontrollers in a college course while earning my BS in engineering..  Your comment looks like one of those made by trolls on Facebook.


Any progress with your project  ?

My code below if you need it.

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->