conversion


Closed Thread
Results 1 to 3 of 3

Thread: conversion

  1. #1
    Join Date
    Sep 2005
    Location
    delhi
    Posts
    14

    Default conversion

    Hi,
    is it possible to start a thread where conversions can be done,programmes written in other language.
    can somebody convert attached code from microchipc.com and explain the working:
    i want to generate software pwm for push pull operation as well as do some other works like writing on lcd.
    thanks
    pramod
    Attached Files Attached Files

  2. #2
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Converting most C programs over to PBP is a fairly simple process. Here's a converted version with blinkng LEDs to indicate which task is currently being run. Change timing to suit whatever osc speed you use.

    I left most of the C code in place for reference, and bumped task0 up to 100 ticks so you can actually see the task0 LED blinking.
    Code:
    ' Conversion from C to BASIC
    '//multitasking system – handle multiple tasks with one microprocessor
    
    DEFINE OSC 4        ' Adjust this & TMR1 values for your osc freq
    DEFINE LOADER_USED 1
    DEFINE INTHAND ISR
    
    'Variables for saving state in interrupt handler
    wsave	VAR	BYTE $70 system		' Saves W
    ssave	VAR	BYTE bank0 system	' Saves STATUS
    psave	VAR	BYTE bank0 system	' Saves PCLATH
    fsave	VAR	BYTE bank0 system	' Saves FSR
    
    '//task counters used to tell when a task is ready to be executed
    '//all these counters are incremented every time a 500us interrupt happens
    '//every task has its own counter that is updated every time a 500us interrupt happens
    'unsigned int task0_counter=0;
    task0_counter VAR BYTE
    task0_counter = 0
    'unsigned int task1_counter=0;
    task1_counter VAR WORD
    task1_counter = 0
    'unsigned int task2_counter=0;
    task2_counter VAR WORD
    task2_counter = 0
    
    FALSE CON 0
    TRUE CON 1
    
    '//this tells when a task is going to happen again
    '//for example, when task0_counter==TASK0_COUNTER_MAX, set task0_counter=0 and do task
    '#define TASK0_COUNTER_MAX 1         //high frequency task – every 500us, maybe PWM
    '#define TASK1_COUNTER_MAX 2000      //low frequency task – every 1000ms
    '#define TASK2_COUNTER_MAX 5000      //low frequency and low priority task, every 2500ms
    TASK2_COUNTER_MAX CON 5000
    TASK1_COUNTER_MAX CON 2000
    TASK0_COUNTER_MAX CON 100
    
    '#define TICKS_BETWEEN_INTERRUPTS 2000
    '#define INTERRUPT_OVERHEAD 19
    '#define TMR1RESET (0xFFFF-(TICKS_BETWEEN_INTERRUPTS-INTERRUPT_OVERHEAD))
    '#define TMR1RESET_HIGH TMR1RESET >> 8
    '#define TMR1RESET_LOW TMR1RESET & 0xFF
    TICKS_BETWEEN_INTERRUPTS CON 2000
    INTERRUPT_OVERHEAD CON 19
    INTER CON  TICKS_BETWEEN_INTERRUPTS - INTERRUPT_OVERHEAD
    TMR1RESET CON $FFFF-INTER '$FFFF-(TICKS_BETWEEN_INTERRUPTS-INTERRUPT_OVERHEAD)
    TMR1RESET_HIGH CON TMR1RESET >> 8
    TMR1RESET_LOW CON TMR1RESET & $FF
    
    '//this enables/disables a task
    'volatile unsigned char task0_enable=TRUE;
    'volatile unsigned char task1_enable=TRUE;
    'volatile unsigned char task2_enable=TRUE;
    '//this allows tasks triggered by interrupt to run in the background in main()
    'volatile unsigned char task2_go=FALSE;
    task0_enable VAR BIT
    task0_enable = TRUE
    task1_enable VAR BIT
    task1_enable = TRUE
    task2_enable VAR BIT
    task2_enable = TRUE
    task2_go VAR BIT
    task2_go = FALSE
    
    SYMBOL TMR1ON = T1CON.0
    SYMBOL TMR1IF = PIR1.0
    SYMBOL TMR1IE = PIE1.0
    SYMBOL TMR1CS = T1CON.1
    SYMBOL T1CKPS0 = T1CON.4
    SYMBOL T1CKPS1 = T1CON.5
    SYMBOL PEIE = INTCON.6
    SYMBOL GIE = INTCON.7
    
    PORTB = 0
    TRISB = 0
    
    GOTO Main
    
    setup_multitasking:
    'void setup_multitasking(void)
    '{
    '   //set up tmr1  to interrupt every 500us
        TMR1CS=0;
        T1CKPS0=0;
        T1CKPS1=0;
    '/*We want to wait 2000 clock cycles, or 500us @ 16MHz (instructions are 1/4 speed of clock).  Timer 1 interrupts when it gets to 0xFFFF or 65535.  Therefore, we set timer 1 to 65535 minus 2000 = 63535, then wait 2000 ticks until rollover at 65535.  To test, use simulator to find that its exactly correct*/
    '   #define  TICKS_BETWEEN_INTERRUPTS      2000
    '   #define  INTERRUPT_OVERHEAD            19
    '   #define TMR1RESET (0xFFFF-(TICKS_BETWEEN_INTERRUPTS-INTERRUPT_OVERHEAD))
    '   #define TMR1RESET_HIGH TMR1RESET >> 8
    '   #define TMR1RESET_LOW TMR1RESET & 0xFF
        TMR1ON=0;
        TMR1H = TMR1RESET_HIGH
        TMR1L = TMR1RESET_LOW
        TMR1ON=1;
        TMR1IF=0;
        TMR1IE=1;
        PEIE=1;
        GIE=1;
    '}
        RETURN
    
    ASM
    ISR     ; NOTE: If you're using BASIC in this ISR, then you may need to save
            ; some PBP system vars. Look for Darrel Taylors examples here in the forum.
            
            ; Uncomment the following if the device has less than 2k of code space
    		;movwf	wsave			; Save W
    		;swapf	STATUS, W		; Swap STATUS to W (swap avoids changing STATUS)
    		;clrf	STATUS			; Clear STATUS
    		;movwf	ssave			; Save swapped STATUS
    		;movf	PCLATH, W		; Move PCLATH to W
    		;movwf	psave			; Save PCLATH
    
    ; Save the FSR value for later	
    		movf	FSR, W			; Move FSR to W
    		movwf	fsave			; Save FSR
    ENDASM
    
    'void interrupt isr(void)
    '{
    '   //one tick every 500us at 16Mhz
        IF TMR1IF THEN 'if (TMR1IF)
    '   {
    '   //set up timer 1 again to interrupt 500us in future
        TMR1IF=0;
        TMR1ON=0;
        TMR1H=TMR1RESET_HIGH;
        TMR1L=TMR1RESET_LOW;
        TMR1ON=1;
          task0_counter = task0_counter +1 'task0_counter++;
          if (task0_counter>=TASK0_COUNTER_MAX) THEN ' //high frequency task – every 1 tick
    '      {
                task0_counter=0;
                if (task0_enable==TRUE) THEN
    '            {
    '                  //do high frequency important task 0, for example PWM
                        TOGGLE 0 ' Toggle PORTB.0
    '            }
                ENDIF
    '      }
          ENDIF
          task1_counter = task1_counter + 1 'task1_counter++;
          if (task1_counter>=TASK1_COUNTER_MAX) THEN ' //low priority task - every 2000 ticks
    '      {
                 task1_counter=0;
                 if (task1_enable==TRUE) THEN
    '            {
    '                  //do low frequency yet important task 1
                        TOGGLE 1 ' Toggle PORTB.1
    '            }
                 ENDIF
    '      }
          ENDIF
          
    '/*this task takes a long time, 100ms for example, lots of maths.  Is extremely low priority, but has to be done at regular intervals, so all this does is trigger it.  In main(), it will, at leisure, poll ‘task2_go’ and then execute it in the background.*/
           task2_counter = task2_counter + 1 'task2_counter++;
          if (task2_counter>=TASK2_COUNTER_MAX) THEN ' //every 250ms
    '      {
               task2_counter=0;
               if (task2_enable==TRUE) THEN
    '          {
                   TOGGLE 2 ' Toggle PORTB.2
    ' //every 250ms take 100ms to do maths, do this in main() so the we can get back to doing the high frequency tasks.
                   task2_go=TRUE;
    '          }
               ENDIF
    '      }
          ENDIF
    '    }  //if (TMR1IF)
    '} //interrupt routine
      ENDIF
     		
    ASM
    ; Restore FSR, PCLATH, STATUS and W registers
    finished
    		movf	fsave, W		; retrieve FSR value
    		movwf	FSR				; Restore it to FSR
    		movf	psave, W		; Retrieve PCLATH value
    		movwf	PCLATH			; Restore it to PCLATH
    		swapf	ssave, W		; Retrieve the swapped STATUS value (swap to avoid changing STATUS)
    		movwf	STATUS			; Restore it to STATUS
    		swapf	wsave, F		; Swap the stored W value
    		swapf	wsave, W		; Restore it to W (swap to avoid changing STATUS)
    		retfie					; Return from the interrupt
    EndAsm
    
    Main:
    'main()
    '{
        'setup_multitasking();
         GOSUB setup_multitasking:
    
    Idle:
          if (task2_go==TRUE) THEN
             task2_go=FALSE;
          ENDIF
          GOTO Idle
    '            //take our time, doing heaps of complex maths at our leisure in the background
    '      }
    '   }
    '}
    END
    Look for some of Darrel Taylors (or Tim Box) interrupt saving routines here in the forum if you're using BASIC commands with assembler interrupts.

    Depending on which PBP commands you use, you'll most likely need to save some PBP system variables.

    I suspect this would also work fine with ON INTERRUPT, but I hate using it.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  3. #3
    Join Date
    Sep 2005
    Location
    delhi
    Posts
    14


    Did you find this post helpful? Yes | No

    Smile Thanks From Inner Core Of Heart

    Quote Originally Posted by Bruce
    Converting most C programs over to PBP is a fairly simple process. Here's a converted version with blinkng LEDs to indicate which task is currently being run. Change timing to suit whatever osc speed you use.

    I left most of the C code in place for reference, and bumped task0 up to 100 ticks so you can actually see the task0 LED blinking.
    Code:
    ' Conversion from C to BASIC
    '//multitasking system – handle multiple tasks with one microprocessor
    
    DEFINE OSC 4        ' Adjust this & TMR1 values for your osc freq
    DEFINE LOADER_USED 1
    DEFINE INTHAND ISR
    
    'Variables for saving state in interrupt handler
    wsave	VAR	BYTE $70 system		' Saves W
    ssave	VAR	BYTE bank0 system	' Saves STATUS
    psave	VAR	BYTE bank0 system	' Saves PCLATH
    fsave	VAR	BYTE bank0 system	' Saves FSR
    
    '//task counters used to tell when a task is ready to be executed
    '//all these counters are incremented every time a 500us interrupt happens
    '//every task has its own counter that is updated every time a 500us interrupt happens
    'unsigned int task0_counter=0;
    task0_counter VAR BYTE
    task0_counter = 0
    'unsigned int task1_counter=0;
    task1_counter VAR WORD
    task1_counter = 0
    'unsigned int task2_counter=0;
    task2_counter VAR WORD
    task2_counter = 0
    
    FALSE CON 0
    TRUE CON 1
    
    '//this tells when a task is going to happen again
    '//for example, when task0_counter==TASK0_COUNTER_MAX, set task0_counter=0 and do task
    '#define TASK0_COUNTER_MAX 1         //high frequency task – every 500us, maybe PWM
    '#define TASK1_COUNTER_MAX 2000      //low frequency task – every 1000ms
    '#define TASK2_COUNTER_MAX 5000      //low frequency and low priority task, every 2500ms
    TASK2_COUNTER_MAX CON 5000
    TASK1_COUNTER_MAX CON 2000
    TASK0_COUNTER_MAX CON 100
    
    '#define TICKS_BETWEEN_INTERRUPTS 2000
    '#define INTERRUPT_OVERHEAD 19
    '#define TMR1RESET (0xFFFF-(TICKS_BETWEEN_INTERRUPTS-INTERRUPT_OVERHEAD))
    '#define TMR1RESET_HIGH TMR1RESET >> 8
    '#define TMR1RESET_LOW TMR1RESET & 0xFF
    TICKS_BETWEEN_INTERRUPTS CON 2000
    INTERRUPT_OVERHEAD CON 19
    INTER CON  TICKS_BETWEEN_INTERRUPTS - INTERRUPT_OVERHEAD
    TMR1RESET CON $FFFF-INTER '$FFFF-(TICKS_BETWEEN_INTERRUPTS-INTERRUPT_OVERHEAD)
    TMR1RESET_HIGH CON TMR1RESET >> 8
    TMR1RESET_LOW CON TMR1RESET & $FF
    
    '//this enables/disables a task
    'volatile unsigned char task0_enable=TRUE;
    'volatile unsigned char task1_enable=TRUE;
    'volatile unsigned char task2_enable=TRUE;
    '//this allows tasks triggered by interrupt to run in the background in main()
    'volatile unsigned char task2_go=FALSE;
    task0_enable VAR BIT
    task0_enable = TRUE
    task1_enable VAR BIT
    task1_enable = TRUE
    task2_enable VAR BIT
    task2_enable = TRUE
    task2_go VAR BIT
    task2_go = FALSE
    
    SYMBOL TMR1ON = T1CON.0
    SYMBOL TMR1IF = PIR1.0
    SYMBOL TMR1IE = PIE1.0
    SYMBOL TMR1CS = T1CON.1
    SYMBOL T1CKPS0 = T1CON.4
    SYMBOL T1CKPS1 = T1CON.5
    SYMBOL PEIE = INTCON.6
    SYMBOL GIE = INTCON.7
    
    PORTB = 0
    TRISB = 0
    
    GOTO Main
    
    setup_multitasking:
    'void setup_multitasking(void)
    '{
    '   //set up tmr1  to interrupt every 500us
        TMR1CS=0;
        T1CKPS0=0;
        T1CKPS1=0;
    '/*We want to wait 2000 clock cycles, or 500us @ 16MHz (instructions are 1/4 speed of clock).  Timer 1 interrupts when it gets to 0xFFFF or 65535.  Therefore, we set timer 1 to 65535 minus 2000 = 63535, then wait 2000 ticks until rollover at 65535.  To test, use simulator to find that its exactly correct*/
    '   #define  TICKS_BETWEEN_INTERRUPTS      2000
    '   #define  INTERRUPT_OVERHEAD            19
    '   #define TMR1RESET (0xFFFF-(TICKS_BETWEEN_INTERRUPTS-INTERRUPT_OVERHEAD))
    '   #define TMR1RESET_HIGH TMR1RESET >> 8
    '   #define TMR1RESET_LOW TMR1RESET & 0xFF
        TMR1ON=0;
        TMR1H = TMR1RESET_HIGH
        TMR1L = TMR1RESET_LOW
        TMR1ON=1;
        TMR1IF=0;
        TMR1IE=1;
        PEIE=1;
        GIE=1;
    '}
        RETURN
    
    ASM
    ISR     ; NOTE: If you're using BASIC in this ISR, then you may need to save
            ; some PBP system vars. Look for Darrel Taylors examples here in the forum.
            
            ; Uncomment the following if the device has less than 2k of code space
    		;movwf	wsave			; Save W
    		;swapf	STATUS, W		; Swap STATUS to W (swap avoids changing STATUS)
    		;clrf	STATUS			; Clear STATUS
    		;movwf	ssave			; Save swapped STATUS
    		;movf	PCLATH, W		; Move PCLATH to W
    		;movwf	psave			; Save PCLATH
    
    ; Save the FSR value for later	
    		movf	FSR, W			; Move FSR to W
    		movwf	fsave			; Save FSR
    ENDASM
    
    'void interrupt isr(void)
    '{
    '   //one tick every 500us at 16Mhz
        IF TMR1IF THEN 'if (TMR1IF)
    '   {
    '   //set up timer 1 again to interrupt 500us in future
        TMR1IF=0;
        TMR1ON=0;
        TMR1H=TMR1RESET_HIGH;
        TMR1L=TMR1RESET_LOW;
        TMR1ON=1;
          task0_counter = task0_counter +1 'task0_counter++;
          if (task0_counter>=TASK0_COUNTER_MAX) THEN ' //high frequency task – every 1 tick
    '      {
                task0_counter=0;
                if (task0_enable==TRUE) THEN
    '            {
    '                  //do high frequency important task 0, for example PWM
                        TOGGLE 0 ' Toggle PORTB.0
    '            }
                ENDIF
    '      }
          ENDIF
          task1_counter = task1_counter + 1 'task1_counter++;
          if (task1_counter>=TASK1_COUNTER_MAX) THEN ' //low priority task - every 2000 ticks
    '      {
                 task1_counter=0;
                 if (task1_enable==TRUE) THEN
    '            {
    '                  //do low frequency yet important task 1
                        TOGGLE 1 ' Toggle PORTB.1
    '            }
                 ENDIF
    '      }
          ENDIF
          
    '/*this task takes a long time, 100ms for example, lots of maths.  Is extremely low priority, but has to be done at regular intervals, so all this does is trigger it.  In main(), it will, at leisure, poll ‘task2_go’ and then execute it in the background.*/
           task2_counter = task2_counter + 1 'task2_counter++;
          if (task2_counter>=TASK2_COUNTER_MAX) THEN ' //every 250ms
    '      {
               task2_counter=0;
               if (task2_enable==TRUE) THEN
    '          {
                   TOGGLE 2 ' Toggle PORTB.2
    ' //every 250ms take 100ms to do maths, do this in main() so the we can get back to doing the high frequency tasks.
                   task2_go=TRUE;
    '          }
               ENDIF
    '      }
          ENDIF
    '    }  //if (TMR1IF)
    '} //interrupt routine
      ENDIF
     		
    ASM
    ; Restore FSR, PCLATH, STATUS and W registers
    finished
    		movf	fsave, W		; retrieve FSR value
    		movwf	FSR				; Restore it to FSR
    		movf	psave, W		; Retrieve PCLATH value
    		movwf	PCLATH			; Restore it to PCLATH
    		swapf	ssave, W		; Retrieve the swapped STATUS value (swap to avoid changing STATUS)
    		movwf	STATUS			; Restore it to STATUS
    		swapf	wsave, F		; Swap the stored W value
    		swapf	wsave, W		; Restore it to W (swap to avoid changing STATUS)
    		retfie					; Return from the interrupt
    EndAsm
    
    Main:
    'main()
    '{
        'setup_multitasking();
         GOSUB setup_multitasking:
    
    Idle:
          if (task2_go==TRUE) THEN
             task2_go=FALSE;
          ENDIF
          GOTO Idle
    '            //take our time, doing heaps of complex maths at our leisure in the background
    '      }
    '   }
    '}
    END
    Look for some of Darrel Taylors (or Tim Box) interrupt saving routines here in the forum if you're using BASIC commands with assembler interrupts.

    Depending on which PBP commands you use, you'll most likely need to save some PBP system variables.

    I suspect this would also work fine with ON INTERRUPT, but I hate using it.
    THANKS A LOT BRUCE


    THANKS BRUCE,
    I AM GOING THROUGH YOUR SUGGESTIONS AND HOPE THIS WOULD HELP
    TOO MANY PICKERS WHO WISH TO IMPLEMENT MULTITASKING IN THEIR PROJECTS.
    I AM A LEARNER AND I WILL DO SOME EXPERIMENTS WITH YOUR ADVICE.
    THANKS AGAIN
    REGARDS
    PRAMOD

Similar Threads

  1. A/D conversion with PIC18F67J50
    By ScaleRobotics in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 8th May 2009, 01:48
  2. A/D conversion problem in 18F2520, 2523, 2550 etc.
    By selimkara in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 10th March 2008, 16:26
  3. A/D conversion problem on 18F4431
    By ttease in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 10th April 2007, 23:03
  4. Help for decimal conversion
    By eva in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 15th March 2007, 18:20
  5. Strange A/D conversion...
    By Christos_K in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 5th June 2005, 01:35

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts