Menu

pic16f628a simple counter problem

Help
fisyon
2012-08-12
2013-05-30
  • fisyon

    fisyon - 2012-08-12

    hi,
    i made a simple counter on breadboard with 2 switches and 3 digita 7 segments CA display.
    sw1 counts up and sw2 counts down. counter resets if both are pressed
    somehow i completed program but there is a problem:
    the counter can count between 0 and 255. i wanted 0-999 counter but the counter returns 0 when i increased >255.
    i tried a few things like canceling systempx… not working…

    here is my whole code:

    '================================================================
    '===== CHIP SETUP 
    '================================================================
    #chip 16F628a, 4
    #config  OSC=int, BODEN=OFF, WDT=OFF                    
                              
    #define StartUpDelay 100 ms
    '#define Delay 500 ms                          
    '================================================================
    '===== DEFINE THE PORTS 
    '================================================================
    'Pin14 ===> Vdd

    #define DISP_SEL_1 PORTa.3 'Disp1 MSD 2->12
    #define DISP_SEL_2 PORTa.6 'Disp2 15->9
    #define DISP_SEL_3 PORTa.7 'Disp3 LSD 16->8
    #Define DISP_SEG_A PORTb.3 'A 9->11
    #Define DISP_SEG_B PORTb.1 'B 7->7
    #Define DISP_SEG_C PORTb.7 'C 13->4
    #Define DISP_SEG_D PORTb.5 'D 11->2
    #Define DISP_SEG_E PORTb.4 'E 10->1
    #Define DISP_SEG_F PORTb.2 'F 8->10
    #Define DISP_SEG_G PORTa.0 'G 17->5
    #define DP PORTb.6 'DP 12->3
    #define sw1 porta.1 'Buton1
    #define sw2 porta.2 'Buton2

    'Pin5 ===> Vss
                              
    '===> Timer interrupt example - Timer Setup
    'Replace with your interrupt requirements
    InitTimer1 (Osc, PS1_1/8) '==> Init timer prescaler
    StartTimer 1
    CounterValue = 0
                              
    '================================================================
    '===== SET DIRECTION OF THE PORTS 
    '================================================================
    'Pin14 ===> Vdd
    dir portb out
    dir porta.4 out

    set PORTa.3 off'Disp1 MSD
    set PORTa.6 off'Disp2
    set PORTa.7 off'Disp3 LSD
    set PORTb.3 off'A
    set PORTa.1 off'B
    set PORTb.7 off'C
    set PORTb.5 off'D
    set PORTb.4 off'E
    set PORTa.2 off'F
    set PORTa.0 off'G
    set PORTb.6 on'DP
    dir sw1 in
    dir sw2 in

    'Pin5 ===> Vss
    dim delay as byte
    dim swdelay as word
    dim num as integer

    swdelay=250
    delay=5

    Startup:
    Wait StartUpDelay
    '===> Timer interrupt example - Enable interrupt
    'Replace with your interrupt requirements
    On Interrupt Timer1Overflow Call IncCounter    
                              
    '================================================================
    '===== MAIN PROGRAM LOOP 
    '================================================================
    Main:
           'Main App code here 
    epread 20, num

    set PORTa.3 off'Disp1 MSD
    set PORTa.6 off'Disp2
    set PORTa.7 off'Disp3 LSD
    set PORTb.3 off'A
    set PORTa.1 off'B
    set PORTb.7 off'C
    set PORTb.5 off'D
    set PORTb.4 off'E
    set PORTa.2 off'F
    set PORTa.0 off'G
    set PORTb.6 on'DP

    if sw1=1 and sw2=1 then
    wait swdelay ms
    num=0
    EPWrite 20,num
    end if

    if sw1=1 then
    wait swdelay ms
    num=num+1
    EPWrite 20,num
    end if

    if sw2=1 then
    wait swdelay ms
    num=num-1
    EPWrite 20,num
    end if

                      

    gosub showdisp

    Goto Main
                              
    '================================================================
    '===== SUBROUTINES AND FUNCTIONS 
    '================================================================
    sub showdisp

    do
    select case num
    case >=100
    DispNum1=num/100
    DisplayValue 1,dispnum1
    wait delay ms
    Num2=num-(dispnum1*100)
    if Num2>=10 then
    DispNum2=num2/10
    DispNum3=num2-(dispnum2*10)
    DisplayValue 2,dispnum2                  
    wait delay ms
    DisplayValue 3,dispnum3                  
    wait delay ms
    else
    DispNum3=num2
    displayvalue 2,0
    wait delay ms
    DisplayValue 3,dispnum3                  
    wait delay ms
    end if

    case =>10 and num<100

    DispNum2=num/10
    DispNum3=num-(dispnum2*10)
    DisplayValue 2,dispnum2                  
    wait delay ms
    DisplayValue 3,dispnum3                  
    wait delay ms

    case <10
    DispNum3=num
    DisplayValue 3,dispnum3                  
    wait delay ms

    end select

                     
    goto main
    loop
    end sub

    Sub IncCounter '===> Sub called by Timer interrupt example
           CounterValue ++
    End Sub

    PS:
    * i am not good at english, please forgive my mistakes
    * the code probably is not optimum. i don't care if it is working…
    * this is a learning practice for me. no serious goal at this moment.
    * i don't understand how to use an interrupt with these switches. can you help me about that too?
    * the 7segment.h file edited by me because Common Anode displays with no transistor used
    * i am tired of pull out / put in the IC. i know i need a simulator. can you recommend working one on winxp?

     
  • mmotte

    mmotte - 2012-08-13

    I haven't seen a reply so I have a couple comments.

    1) num is defined as an integer which only has a range of  0 - 255.  When the variable overflows to 1000 then you have to reset it to 0 with a statement.  Are you making a timer or a counter?

    2) CounterValue is not being used.    To use an interrupt  you would need an "On Interrupt" statement calling the interrput subroutine.

    3) You should not write to EEPROM so often. It is only guaranteed   X number writes.  X could be 1000000 but if you write every 250 ms that could pass quick.

    Sorry that is all the time I have,
    GL
    Mike

     
  • mmotte

    mmotte - 2012-08-13

    Now I see the "On Interrupt" !  skip that comment.

    sorry
    mike

     
  • fisyon

    fisyon - 2012-08-13

    thank you mike,
    1) as far as i know "byte" has 0 / 255 range and "integer" must be -32768 / 32767 range according to gcbasic help file

    2) i dont know how to connect oninterrupt and switches. i need to make an interrupt when a particular switch pressed… this "oninterrupt" word is not written by me. it is "gcbide"s example code which i didn't delete.

    3) yes, i know  eeproms have short lifespan. i will do it better way.

    PS:
    * i don't know what is changed  but 0-999 is working now :P
    * i really need a working simulator. it is annoying to put in/out pic to breadboard for every trial… you guys, how do you do that trials?

     
  • mmotte

    mmotte - 2012-08-13

    in your downloaded "update file"    :   http://gcbasic.sourceforge.net/update.html
    Look at the help file   gcbasic.chm  which opens into Great Cow Basic Help > command reference> interrupts> on interrupt

    on the 16f628a the "B port" has a on change of bits 4-7    RBIF
    You could hang your switches on these bits but that would require  a decision  when entering the interrupt to see if it is Port B interrput or a timer interrupt and then service that interrupt.  Switches and people that push them are relatively slow so just having them in the main loop and polling them should be fast enough( like you have now).

    73
    mike

     
  • kent_twt4

    kent_twt4 - 2012-08-13

    @fisyon
    You are using a ziff socket for programming?  Best way is to use icsp or in circuit serial programming.  To do that break out the MCLR , Vdd, Vss, icspDAT, iscpCLK lines respectively.  You can use jumpers or make up a cable to go between the programmer and the bread board.  Using a straight or 90 deg.  6 pin 0.100" header also works for the highly recommended  pickit programmers.

     
  • fisyon

    fisyon - 2012-08-13

    mike,
    thank you for the fast reply,
    so you are saying i can only use portb 4-7 pins for interrupts on 16f628a?
    if so i will need to change all circut and code :P
    whatever, thanks for your patience

     
  • fisyon

    fisyon - 2012-08-13

    @kent_twt4
    yes, i am using usb programmer with ziff socket (k182?)
    icsp may be good idea but i am not feeling that i can handle it properly at this moment.
    thank you anyway

     
  • kent_twt4

    kent_twt4 - 2012-08-13

    Here is the developers page on icsp programming for the kitsrus programmers http://www.kitsrus.com/icsp.html
    I would implore you to effect the icsp diagram with the three commonly available parts.  There is no shame in hitting the compile button repeatably, I do it all the time.  Taking a chip in and out of the ziff socket all the time would just take the fun out of doing projects :-)

     
  • Nobody/Anonymous

    Your problem is here . EPWrite 20,num
    The EEPROM in a 16F628 is only 8 bits wide not 16 , so you can only write and read 8 bit values
    to any EEPROM memory location.
    To write and read 16 bit values , you have to break the variable into 2, 8 bit variables and then write them to multiple memory locations.

     
  • Nobody/Anonymous

    Back to the code.

    'Goto main' there is not allowed, because your stack will get messed-up.
    you may never jump out of a sub without using the stack pointer.
    Goto doesn't use the stack-pointer, 'end Sub' does. So, 'end sub' should be the call to make to return where it cam from

    Op 12 aug. 2012, om 22:58 heeft SourceForge.net het volgende geschreven:

            end select
    
    goto main  <- not allowed
        loop
    end sub
    
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.