a task with pic16f628 timer 0 . question

Discussion in 'Homework Help' started by Cyrenaica —, Nov 24, 2015.

  1. Cyrenaica —

    Thread Starter New Member

    Jun 7, 2015
    16
    2
    hi to every1 !!
    i hav a task : make a program on assembler , simulating traffic lights in two directions , with two versions: 1) with software's control timer using TMR0 ; 2) with interrupt of TMR0 .
    the first part of this task is totally completed ( except circuit of algorithm ) and no problem with this , so every switching of lights is controlled fully by timer 0 . okay . but now i am stuck by hours with second part . since it is a quite stupid idea to to force a chip to count digits with counters with BTFSS/BTFSC in macro ( due to power consumption 4 example ) , is there any way to use the first part of task to perform the second part of task ? maybe any other way ?
    interrupt should be whatever me wish , 4 example "by appearing of 0 on PORTA,4 ( by switching ON SA4 ) , start interrupt and make yellow colour blinks for some time then go back to main loop "
    i have tried and its ( maybe ) impossible cause tmr0 controls the changes of lights in the same time ! !
    please , any opinions or ideas are welcomed !

    [​IMG]

    Code (Text):
    1.     list p=16f628
    2.     #include <p16f628.inc>
    3.     __config _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF
    4.     cblock    0x22
    5. counter_1
    6. counter_2
    7.     endc
    8. ;================== beginprogram ==================
    9.     org 0x00
    10.     clrf PORTB
    11.     bcf STATUS,RP1
    12.     bsf STATUS,RP0
    13.     movlw b'11000000'
    14.     movwf TRISB
    15.     bcf STATUS,RP0
    16.     banksel OPTION_REG
    17.     movlw b'11010111'
    18.     movwf OPTION_REG       ;prescaler — 1:256
    19.     banksel TMR0
    20.     movlw .0
    21.     movwf TMR0             ;unset tmr
    22.  
    23. main_loop
    24.     bsf PORTB,4
    25.     bsf PORTB,1
    26.     bcf PORTB,2
    27.     bcf PORTB,3
    28.     bcf PORTB,0
    29.     movlw .92
    30.     movwf counter_1
    31. loop_1
    32.     call delay
    33.     decfsz counter_1,f
    34.     goto loop_1
    35.     movlw .4
    36.     movwf counter_2
    37. loop_2
    38.     bcf PORTB,4
    39.     movlw .8
    40.     movwf counter_1
    41. loop_3
    42.     call delay
    43.     decfsz counter_1,f
    44.     goto loop_3
    45.     bsf PORTB,4
    46.     movlw .8
    47.     movwf counter_1
    48. loop_4
    49.     call delay
    50.     decfsz counter_1,f
    51.     goto loop_4
    52.     decfsz counter_2,f
    53.     goto loop_2
    54.     bsf PORTB,2
    55.     bsf PORTB,3
    56.     bcf PORTB,4
    57.     movlw .31
    58.     movwf counter_1
    59. loop_5
    60.     call delay
    61.     decfsz counter_1,f
    62.     goto loop_5
    63.     bsf PORTB,0
    64.     bsf PORTB,5
    65.     bcf PORTB,2
    66.     bcf PORTB,3
    67.     bcf PORTB,1
    68.     movlw .92
    69.     movwf counter_1
    70. loop_6
    71.     call delay
    72.     decfsz counter_1,f
    73.     goto loop_6
    74.     movlw .4
    75.     movwf counter_2
    76. loop_7
    77.     bcf PORTB,5
    78.     movlw .8
    79.     movwf counter_1
    80. loop_8
    81.     call delay
    82.     decfsz counter_1,f
    83.     goto loop_8
    84.     bsf PORTB,5
    85.     movlw .8
    86.     movwf counter_1
    87. loop_9
    88.     call delay
    89.     decfsz counter_1,f
    90.     goto loop_9
    91.     decfsz counter_2,f
    92.     goto loop_7
    93.     bsf PORTB,2
    94.     bsf PORTB,3
    95.     bcf PORTB,5
    96.     movlw .31
    97.     movwf counter_1
    98. loop_10
    99.     call delay
    100.     decfsz counter_1,f
    101.     goto loop_10
    102.     goto main_loop
    103. ;********* subroutine *********
    104. delay
    105.     btfss INTCON,T0IF
    106.     goto delay
    107.     bcf INTCON,T0IF
    108.     banksel TMR0
    109.     movlw .0
    110.     movwf TMR0
    111.     return
    112. ;********* subroutineend *********
    113.     end
    114. ;================== end ==================
     
  2. GopherT

    AAC Fanatic!

    Nov 23, 2012
    6,056
    3,818
    Start by adding a ; to the right of each instruction (or block of instructions) and place a comment - lots of comments, so we know what you intended to do.

    also, if you read the datasheet - you will realize there are two more timers on that chip. An 8-bit and a 16 bit timer in addition to Timer0.
     
  3. Cyrenaica —

    Thread Starter New Member

    Jun 7, 2015
    16
    2
    thx for fast answer ! yes i have seen but they need external oscillators afaik , and the task is about tmr0 only . the main circuit in first post doesnt has any external oscs

    Code (Text):
    1. list p=16f628          ;list of options
    2.     #include <p16f628.inc> ; connect an additional output file
    3.     __config _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF
    4.                            ; set configuration bits microcontroller
    5.     cblock    0x22           ; determination unit constants
    6. counter_1
    7. counter_2
    8.     endc
    9. ;================== begin of programm ==================
    10. ;********* needed settings *********
    11.     org 0x00               ;make start address 0
    12.     clrf PORTB             ;initialization of PORTB
    13.     bcf STATUS,RP1
    14.     bsf STATUS,RP0         ;choose bank 1
    15.     movlw b'11000000'
    16.     movwf TRISB            ;RB<5:0> now working as OUTPUT
    17.     bcf STATUS,RP0         ;go back to bank 0
    18.     banksel OPTION_REG     ;choose bank of register
    19.     movlw b'11010111'
    20.     movwf OPTION_REG       ;options for timer; prescaler — 1:256
    21.     banksel TMR0           ;choose bank of register
    22.     movlw .0
    23.     movwf TMR0             ;unset timer
    24. ;********* needed setting completed *********
    25. main_loop                  ;this is the main loop
    26.     bsf PORTB,4 ;turn ON green led of one lighter
    27.     bsf PORTB,1 ;also turn ON red led of another lighter
    28.     bcf PORTB,2 ;turn OFF all yellow leds
    29.     bcf PORTB,3
    30.     bcf PORTB,0 ;and turn OFF red led of one lighter (watch the table)
    31.     movlw .92 ;send digit 92 for counter1, to count 0,065ms*92=6 sec approximately
    32.     movwf counter_1
    33. loop_1
    34.     call delay ; goto subroutine
    35.     decfsz counter_1,f ;decrement counter1 (“skip if 0”)
    36.     goto loop_1 ;if counter_1 >0 then go to loop 1
    37.     movlw .4 ;if counter 1=0 then make 4 cycles, totally 8 yellow blinks, every for 8*0,065ms=0,5 sec approximately
    38.     movwf counter_2
    39. loop_2
    40. ...
    41. ...
    42. ...
    43. ...
    44. etc
    45. ...
    46. ...
    47. loop_10
    48.     call delay ;call subroutine
    49.     decfsz counter_1,f ;decrement counter_1 and skip next instruction if it 0
    50.     goto loop_10
    51.     goto main_loop         ;go to the begin of programm
    52. ;********* subroutine*********
    53. delay
    54.     btfss INTCON,T0IF ;check T0IF and skip next instruction if it 1
    55.     goto delay ;t0if=0 - go here
    56.     bcf INTCON,T0IF ;t0if=1 - go here
    57.     banksel TMR0 ;choose bank of register
    58.     movlw .0 ;send a constant (unset tmr)
    59.     movwf TMR0
    60.     return ;return back
    61. ;********* end of subroutine*********
    62.     end
    63. ;================== end of programm ==================
    64.  
    i think the table of " switchings " could help to understand completed first part of the task . i have no problem with it , it compiles without any single error and were checked in real pic

    below is the table of switching . programm starts with action 1, then goes to 2,3,4,5,6 etc till 20, then goes back to 1 to repeat the cycle . if table not helps to understand what is going on , i will create circuit of algorithm later

    [​IMG]

    sorry for broken English
     
  4. Dodgydave

    Distinguished Member

    Jun 22, 2012
    4,986
    745
    Why do you need 8 sequences of leds, just use the four sequence repeated.
     
  5. Cyrenaica —

    Thread Starter New Member

    Jun 7, 2015
    16
    2
    no sir . i must have eight sequences because i have two traffic lights for two perpendicular roads :) it's all ok with my first type of programm

    well . i had re-read datasheet again further and now i think the best idea is to use TMR1 with an internal clock signal ( since we can use (???) programm connection to internal oscillator too , not only external as i thought ) . o_O really there no any other way , to make everything with only one timer as i wished . o_O so , the only thing in my mind now is to put and additional "BTFSS/BTFSC" with "BCF TMRC1S,4" etc , in delay subroutine , which redirects chip for work with other timer :(
     
  6. JohnInTX

    Moderator

    Jun 26, 2012
    2,346
    1,029
    This is a classic example of a state-machine. Look at your table. Each entry is a self-contained condition, the state of the system. Each line is a different 'state' and the system can only be in one state at a time.
    So.. a way to approach this is to first identify each state that the system can be in. According to your table, the system can be in 1 of 8 states. Code each state like it is a separate little program. Do this by coding 8 different functions (sub-routines), one for each state.

    So now you have 8 different functions. If you called one, it would output the light pattern that you want for that particular state i.e. RED on Main Street, GREEN on the cross street. The next state might be RED on Main Street, YELLOW on the cross street. Then GREEN on Main Street, RED on the cross street.

    That's 3 of the 8 states. The others are similar and describe unique conditions. When you are done, you have 8 subroutines/functions that, when called, set up the lights that define the system's current state.

    Once you have all 8 states coded and working, its time to schedule them by calling them in sequence. Column 2 of your table tells you how to do that:
    call function1;
    delay (for the time in line1, column 2)
    call function2;
    delay(...);
    call function3;
    delay(...);
    ... etc...
    when you get to the end, loop to the starting state.

    To start, I would just use dumb delays. The scheduling will be just the code-flow. There are ways of implementing state machines that are better but I'd do a brute-force approach first. Later, you can add a better scheduler and if you write the light output routines as the self-contained sub-routines as I describe, a better scheduler can use them as is.

    Have fun.
     
    Cyrenaica — likes this.
  7. Cyrenaica —

    Thread Starter New Member

    Jun 7, 2015
    16
    2
    thank you , great idea . :) it just makes programm looks neat . i see no difference in functional aspect , but your idea of " how to make program " is a way better to understand if it is being demonstrating to audience :eek:

    recently i have successfully received the highest mark for my homework ! thank to all for opinions and attention ! :) :) :)

    finally , ive used both timer 0 and timer 1 . after simulation in mplab ive have used proteus simulation , and then checked everything in the real pic . below is my code ( maybe itll be useful for some1 ) . comments are deleted . and proteus file i cant attach in forum due to " The uploaded file does not have an allowed extension. "

    Code (Text):
    1.  
    2.     list p=16f628
    3.     #include <p16f628.inc>
    4.     __config _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF
    5.     cblock    0x22  
    6. counter_1    
    7. counter_2                
    8. d1                        
    9. d2                            
    10. d3                            
    11.     endc            
    12. ;================== begin of program ==================
    13.     org 0x00                  
    14.     goto start_loop            
    15.     org 0x04                  
    16.     goto interrupt            
    17. start_loop                    
    18. ;********* list of macroses used *********
    19. delay500us    macro            
    20.     movlw D'5'                    
    21.     movwf d3                    
    22.     movlw D'5'                    
    23.     movwf d2                    
    24.     movlw D'5'                    
    25.     movwf d1                    
    26.     decfsz d1                    
    27.     goto $-1                  
    28.     decfsz d2                    
    29.     goto $-5                    
    30.     decfsz d3                    
    31.     goto $-9                    
    32.     endm                        
    33. ;********* end of list of macroses *********
    34. ;********* needed options *********
    35.     banksel INTCON              
    36.     clrf INTCON                  
    37.     banksel PORTA              
    38.     clrf PORTA              
    39.     movlw 0x07                
    40.     movwf CMCON              
    41.     banksel TRISA            
    42.     movlw b'00010000'          
    43.     movwf TRISA                
    44.     banksel PORTB            
    45.     clrf PORTB                  
    46.     banksel TRISB            
    47.     movlw b'11000000'          
    48.     movwf TRISB                
    49.     banksel OPTION_REG        
    50.     movlw b'11010111'          
    51.     movwf OPTION_REG        
    52.     banksel TMR0            
    53.     movlw .0                
    54.     movwf TMR0                  
    55. ;********* needed options are done *********
    56. main_loop                  
    57.     bsf PORTB,4                    
    58.     bsf PORTB,1                    
    59.     bcf PORTB,2                    
    60.     bcf PORTB,3                    
    61.     bcf PORTB,0                    
    62.     movlw .92                    
    63.     movwf counter_1                
    64. loop_1                            
    65.     call delay_1                
    66.     decfsz counter_1,f            
    67.     goto loop_1                
    68.     movlw .4                
    69.     movwf counter_2                
    70. loop_2                            
    71.     bcf PORTB,4                    
    72.     movlw .8                    
    73.     movwf counter_1                
    74. loop_3                            
    75.     call delay_1                
    76.     decfsz counter_1,f            
    77.     goto loop_3                    
    78.     bsf PORTB,4                    
    79.     movlw .8                    
    80.     movwf counter_1                
    81. loop_4                            
    82.     call delay_1                
    83.     decfsz counter_1,f            
    84.     goto loop_4                    
    85.     decfsz counter_2,f            
    86.     goto loop_2                  
    87.     bsf PORTB,2                    
    88.     bsf PORTB,3                    
    89.     bcf PORTB,4                    
    90.     movlw .31                    
    91.     movwf counter_1                
    92. loop_5                            
    93.     call delay_1                
    94.     decfsz counter_1,f            
    95.     goto loop_5                  
    96.     bsf PORTB,0                    
    97.     bsf PORTB,5                    
    98.     bcf PORTB,2                    
    99.     bcf PORTB,3                    
    100.     bcf PORTB,1                    
    101.     movlw .92                    
    102.     movwf counter_1                
    103. loop_6                            
    104.     call delay_1                
    105.     decfsz counter_1,f            
    106.     goto loop_6                  
    107.     movlw .4              
    108.     movwf counter_2                
    109. loop_7                            
    110.     bcf PORTB,5                    
    111.     movlw .8                    
    112.     movwf counter_1                
    113. loop_8                            
    114.     call delay_1                
    115.     decfsz counter_1,f            
    116.     goto loop_8                  
    117.     bsf PORTB,5                    
    118.     movlw .8                    
    119.     movwf counter_1                
    120. loop_9                            
    121.     call delay_1                
    122.     decfsz counter_1,f            
    123.     goto loop_9                    
    124.     decfsz counter_2,f            
    125.     goto loop_7                  
    126.     bsf PORTB,2                    
    127.     bsf PORTB,3                    
    128.     bcf PORTB,5                    
    129.     movlw .31                    
    130.     movwf counter_1                
    131. loop_10                            
    132.     call delay_1                
    133.     decfsz counter_1,f            
    134.     goto loop_10              
    135.     goto main_loop            
    136. ;********* sub-routinnes *********
    137. delay_1                          
    138.     btfss PORTA,4            
    139.     call timer_1            
    140.     btfss INTCON,T0IF          
    141.     goto delay_1              
    142.     bcf INTCON,T0IF              
    143.     banksel TMR0              
    144.     movlw .0              
    145.     movwf TMR0                  
    146.     return                      
    147. delay_2                          
    148.     btfss INTCON,T0IF          
    149.     goto delay_2            
    150.     bcf INTCON,T0IF              
    151.     banksel TMR0          
    152.     movlw .0                  
    153.     movwf TMR0                
    154.     return                        
    155. timer_1                        
    156.     banksel PORTA            
    157.     bsf INTCON,GIE              
    158.     bsf INTCON,PEIE          
    159.     banksel PIE1            
    160.     bsf PIE1,TMR1IE            
    161.     banksel T1CON              
    162.     bsf T1CON,0                
    163.     bcf T1CON,1                  
    164.     movlw b'11111110'          
    165.     movwf TMR1H                
    166.     movwf TMR1L                  
    167.     delay500us              
    168.     nop                            
    169.     goto main_loop              
    170. ;********* sub-routinne of interrupt *********
    171. interrupt                        
    172.     bcf INTCON,GIE          
    173.     banksel T1CON              
    174.     bcf T1CON,0                  
    175.     bcf PIR1,TMR1IF      
    176.     bcf PORTB,0                  
    177.     bcf PORTB,1              
    178.     bcf PORTB,4                  
    179.     bcf PORTB,5                    
    180.     movlw .8                  
    181.     movwf counter_2                
    182. loop_11                            
    183.     bsf PORTB,2                    
    184.     bsf PORTB,3                    
    185.     movlw .8                    
    186.     movwf counter_1                
    187. loop_12                            
    188.     call delay_2                
    189.     decfsz counter_1,f            
    190.     goto loop_12                
    191.     bcf PORTB,2                    
    192.     bcf PORTB,3                    
    193.     movlw .8                    
    194.     movwf counter_1                
    195. loop_13                            
    196.     call delay_2                
    197.     decfsz counter_1,f            
    198.     goto loop_13                
    199.     decfsz counter_2,f            
    200.     goto loop_11              
    201.     retfie                  
    202. ;********* end of sub-routinne of interrupt *********
    203. ;********* end of sub-routinnes *********
    204.     end                            ;
    205. ;================== end of programm ==================
    /solved o_O
     
  8. JohnInTX

    Moderator

    Jun 26, 2012
    2,346
    1,029
    Nothing succeeds like success. Well done and congratulations on your high marks!

    If you would like to take the next step and explore ways to make it even better, let us know.
     
  9. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,648
    764
    Hola John,

    Dumb delay. On line delay?
     
    JohnInTX likes this.
  10. Cyrenaica —

    Thread Starter New Member

    Jun 7, 2015
    16
    2
    yes , sure ! i am interested in this ! ! please tell me :)

    as i suppose now , we can succesfully complete the task with traffic light by 2 ways: 1) linear algorythm ( like i have done it before , see top picture in pdf-file ) - simple way ; 2) parallel algorythm with modification of " status word " , which choosing which way (route ) the programm will go next time ( see bottom picture in pdf-file ). this way was recommended by my lecturer as alternative , but i have rejected this idea it cause we really havent examined how to do it properly .

    if its possible , then how to improve algorythm further ?

    Mod note: Reduced file size
     
    Last edited by a moderator: Dec 12, 2015
  11. JohnInTX

    Moderator

    Jun 26, 2012
    2,346
    1,029
    I like what your lecturer has provided in the second page, it is the basis of a finite state machine. The 'status word' is the state indicator. I use them all the time for things like this and PICs are particularly good at them. So... where to start?

    First, a little clean up:
    Instead of explicitly calling out IO in the code flow, do it in subroutines with useful names. Your lights can only have one meaning at a time so have one subroutine per meaning i.e. MainStreetGREEN_CrossStreetRED. The same with any inputs. Rather than asking is PORTA,2 low, ask has the button been pressed? The general rule is to keep your main code as minimal as possible. The code snippet below shows how I would collect the IO initialization and unique light patterns into their own routines. Personally, I put all IO into its own file and INCLUDE "IO.inc". If you look at the resulting code, its easier to read and see what's going on. This idea of separating the program's logic flow from the peripheral actions is important when you get into more complex things, have to relocate pins or - as we shall see - find out that the IO doesn't always behave like it should.

    Code (Microchip Assembler):
    1. ; Breaking out the IO. First, collect all IO - including the initialization - into
    2. ; one place (I would recommend a second file called IO.inc)
    3. ;************** INIT IO  ********************
    4. ; Set up all IO for the system
    5. initIO:
    6.     banksel PORTA            
    7.     clrf PORTA            
    8.     movlw 0x07              
    9.     movwf CMCON            
    10.     banksel TRISA          
    11.     movlw b'00010000'        
    12.     movwf TRISA              
    13.     banksel PORTB          
    14.     clrf PORTB                
    15.     banksel TRISB          
    16.     movlw b'11000000'        
    17.     movwf TRISB
    18.     return
    19.  
    20. ; Each light pattern gets its own subroutine
    21. ;*******************************
    22. MainStreetGREEN_CrossStreetRED:
    23.     bsf PORTB,0                  
    24.     bsf PORTB,5                  
    25.     bcf PORTB,2                  
    26.     bcf PORTB,3                  
    27.     bcf PORTB,1
    28.     return
    29.  
    30.  
    31. ;-------------------------
    32. ; Now in main, THIS:
    33. ;***********************************
    34.  
    35.     banksel PORTA            
    36.     clrf PORTA            
    37.     movlw 0x07              
    38.     movwf CMCON            
    39.     banksel TRISA          
    40.     movlw b'00010000'        
    41.     movwf TRISA              
    42.     banksel PORTB          
    43.     clrf PORTB                
    44.     banksel TRISB          
    45.     movlw b'11000000'        
    46.     movwf TRISB
    47.  
    48.     banksel OPTION_REG      
    49.     movlw b'11010111'        
    50.     movwf OPTION_REG      
    51.     banksel TMR0          
    52.     movlw .0              
    53.     movwf TMR0
    54.  
    55.  
    56. ;becomes THIS:
    57.     call initIO        ; init system IO
    58.  
    59.     banksel OPTION_REG      
    60.     movlw b'11010111'        
    61.     movwf OPTION_REG      
    62.     banksel TMR0          
    63.     movlw .0              
    64.     movwf TMR0
    65.  
    66.  
    67. ; and THIS:
    68. ;**********************************
    69. loop_5                          
    70.     call delay_1              
    71.     decfsz counter_1,f          
    72.     goto loop_5                
    73.     bsf PORTB,0                  
    74.     bsf PORTB,5                  
    75.     bcf PORTB,2                  
    76.     bcf PORTB,3                  
    77.     bcf PORTB,1
    78.  
    79. ; becomes THIS
    80. loop_5:
    81.     call delay_1              
    82.     decfsz counter_1,f          
    83.     goto loop_5
    84.  
    85.     call MainStreetGREEN_CrossStreetRED
    86.   ...
    87.  
    Things like timer inits should be broken out as well - we'll get to that directly.

    Once we can easily deal with the IO, its time to think about delays. You are using dumb delays that eat up all of the system's resources. Before getting into the state machine, let's fix that.
    We'll use TMR2 to generate periodic interrupts at 10ms intervals. I'll let you give that a try yourself. Select values for the prescaler, PR2 and postscaler to generate interrupts at 10msec intervals. For now, just clear TMR2IF when its interrupted and return to the code. See the datasheet for the 628A to see how to write a basic interrupt code. If you have a scope, pulse a spare output line to confirm you have 10msec. We then will have a system tick that we can use to create other timers. As in the IO, I would put the timer init code in its own routine (initSYSTIK). This code should do everything BUT enabling GIE. Enable GIE as the last thing after ALL inits (IO, Timers and whatever).

    When done with these two things, we will have the tools to move on to a state-driven real time system, one that is applicable to many other tasks.
    Baby steps for now.

    Have fun.

    BTW: Since this is a school project you might not be up for a lot of changes at this time. If that's the case, you don't have to do any of the actual coding, just keep it in mind for the next one :)
     
    Last edited: Dec 12, 2015
    atferrari likes this.
Loading...