Learning to program the PIC10LF322

Discussion in 'Embedded Systems and Microcontrollers' started by cmartinez, Jul 6, 2018.

  1. JohnInTX

    Moderator

    Jun 26, 2012
    3,370
    1,695
    Yeah, do that. I'd be interested in what happens.
     
  2. MaxHeadRoom

    Expert

    Jul 18, 2013
    16,385
    4,819
    PR2 Timer2 is also used for the period register when using PWM.
    Max,
     
    cmartinez and JohnInTX like this.
  3. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    I'm getting there, Max ... baby steps! ... Emoji Smiley-64.png ...
     
  4. MaxHeadRoom

    Expert

    Jul 18, 2013
    16,385
    4,819
    My theory is that two timers were made available for this chip, and Picmicro appear to try and keep thing standard across different versions as much as possible, and a PWM module is present so the usual PR2/TMR2 was included because of this.
    TMR1 lost the cut.
    Max.
     
    cmartinez likes this.
  5. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    This is the closest approximation for an interrupt period for Timer2 that I could find:

    ;PR2 = 8D <- Timer2 compare and interrupt trigger value
    ;T2CKPS = 64D <- prescaling factor, 1:1 to 1:64
    ;TOUTPS = 15D <- postscaling factor, 1:1 to 1:16

    That would result in: 8 * 64 * 15 / (31,000/4) = 0.99097 seconds ... which is perfectly alright, because the service routine itself will eat up more cycles, plus the 1/10 of a second that the LED will flash before completing the routine.... I'll just work with these parameters for now, and refine them later.

    Question, I get that the normal syntax for hex numbers is 0x050 (or 50H if I'm not mistaken), for instance. and for binary is b'00000000' ... what would be the most common convention for the different formats? Can I write decimal 12 as 12D, instead of d'12' or .12 ?
     
  6. JohnInTX

    Moderator

    Jun 26, 2012
    3,370
    1,695
    I prefer .12 myself.. easier to type and reads better IMHO
     
    cmartinez likes this.
  7. jpanhalt

    Expert

    Jan 18, 2008
    6,449
    1,251
    I used zero for PR2 just to see how it worked in a recent project. It worked and gave a very short period limited by the steps it took to recognize it as zero. It is not like, say, decfsz , which if you start at zero, counts all the way around back to zero.
     
    cmartinez and JohnInTX like this.
  8. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    HELP! ... I'm trying to figure out how to complement a bit in a register in the PIC architecture ... but I'm trapped by my 8051 mentality and can't get out! ...

    Mainly, I'd like to toggle the RA1 pin on and off
     
  9. jpanhalt

    Expert

    Jan 18, 2008
    6,449
    1,251
    Try xor'ing it. That is , 0x01 xor 0x01 = 0, xor w/ 0x01 = 1 ...

    Very often used to flash LED's or switch anything alternating with a delay in between.

    You will use xorlw or xorwf depending on your code.

    Of course xor w/ 0x01 only affects bit zero.

    John
     
  10. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    I know what an XOR does ... but would you mind being more specific? I'm suffering from complete mental block right now ...
     
  11. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    Ok... would this work?

    Code (Text):
    1.  
    2.                movf LATA, 0      ;load the contents of LATA into W
    3.                xorlw b'00000010' ;perform an exclusive or on the contents of W, filtering
    4.                                  ;bit1 (LATA1)
    5.                movwf LATA        ;load the contents of W into LATA
     
  12. jpanhalt

    Expert

    Jan 18, 2008
    6,449
    1,251
    Saves a step:
    Code (Text):
    1.  
    2. movlw     0x01      
    3. xorwf     LATA,f         ;pulses LED  (i.e., LATA, 1)
    4.  
     
    cmartinez likes this.
  13. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    why "xorwf LATA, f" instead of "xorwf LATA, 1" ? is it the same thing in PIC syntax?
     
  14. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    Here's the complete code for my first attempt. It already went through the compiler, reporting no errors.

    Code (Text):
    1.  
    2. ;*****************************************************************************************
    3. ;                                  11 JUL 2018, 12:39:15 PM:
    4. ;                           Generator controller for the PIC10LF322
    5. ;     The following program flashes a LED connected at RA1 for 0.1s once per second using
    6. ;    the Timer interrupt feature. Internal oscillator is set at 31 KHz
    7. ;    
    8. ;*****************************************************************************************
    9.  
    10.        list          p=PIC10LF322                ;list directive to define processor
    11.        #include      p10lf322.inc                ;processor specific variable definitions
    12.        radix         dec
    13.  
    14.        ; - Flash memory self-write protection off     (default state)
    15.        ; - Brown-out reset low trip point is selected (default state)
    16.        ; - Low-power Brown-out Reset is enabled       (default state)
    17.        ; - High Voltage on MCLR pin must be used for programming
    18.        ; - Program memory code protection disabled    (default state)
    19.        ; - MCLR pin set as digital input
    20.        ; - Power-up Timer disabled                    (default state)
    21.        ; - Watchdog timer disabled
    22.        ; - Brown-out reset is enabled                 (default state)
    23.        ; - Internal oscillator is activated
    24.        
    25.        __CONFIG _LVP_OFF & _MCLRE_OFF & _WDTE_OFF & _FOSC_INTOSC
    26.  
    27.  
    28. ; in this architecture, general purpose registers are located in addresses 40H through 7FH
    29. TEMPVAR EQU 40H                    ;TEMPVAR creates a direct reference to memory location 40H
    30.  
    31. ;*****************************************************************************************
    32. ;                       Reset and Interrupt program memory locations
    33. ;*****************************************************************************************
    34. RESET_VECTOR: ORG    0x000                       ;processor reset vector
    35.               goto Init                          ;go to beginning of program
    36.  
    37. INT_VECTOR:   ORG    0x004                       ;interrupt vector location
    38.                ;clear the Timer2 to PR2 match interrupt flag
    39.                bcf PIR1, TMR2IF
    40.                
    41.                ;complement RA1's state, effectively turning on the LED for 1 second
    42.                ;and off for another second
    43.                movlw b'00000010' ;load W with a filter
    44.                xorwf LATA, 1     ;perform an exclusive or on the contents of W, filtering
    45.                                  ;bit1 (LATA1) ... if LATA1 was zero, it will be set as
    46.                                  ;one, if LATA1 was one, it will be set as zero ... all of
    47.                                  ;the other bits will remain unafected
    48.                
    49.        retfie ;return from interrupt
    50.  
    51. ;*****************************************************************************************
    52. ;                                   Main program start
    53. ;*****************************************************************************************
    54. Init:
    55.  
    56.        ;the reference Clock output bit CLKROE is disabled by default, we'll leave it that way
    57.        ;set the internal oscillator frequency to 31 KHz (the lowest possible), this is done
    58.        ;by clearing the IRCF bits, which belong in bit locations 4, 5 and 6, respecively
    59.  
    60.        movlw b'10001111'  ;the W register has been loaded with the IRCF bits as zeroes
    61.        andwf OSCCON, f    ;AND the W register with OSCCON, storing the result in OSCCON
    62.  
    63.        clrf   INTCON      ;make sure that all interrupts are disabled for now
    64.  
    65. ;************************************* I/O definitions ***********************************
    66.        CLRF ANSELA       ;clear the analog select register, which for some stupid reason
    67.                          ;is enabled by default ... otherwise the digital i/o function
    68.                          ;won't work
    69.                          
    70.        
    71.        ;BANKSEL PORTA  ;this instruction is not necessary with the 10LF322, since it only
    72.        ;has one bank of SFRs
    73.  
    74.        ;set all pin outputs as zeroes (low), to prevent the LED from starting up already
    75.        ;lit before enabling the timer interrupt function
    76.        movlw b'00000000'
    77.        movwf LATA
    78.  
    79.        ; - set RA1 as an output, active high ... leave RA0 and RA2 as inputs ... RA3 can
    80.        ;   ONLY be an input
    81.        ;10 JUL 2018, 5:57:17 PM: By the advice of JohnInTx a complete movwf to TRISA should
    82.        ;be used, instead of writing to the individual TRISAX bits
    83.        movlw b'00001101'
    84.        movwf TRISA
    85.        
    86.        ;Interrupt period is given by: PR2 * T2CKPS * TOUTPS / (Fosc/4)
    87.        ;to get a period of one second, the following values make for the best approximation:
    88.        ;Remember that the clock input for the timers is Fosc/4, in this case 31 KHz/4 = 7.75 KHz
    89.        ;PR2    =  8D <- Timer2 compare and interrupt trigger value
    90.        ;T2CKPS = 64D <- prescaling factor, 1:1 to 1:64
    91.        ;TOUTPS = 15D <- postscaling factor, 1:1 to 1:16
    92.  
    93.        movlw d'8'
    94.        movwf PR2
    95.        
    96.        ;check the structure of T2CON to understand the following instruction
    97.        movlw b'01110011'
    98.        movwf T2CON
    99.        
    100.        ;enable Timer2 to match PR2 interrupt
    101.        bsf PIE1, TMR2IE
    102.        
    103.        ;enable all active peripheral interrupts
    104.        bsf INTCON, PEIE
    105.  
    106.        ;enable all active interrupts
    107.        bsf INTCON, GIE
    108.        
    109.        ;turn Timer2 On
    110.        bsf T2CON, TMR2ON
    111.  
    112. ProgramLoop:
    113.        goto $
    114.  
    115.  END
     
  15. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    :eek: IT WORKS!!!! ... and on my very first attempt! :) ...

    ... that felt kind of weird ... :confused: ... guess I'm too used to banging my head against the wall whenever I try to make something work for the first time ... :(
     
  16. jpanhalt

    Expert

    Jan 18, 2008
    6,449
    1,251
    Because the bit being affected is defined by 0x01. You need the destination as there are two possibilities, W and F (see below). I used to use 1 and 0 for my destinations of F and W, respectively, but learned from the excellent examples here not to do that. I still have the bad habit of using lower case f and w, but I am trying to fix that. It is just so easy to avoid the upper case.

    upload_2018-7-11_18-9-47.png

    Edit: Nothing feels better than getting code that works! Good for you.

    John
     
    cmartinez likes this.
  17. JohnInTX

    Moderator

    Jun 26, 2012
    3,370
    1,695
    Nice!
    Now, its time to do the proper context save in the interrupt routine.

    Agree with @japhnalt on the destination specifier. Use F or W always, (I like upper case) and never just accept the default destination (F). If you do, you'll get a warning that you'll be tempted to ignore or suppress - then when you make a REAL destination mistake, it will be a lot harder to find e.g. 'Many of these use the default destination of F. One is wrong. Your job-find it' Better to be explicit and let MPASM warn you when you goof.
     
    cmartinez likes this.
  18. JohnInTX

    Moderator

    Jun 26, 2012
    3,370
    1,695
    Typical midrange context save code:
    Code (Microchip Assembler):
    1.      
    2.       ; Saves W common area or replicated banked RAM as necessary
    3.       ; Saves status and PCLATH in banked context save RAM
    4.           ; Polls sources and goes to routine
    5.           ; IRQ routines come back to IRQreturn
    6.  
    7.           movwf   IRQsaveW      ; save W reg, in common area if available
    8.                 ; iff not available, replicate IRQsaveW in each bank
    9.                 ; for banked systems
    10.  
    11.           swapf   STATUS,W      ; get status reg without changing flags
    12.  
    13.           banksel IRQsaveS      ; save it in context bank
    14.           movwf   IRQsaveS
    15.  
    16. ; Saving PCLATH is necessary only when multiple ROM banks are used
    17.       movf      PCLATH,W    ; save upper address as req'd
    18.       movwf   IRQsavePCLATH
    19. ; set PCLATH to point to service routines
    20.       pagesel svcTMR2 ; better way to do it
    21.  
    22.  
    23.           ;******************************************************
    24.           ; Check flags and exit iff none set, else, do em again
    25.           ;  without running foreground (just burns overhead)
    26.  
    27.           btfss   PIE1,TMR2IE   ; Timer 2 irq enabled?
    28.           goto    chkNext       ; nope (can omit iff you never turn TMR2 off)
    29.  
    30.           btfsc   PIR1,TMR2IF   ; Timer 2 needs service?
    31.           goto    svcTMR2       ; Jump instead of call to save stack space
    32.  
    33.           ;************************
    34.           ; Check other IRQ sources as required
    35. chkNext:
    36.  
    37.       ;*********************************
    38.           ; Service routines jump back here
    39. IRQreturn:
    40.           banksel IRQsaveS        ; locate saved context
    41.  
    42.           movf    IRQ_PCLATH,W    ; restore upper address (iff used)
    43.           movwf   PCLATH  ; NO more calls or gotos after this..
    44.  
    45.           swapf   IRQsaveS,W      ; get saved status
    46.           movwf   STATUS          ; now.. we are in the original banks
    47.  
    48.           swapf   IRQsaveW,F      ; get saved W without changing flags
    49.           swapf   IRQsaveW,W
    50.          retfie                   ; return and reenable
    EDIT: used pagesel directive for PCLATH
     
    Last edited: Jul 11, 2018
    cmartinez likes this.
  19. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    I guess I'm too spoiled by the PUSH and POP instructions available in the 8051 ... how is IRQsaveS supposed to be declared?
     
  20. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    5,564
    6,620
    Also, the PIC10 architecture has less instructions than other more advanced chips:

    For instance, there's no pagesel instruction .... nor banksel

    upload_2018-7-11_18-27-36.png
     
Loading...