LED FLASHING RATE CONTROL USING PIC16F684

Thread Starter

Don Omar

Joined May 5, 2017
49
That's just an example excerpt to demonstrate toggling the LED at the end of each half cycle. It can only become a working example if you fill in the missing pieces. Sorry!

The DelayCy() line is a macro call to a cycle-accurate delay sub-subsystem that allows specifying delays in cycles, microseconds, or milliseconds plus or minus 'n' cycles. Just replace it with a call to your own ~1-msec delay function. However, if you're interested, I've included a DelayCy() fixed delay sub-system demo below. The sub-system can be used to produce cycle-accurate delays in your code at almost any clock (4, 8, 16, 20, 32, etc.).

Code:
;******************************************************************
;  DelayCy() Demo, (C)2010, Mike McLaren                          *
;******************************************************************

        cblock 0x70
delayhi                 ; DelayCy() sub-system timing variable
        endc
;==================================================================
;  K8LH DelayCy() subsystem macro generates four instructions     =
;==================================================================
        radix   dec
clock   equ     4               ; 4, 8, 12, 16, 20 (MHz), etc.
usecs   equ     clock/4         ; cycles/microsecond multiplier
msecs   equ     usecs*1000      ; cycles/millisecond multiplier
dloop   equ     5               ; loop size, 5 to ??? cycles
;
;  -- loop --  -- delay range --  -- memory overhead ----------
;  5-cyc loop, 11..327690 cycles,  9 words (+4 each macro call)
;  6-cyc loop, 11..393226 cycles, 10 words (+4 each macro call)
;  7-cyc loop, 11..458762 cycles, 11 words (+4 each macro call)
;  8-cyc loop, 11..524298 cycles, 12 words (+4 each macro call)
;  9-cyc loop, 11..589834 cycles, 13 words (+4 each macro call)
;
DelayCy macro   cycles          ; range, see above
    if (cycles<11)|(cycles>(dloop*65536+10))
        error " DelayCy range error "
    else
        movlw   high((cycles-11)/dloop)+1
        movwf   delayhi
        movlw   low ((cycles-11)/dloop)
        call    uLoop-((cycles-11)%dloop)
    endif
        endm

;******************************************************************
;  example code for simulation testing                            *
;******************************************************************
        org     0x000
SimTest
        DelayCy(20*msecs)       ; <- put simulator PC here
        goto    $               ; <- put simulator break point here

;******************************************************************
;  K8LH DelayCy() subsystem 16-bit 'uLoop' timing subroutine      *
;******************************************************************
a = dloop-1
    while a > 0
        nop                     ; (cycles-11)%dloop entry points  |B0
a -= 1
    endw
uLoop   addlw   -1              ; subtract 'dloop' loop time      |B0
        skpc                    ; borrow? no, skip, else          |B0
        decfsz  delayhi,F       ; done?  yes, skip, else          |B0
        goto    uLoop-dloop+5   ; do another loop                 |B0
        return                  ;                                 |B0

;******************************************************************
        end
Hey dear,
When u say replace the missing parts what do u mean ?
And how many of them?
 

MMcLaren

Joined Feb 14, 2010
861
The same "basic" parts you have in your program; (1) the "list" and "include" directives, (2) configuration settings, (3) variable and constant declarations, (4) program "org" statement, (5) initialization code, (6) the "main loop", which I provided a sample of, and (6) your delay subroutine...

It would be better if you took the time to understand the example and implement something similar in your program rather than simply trying to copy and paste a program together from examples. If you don't understand a piece of the code, ask about it.

The main program loop example I provided is a simple timing loop based on the ADC "duration" reading. At the beginning of each loop you toggle the LED from off to on or from on to off, then burn off the amount of time from the ADC "duration" reading while updating the "duration" and "brightness" variables from the ADC inputs. The "duration" and "brightness" settings are applied at the beginning of each new timing loop.

Code:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  pwm_led.asm  (untested)                                        ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        list P=PIC16F684, R=DEC
        include "p16f684.inc"
        errorlevel -302

__CONFIG _FOSC_INTOSCIO & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF &
          _IESO_OFF & _FCMEN_OFF
;
; _CP_OFF    default
; _CPD_OFF   default
; _BOD_ON    default
;

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  variables                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        cblock  0x20
duration
pwmlevel
ledstate
counter
delayhi                         ; DelayCy() subsystem variable
        endc

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  K8LH DelayCy() subsystem macro generates four instructions     ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        radix dec
clock   equ     4               ; 4, 8, 12, 16, 20 (MHz), etc.
usecs   equ     clock/4         ; cycles/microsecond multiplier
msecs   equ     usecs*1000      ; cycles/millisecond multiplier
dloop   equ     5               ; loop size, 5 to 8 cycles
;
;  -- loop --  -- delay range --  -- memory overhead ----------
;  5-cyc loop, 11..327690 cycles,  9 words (+4 each macro call)
;  6-cyc loop, 11..393226 cycles, 10 words (+4 each macro call)
;  7-cyc loop, 11..458762 cycles, 11 words (+4 each macro call)
;  8-cyc loop, 11..524298 cycles, 12 words (+4 each macro call)
;
DelayCy macro   cycles          ; range, see above
    if (cycles<11)|(cycles>(dloop*65536+10))
        error " DelayCy range error "
    else
        movlw   high((cycles-11)/dloop)+1
        movwf   delayhi
        movlw   low ((cycles-11)/dloop)
        call    uLoop-((cycles-11)%dloop)
    endif
        endm

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  reset vector                                                   ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        org     0x000
v_reset
        clrf    STATUS          ; force bank 0                    |00
        clrf    PORTA           ; initialize PORT A               |00
        clrf    PORTC           ; initialize PORT C               |00
        movlw   0x07            ;                                 |00
        movwf   CMCON0          ; comparators OFF                 |00
;
;  ADC and PWM configuration
;
        bsf     STATUS,RPO      ; bank 1                          |01
        movlw   1<<RA0|1<<RA1   ;                                 |01
        movwf   TRISA           ; RA1..RA0 inputs                 |01
        movwf   ANSEL           ; RA1..RA0 analog                 |01
        movlw   b'01110000'     ; select Frc 500-kHz oscillator   |01
        movwf   ADCON1          ; as ADC clock source             |01
        bcf     TRISC,RA5       ; RA5 output, others inputs       |01
        movlw   0xFF            ;                                 |01
        movwf   PR2             ; PWM period 244Hz                |01

        bcf     STATUS,RP0      ; bank 0                          |00
        bsf     ADCON0,ADON     ; left justify, vdd Vref, AN0, on |00
        movlw   7               ;                                 |00
        movwf   T2CON           ; prescale 16, timer 'on'         |00
        movlw   0x0C            ;                                 |00
        movwf   CCP1CON         ; select active hi PWM mode       |00

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  main loop                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

halfcyc
        incf    duration,W      ; duration, 1..256 msecs          |00
        movwf   counter         ;                                 |00
;
;  toggle LED on or off each half cycle
;
        incf    ledstate,F      ; bump bit 0 LED 'state'          |00
        movf    pwmlevel,W      ; duty cycle, 0..255              |00
        btfss   ledstate,0      ; state 1? yes, skip, else        |00
        movlw   0               ; use 'off' duty cycle value      |00
        movwf   CCPR1L          ; set PWM duty cycle              |00
tmrloop
        movlw   1<<CHS0         ; bit mask for ADCON0.CHS0 bit    |00
        xorwf   ADCON0,F        ; toggle channel (0 or 1)         |00
        DelayCy(1*msecs-20)     ; wait 1-msec minus 20 cycles     |00
;
;  read each ADC channel on alternating 1-msec intervals
;
        bsf     ADCON0,GO       ; start conversion                |00
adcwait btfsc   ADCON0,GO       ; done? yes, skip, else           |00
        goto    adcwait         ; branch (wait)                   |00
        movf    ADRESH,W        ; adc result, 0..255              |00
        btfsc   ADCON0,CHS0     ; duration? no, skip, else        |00
        movwf   duration        ; update 'duration', 0..255       |00
        btfss   ADCON0,CHS0     ; brightness? no, skip, else      |00
        movwf   pwmlevel        ; update 'pwmlevel', 0..255       |00
;
;  check for end of half cycle
;
        decfsz  counter,F       ; end of half cycle duration?     |00
        goto    tmrloop         ; no, branch, else, fall thru     |00
        goto    halfcyc         ; start a new half cycle          |00

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  K8LH DelayCy() subsystem 16-bit uDelay subroutine              ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

a = dloop-1
    while a > 0
        nop                     ; (cycles-11)%dloop entry points  |00
a -= 1
    endw
uLoop   addlw   -1              ; subtract 'dloop' loop time      |00
        skpc                    ; borrow? no, skip, else          |00
        decfsz  delayhi,F       ; done?  yes, skip, else          |00
        goto    uLoop-dloop+5   ; do another loop                 |00
        return                  ;                                 |00
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        end
 
Last edited:

Thread Starter

Don Omar

Joined May 5, 2017
49
is this looks okay to you ?
Code:
TITLE "pwm_led.asm" ;
  List P=PIC16F684, R=DEC
  INCLUDE "p16f684.inc"

  ERRORLEVEL -302  ; suppress 'not in bank' messages

  ; data segment
  CBLOCK 0x20
  del  ; variable used for delay
  temp  ; local temp variable
  FlashK  ; counts 1 ms delays to do flash
  duration
  pwmlevel
  ledstate
  counter
  delayhi
  ENDC

  ; code segment
  PAGE
  __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

  ;****************** PROGRAM BEGINS  ******************************

  ORG 0 ; start program at the beginning of mem

  ;Init
   clrf   PORTA          ; initialize PORT A
   clrf   PORTC          ; initialize PORT C
   bsf    STATUS,RP0     ; select memory bank
   movlw   B'00001111'   ;
   movwf   TRISA         ;
   movlw   B'11100000'   ;
   movwf   TRISC         ;
   movlw 0x07
   movwf CMCON0 ; comparators OFF
   bsf STATUS, RP0 ; change to BANK 1

; ADC and PWM configuration
   movlw   B'00001111'   ; AN0 to AN3 are analog inputs
   movwf   ANSEL          ;Bank 1
   movlw   B'01000000'   ; left justified A/D result, VCC as ref
   movwf   ADCON1        ;Bank 1
   movlw b'01110000'     ; set ADC Frc clock
   movwf ADCON1
   movlw 0xFF
   movwf PR2  ; PWM period 244Hz
   bcf TRISC , 5 ; enable RC5 for output
   bcf STATUS, RP0 ; back to BANK 0
   bsf ADCON0, 0 ; Left justify, Vdd Vref, AN0, On
   movlw 7
   movwf T2CON ; enable Timer 2 with 1:16 prescaler
   movlw 0x0C ; enable single output PWM
   movwf CCP1CON

loop
  ;-------------------- PROCESS AN0 -> PWM  ------------------
  ; PWM controls brightness
  ; Assumes channel 0 is set
  bsf ADCON0,   GO  ; start ADC operation
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1
  bsf ADCON0,CHS0  ; select channel 1 for NEXT convert, to let it settle
                   ; then process channel 0 result (PWM reading)bsf STATUS, RP0  ; change to BANK
  movf ADRESL,W    ; read 2 lower bits of ADC
  bcf STATUS, RP0
  movwf temp          ; save for shifts
  rrf temp, f         ; shift one right
  rrf temp, W         ; shift one right, dest is W
  andlw  B'00110000' ; strip other bits
  bcf CCP1CON,5       ; clear CCP1CON 5:4 without affecting W
  bcf CCP1CON,4
  iorwf  CCP1CON,F  ; combine temp >> 2 with CCP1CON 5:4
  movf ADRESH, W  ; get high 8 bits of ADC
  movwf CCPR1L  ; setup PWM duty cycle

  ;----------------- PROCESS AN1 -> FLASH RATE  ------------------
  ; Toggles LED every FlashK milliseconds, updates rate at end of each
  ;  flash 1/2 cycle.
  ; assumes AN1 is set but converts only when current LED flash is
  ;  done i.e. FlashK decrements to zero.
  ;  When FlashK==0, gets new FlashK from ADC to change rate
  ; Total flash time is broken into 1ms increments so that it does
  ;  not bog down the PWM sampling for slow flash rates.

  decfsz  FlashK,F  ; flash msecs elapsed?
  goto  _flash1ms  ; nope, wait another ms towards finishing this flash

  ; else, get new FlashK from ADC
  bsf ADCON0, GO  ; start ADC operation
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  movf  ADRESH,W  ; get result
  movwf  FlashK  ; to flash counter
  ;----------------
  halfcyc
        incf    duration,W      ; duration, 1..256 msecs          |00
        movwf   counter         ;                                 |00
;
;  toggle LED on or off each half cycle
;
        incf    ledstate,F      ; bump bit 0 LED 'state'          |00
        movf    pwmlevel,W      ; duty cycle, 0..255              |00
        btfss   ledstate,0      ; state 1? yes, skip, else        |00
        movlw   0               ; use 'off' duty cycle value      |00
        movwf   CCPR1L          ; set PWM duty cycle              |00
tmrloop
        movlw   1<<CHS0         ; bit mask for ADCON0.CHS0 bit    |00
        xorwf   ADCON0,F        ; toggle channel (0 or 1)         |00
        call    _flash1ms     ; wait 1-msec minus 20 cycles     |00
;
;  read each ADC channel on alternating 1-msec intervals
;
        bsf     ADCON0,GO       ; start conversion                |00
adcwait btfsc   ADCON0,GO       ; done? yes, skip, else           |00
        goto    adcwait         ; branch (wait)                   |00
        movf    ADRESH,W        ; adc result, 0..255              |00
        btfsc   ADCON0,CHS0     ; duration? no, skip, else        |00
        movwf   duration        ; update 'duration', 0..255       |00
        btfss   ADCON0,CHS0     ; brightness? no, skip, else      |00
        movwf   pwmlevel        ; update 'pwmlevel', 0..255       |00
;
;  check for end of half cycle
;
        decfsz  counter,F       ; end of half cycle duration?     |00
        goto    tmrloop         ; no, branch, else, fall thru     |00
        goto    halfcyc         ; start a new half cycle          |00
  ;----------------

_flash1ms
  bcf ADCON0,CHS0  ; select channel 0 for NEXT convert, let it settle
  movlw  1  ; delay 1 ms per loop
  movwf  del
  call  delay
  goto loop ; endless loop

  ;**************** UTILITIES  ****************************
  ; procedures
delay ; a delay for del milliseconds
  movlw 200
  sublw 1 ; this loop takes 5us*200 = 1ms
  sublw 0 ; for PIC16F684 @ 4 MHz
  btfss STATUS, Z
  goto $-3

  decfsz del, f
  goto delay
  return
END
 
Last edited by a moderator:

Thread Starter

Don Omar

Joined May 5, 2017
49
The same "basic" parts you have in your program; (1) the "list" and "include" directives, (2) configuration settings, (3) variable and constant declarations, (4) program "org" statement, (5) initialization code, (6) the "main loop", which I provided a sample of, and (6) your delay subroutine...

It would be better if you took the time to understand the example and implement something similar in your program rather than simply trying to copy and paste a program together from examples. If you don't understand a piece of the code, ask about it.

The main program loop example I provided is a simple timing loop based on the ADC "duration" reading. At the beginning of each loop you toggle the LED from off to on or from on to off, then burn off the amount of time from the ADC "duration" reading while updating the "duration" and "brightness" variables from the ADC inputs. The "duration" and "brightness" settings are applied at the beginning of each new timing loop.

Code:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  pwm_led.asm  (untested)                                        ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        list P=PIC16F684, R=DEC
        include "p16f684.inc"
        errorlevel -302

__CONFIG _FOSC_INTOSCIO & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF &
          _IESO_OFF & _FCMEN_OFF
;
; _CP_OFF    default
; _CPD_OFF   default
; _BOD_ON    default
;

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  variables                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        cblock  0x20
duration
pwmlevel
ledstate
counter
delayhi                         ; DelayCy() subsystem variable
        endc

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  K8LH DelayCy() subsystem macro generates four instructions     ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        radix dec
clock   equ     4               ; 4, 8, 12, 16, 20 (MHz), etc.
usecs   equ     clock/4         ; cycles/microsecond multiplier
msecs   equ     usecs*1000      ; cycles/millisecond multiplier
dloop   equ     5               ; loop size, 5 to 8 cycles
;
;  -- loop --  -- delay range --  -- memory overhead ----------
;  5-cyc loop, 11..327690 cycles,  9 words (+4 each macro call)
;  6-cyc loop, 11..393226 cycles, 10 words (+4 each macro call)
;  7-cyc loop, 11..458762 cycles, 11 words (+4 each macro call)
;  8-cyc loop, 11..524298 cycles, 12 words (+4 each macro call)
;
DelayCy macro   cycles          ; range, see above
    if (cycles<11)|(cycles>(dloop*65536+10))
        error " DelayCy range error "
    else
        movlw   high((cycles-11)/dloop)+1
        movwf   delayhi
        movlw   low ((cycles-11)/dloop)
        call    uLoop-((cycles-11)%dloop)
    endif
        endm

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  reset vector                                                   ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        org     0x000
v_reset
        clrf    STATUS          ; force bank 0                    |00
        clrf    PORTA           ; initialize PORT A               |00
        clrf    PORTC           ; initialize PORT C               |00
        movlw   0x07            ;                                 |00
        movwf   CMCON0          ; comparators OFF                 |00
;
;  ADC and PWM configuration
;
        bsf     STATUS,RPO      ; bank 1                          |01
        movlw   1<<RA0|1<<RA1   ;                                 |01
        movwf   TRISA           ; RA1..RA0 inputs                 |01
        movwf   ANSEL           ; RA1..RA0 analog                 |01
        movlw   b'01110000'     ; select Frc 500-kHz oscillator   |01
        movwf   ADCON1          ; as ADC clock source             |01
        bcf     TRISC,RA5       ; RA5 output, others inputs       |01
        movlw   0xFF            ;                                 |01
        movwf   PR2             ; PWM period 244Hz                |01

        bcf     STATUS,RP0      ; bank 0                          |00
        bsf     ADCON0,ADON     ; left justify, vdd Vref, AN0, on |00
        movlw   7               ;                                 |00
        movwf   T2CON           ; prescale 16, timer 'on'         |00
        movlw   0x0C            ;                                 |00
        movwf   CCP1CON         ; select active hi PWM mode       |00

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  main loop                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

halfcyc
        incf    duration,W      ; duration, 1..256 msecs          |00
        movwf   counter         ;                                 |00
;
;  toggle LED on or off each half cycle
;
        incf    ledstate,F      ; bump bit 0 LED 'state'          |00
        movf    pwmlevel,W      ; duty cycle, 0..255              |00
        btfss   ledstate,0      ; state 1? yes, skip, else        |00
        movlw   0               ; use 'off' duty cycle value      |00
        movwf   CCPR1L          ; set PWM duty cycle              |00
tmrloop
        movlw   1<<CHS0         ; bit mask for ADCON0.CHS0 bit    |00
        xorwf   ADCON0,F        ; toggle channel (0 or 1)         |00
        DelayCy(1*msecs-20)     ; wait 1-msec minus 20 cycles     |00
;
;  read each ADC channel on alternating 1-msec intervals
;
        bsf     ADCON0,GO       ; start conversion                |00
adcwait btfsc   ADCON0,GO       ; done? yes, skip, else           |00
        goto    adcwait         ; branch (wait)                   |00
        movf    ADRESH,W        ; adc result, 0..255              |00
        btfsc   ADCON0,CHS0     ; duration? no, skip, else        |00
        movwf   duration        ; update 'duration', 0..255       |00
        btfss   ADCON0,CHS0     ; brightness? no, skip, else      |00
        movwf   pwmlevel        ; update 'pwmlevel', 0..255       |00
;
;  check for end of half cycle
;
        decfsz  counter,F       ; end of half cycle duration?     |00
        goto    tmrloop         ; no, branch, else, fall thru     |00
        goto    halfcyc         ; start a new half cycle          |00

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  K8LH DelayCy() subsystem 16-bit uDelay subroutine              ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

a = dloop-1
    while a > 0
        nop                     ; (cycles-11)%dloop entry points  |00
a -= 1
    endw
uLoop   addlw   -1              ; subtract 'dloop' loop time      |00
        skpc                    ; borrow? no, skip, else          |00
        decfsz  delayhi,F       ; done?  yes, skip, else          |00
        goto    uLoop-dloop+5   ; do another loop                 |00
        return                  ;                                 |00
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        end
can you check the code that i posted because it not working for me
thanks
 

JohnInTX

Joined Jun 26, 2012
4,787
It looks to me that you have just merged what @MMcLaren provided as an example with what I provided as an example. Both approaches should work but not together. As Mike noted in #42, you can't do that.

You need to stop, get a pencil and paper and flow out the loop code in plain language. Do it for both of our approaches until you understand how one or the other or both work then pick an approach that you understand and code it. Then ask for help with the details. As I and others have said here and in the PMs, you can't just stick chunks of code together and hope for it to work. It doesn't work that way. You have to understand the principles behind the coding or you will fail.

Also, it is not reasonable to ask two different members to work on two different approaches with you to see who gets to the finish line first. I lose interest really fast in that kind of thing if you haven't noticed.

Next thing I want to see is a flow chart for the main loop including flasher from you so that time spent is towards a known goal. Mike or others may have more time to devote to this. If so, have at it guys.
 

Thread Starter

Don Omar

Joined May 5, 2017
49
It looks to me that you have just merged what @MMcLaren provided as an example with what I provided as an example. Both approaches should work but not together. As Mike noted in #42, you can't do that.

You need to stop, get a pencil and paper and flow out the loop code in plain language. Do it for both of our approaches until you understand how one or the other or both work then pick an approach that you understand and code it. Then ask for help with the details. As I and others have said here and in the PMs, you can't just stick chunks of code together and hope for it to work. It doesn't work that way. You have to understand the principles behind the coding or you will fail.

Also, it is not reasonable to ask two different members to work on two different approaches with you to see who gets to the finish line first. I lose interest really fast in that kind of thing if you haven't noticed.

Next thing I want to see is a flow chart for the main loop including flasher from you so that time spent is towards a known goal. Mike or others may have more time to devote to this. If so, have at it guys.
I understand what u meant but as i told u before this all new to me because of the time that I have left before submitting it I'm really stress out and I'm rally sorry if asked 2 members for the same thing I'm new to this websites sobi didn't know how this things work here
 

Thread Starter

Don Omar

Joined May 5, 2017
49
It looks to me that you have just merged what @MMcLaren provided as an example with what I provided as an example. Both approaches should work but not together. As Mike noted in #42, you can't do that.

You need to stop, get a pencil and paper and flow out the loop code in plain language. Do it for both of our approaches until you understand how one or the other or both work then pick an approach that you understand and code it. Then ask for help with the details. As I and others have said here and in the PMs, you can't just stick chunks of code together and hope for it to work. It doesn't work that way. You have to understand the principles behind the coding or you will fail.

Also, it is not reasonable to ask two different members to work on two different approaches with you to see who gets to the finish line first. I lose interest really fast in that kind of thing if you haven't noticed.

Next thing I want to see is a flow chart for the main loop including flasher from you so that time spent is towards a known goal. Mike or others may have more time to devote to this. If so, have at it guys.


@JohnInTX
i dont know how to take any further
  1. Code:
    TITLE "pwm_led.asm" ;
    [*]List P=PIC16F684, R=DEC
    [*]  INCLUDE "p16f684.inc"
    [*]
    
    [*]  ERRORLEVEL -302 ; suppress 'not in bank' messages
    [*]
    
    [*]; data segment
    [*]CBLOCK 0x20
    [*]  del  ; variable used for delay
    [*]  temp  ; local temp variable
    [*]  FlashK  ; counts 1 ms delays to do flash
    [*]  duration
    [*]  pwmlevel
    [*]  ledstate
    [*]  counter
    [*]  delayhi
    [*]ENDC
    [*]
    
    [*]; code segment
    [*]PAGE
    [*]__CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
    [*]
    
    [*];****************** PROGRAM BEGINS  ******************************
    [*]
    
    [*]ORG 0 ; start program at the beginning of mem
    [*]
    
    [*];Init
    [*]   clrf PORTA         ; initialize PORT A
    [*]   clrf PORTC         ; initialize PORT C
    [*]   bsf   STATUS,RP0    ; select memory bank
    [*]   movlw B'00001111' ;
    [*]   movwf TRISA       ;
    [*]   movlw B'11100000' ;
    [*]   movwf TRISC       ;
    [*]   movlw 0x07
    [*]   movwf CMCON0 ; comparators OFF
    [*]   bsf STATUS, RP0 ; change to BANK 1
    [*]
    
    [*]; ADC and PWM configuration
    [*]   movlw B'00001111' ; AN0 to AN3 are analog inputs
    [*]   movwf  ANSEL          ;Bank 1
    [*]   movlw B'01000000' ; left justified A/D result, VCC as ref
    [*]   movwf  ADCON1        ;Bank 1
    [*]   movlw b'01110000'   ; set ADC Frc clock
    [*]   movwf ADCON1
    [*]   movlw 0xFF
    [*]   movwf PR2 ; PWM period 244Hz
    [*]   bcf TRISC , 5 ; enable RC5 for output
    [*]   bcf STATUS, RP0 ; back to BANK 0
    [*]   bsf ADCON0, 0 ; Left justify, Vdd Vref, AN0, On
    [*]   movlw 7
    [*]   movwf T2CON ; enable Timer 2 with 1:16 prescaler
    [*]   movlw 0x0C ; enable single output PWM
    [*]   movwf CCP1CON
    [*]
    
    [*]loop
    [*];-------------------- PROCESS AN0 -> PWM  ------------------
    [*]; PWM controls brightness
    [*]; Assumes channel 0 is set
    [*]bsf ADCON0,   GO  ; start ADC operation
    [*]btfsc ADCON0, GO  ; and wait for its completion
    [*]goto $-1
    [*]bsf ADCON0,CHS0  ; select channel 1 for NEXT convert, to let it settle
    [*]                   ; then process channel 0 result (PWM reading)bsf STATUS, RP0  ; change to BANK
    [*]movf ADRESL,W    ; read 2 lower bits of ADC
    [*]bcf STATUS, RP0
    [*]movwf temp          ; save for shifts
    [*]rrf temp, f        ; shift one right
    [*]rrf temp, W        ; shift one right, dest is W
    [*]andlw B'00110000' ; strip other bits
    [*]bcf CCP1CON,5     ; clear CCP1CON 5:4 without affecting W
    [*]bcf CCP1CON,4
    [*]iorwf CCP1CON,F  ; combine temp >> 2 with CCP1CON 5:4
    [*]movf ADRESH, W  ; get high 8 bits of ADC
    [*]movwf CCPR1L ; setup PWM duty cycle
    [*]
    
    [*];----------------- PROCESS AN1 -> FLASH RATE  ------------------
    [*]; Toggles LED every FlashK milliseconds, updates rate at end of each
    [*];  flash 1/2 cycle.
    [*]; assumes AN1 is set but converts only when current LED flash is
    [*];  done i.e. FlashK decrements to zero.
    [*];  When FlashK==0, gets new FlashK from ADC to change rate
    [*]; Total flash time is broken into 1ms increments so that it does
    [*];  not bog down the PWM sampling for slow flash rates.
    [*]
    
    [*]decfsz FlashK,F  ; flash msecs elapsed?
    [*]goto _flash1ms  ; nope, wait another ms towards finishing this flash
    [*]
    
    [*]; else, get new FlashK from ADC
    [*]bsf ADCON0, GO  ; start ADC operation
    [*]btfsc ADCON0, GO  ; and wait for its completion
    [*]goto $-1
    [*]
    
    [*]movf ADRESH,W  ; get result
    [*]movwf FlashK  ; to flash counter
    [*];----------------
    [*]  halfcyc
    [*]       incf   duration,W      ; duration, 1..256 msecs          |00
    [*]       movwf  counter        ;                                 |00
    [*];
    [*];  toggle LED on or off each half cycle
    [*];
    [*]       incf   ledstate,F      ; bump bit 0 LED 'state'          |00
    [*]       movf   pwmlevel,W      ; duty cycle, 0..255              |00
    [*]       btfss  ledstate,0     ; state 1? yes, skip, else        |00
    [*]       movlw 0             ; use 'off' duty cycle value      |00
    [*]       movwf CCPR1L         ; set PWM duty cycle              |00
    [*]tmrloop
    [*]       movlw 1<<CHS0        ; bit mask for ADCON0.CHS0 bit    |00
    [*]       xorwf  ADCON0,F        ; toggle channel (0 or 1)         |00
    [*]       call   _flash1ms    ; wait 1-msec minus 20 cycles     |00
    [*];
    [*];  read each ADC channel on alternating 1-msec intervals
    [*];
    [*]       bsf    ADCON0,GO      ; start conversion                |00
    [*]adcwait btfsc  ADCON0,GO      ; done? yes, skip, else           |00
    [*]       goto   adcwait        ; branch (wait)                   |00
    [*]       movf   ADRESH,W        ; adc result, 0..255              |00
    [*]       btfsc  ADCON0,CHS0    ; duration? no, skip, else        |00
    [*]       movwf  duration        ; update 'duration', 0..255       |00
    [*]       btfss  ADCON0,CHS0    ; brightness? no, skip, else      |00
    [*]       movwf  pwmlevel        ; update 'pwmlevel', 0..255       |00
    [*];
    [*];  check for end of half cycle
    [*];
    [*]       decfsz counter,F      ; end of half cycle duration?     |00
    [*]       goto   tmrloop        ; no, branch, else, fall thru     |00
    [*]       goto   halfcyc        ; start a new half cycle          |00
    [*];----------------
    [*]
    
    [*]_flash1ms
    [*]bcf ADCON0,CHS0  ; select channel 0 for NEXT convert, let it settle
    [*]movlw 1 ; delay 1 ms per loop
    [*]movwf del
    [*]call delay
    [*]goto loop ; endless loop
    [*]
    
    [*];**************** UTILITIES  ****************************
    [*]; procedures
    [*]delay ; a delay for del milliseconds
    [*]movlw 200
    [*]sublw 1 ; this loop takes 5us*200 = 1ms
    [*]sublw 0 ; for PIC16F684 @ 4 MHz
    [*]btfss STATUS, Z
    [*]goto $-3
    [*]
    
    [*]decfsz del, f
    [*]goto delay
    [*]return
    [*]END
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
Stop. Reset. You can't just throw disparate things together and expect them to work. That should be obvious by now as is the prospect of success when you 'don't have the time to understand'-your words- what you are trying to do. There are many recipes for failure and that one is as good as any. It is time to quit fretting and start thinking.

First, I won't write your code for you. But you clearly need some help organizing your thoughts. You have been given several different approaches here and that may be confusing. So.. Let's get with it.

I asked you to flow out the 'loop' portion. A flow chart can be invaluable in helping you see the big picture AND the details. I have generated one for you. The program it describes is kind of a blend of what Mike and I described. Read that flow chart STEP-BY-STEP. Follow the arrows with your finger. That is called desk-checking and is a valuable tool. Do not go any further until you COMPLETELY understand the flow, how the two ADC channels are used and what turns the LED on and OFF at the selected brightness.

Once you understand the flow, it should be clear that virtually all of the coding you need to implement the flow chart is already done - it just needs to be arranged in like the flow chart says.
Init? Check.
Delay? Check.
Read ADC? Check.
Change channels and read the other pot? Check? Yup it's there in one of my posts, probably in Mike's too.
Change PWM duty cycle? Check.
It's all there. A little scattered in the posts maybe but the code is there.

So, take it block by block and implement each block. If the flow chart is good, making the whole thing work is a matter of coding each step to do what the boxes and test diamonds say.

Here's my implementation. Read, understand, get busy. It may take all night. Welcome to the club.
 

Attachments

Last edited:

Thread Starter

Don Omar

Joined May 5, 2017
49
Stop. Reset. You can't just throw disparate things together and expect them to work. That should be obvious by now as is the prospect of success when you 'don't have the time to understand'-your words- what you are trying to do. There are many recipes for failure and that one is as good as any. It is time to quit fretting and start thinking.

First, I won't write your code for you. But you clearly need some help organizing your thoughts. You have been given several different approaches here and that may be confusing. So.. Let's get with it.

I asked you to flow out the 'loop' portion. A flow chart can be invaluable in helping you see the big picture AND the details. I have generated one for you. The program it describes is kind of a blend of what Mike and I described. Read that flow chart STEP-BY-STEP. Follow the arrows with your finger. That is called desk-checking and is a valuable tool. Do not go any further until you COMPLETELY understand the flow, how the two ADC channels are used and what turns the LED on and OFF at the selected brightness.

Once you understand the flow, it should be clear that virtually all of the coding you need to implement the flow chart is already done - it just needs to be arranged in like the flow chart says.
Init? Check.
Delay? Check.
Read ADC? Check.
Change channels and read the other pot? Check? Yup it's there in one of my posts, probably in Mike's too.
Change PWM duty cycle? Check.
It's all there. A little scattered in the posts maybe but the code is there.

So, take it block by block and implement each block. If the flow chart is good, making the whole thing work is a matter of coding each step to do what the boxes and test diamonds say.

Here's my implementation. Read, understand, get busy. It may take all night. Welcome to the club.
hey john
this is what i did so far i really appreciate your help could u please let me know what i have done wrong
Code:
bsf ADCON0, GO         ; start ADC operation
  btfsc ADCON0, GO       ; and wait for its completion
  goto $-1
  movf  ADRESH,W         ; get result
  movwf  FlashK          ; to flash counter
  btfss   ADCON0,CHS0     ; brightness? no, skip, else   
  movwf   FlashCounter        ; update
  decfsz  FlashK,F       ; flash msecs elapsed?
  goto  _flash1ms        ; nope, wait another ms towards finishing this flash
  movlw   0               ;  'off' duty cycle     
  movwf   CCPR1L          ; set PWM duty cycle 
_flash1ms
  bcf ADCON0,CHS0  ; select channel 0 for NEXT convert, let it settle
  movlw  1  ; delay 1 ms per loop
  movwf  del
  call  delay
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
It is a start but where is the rest of it??
You should break the task up into blocks that match the flow chart. My internet is currently down. When it is back, I will upload an annotated flow chart, labeling the blocks and framework code to fill in the blanks. Meanwhile, fill in some of those blocks. For example, where is the pic header file, config bits and init code? Update the cblock to include only the variables in the flow chart. I'll tag you when I am back on line..
@Don Omar
 

Thread Starter

Don Omar

Joined May 5, 2017
49
It is a start but where is the rest of it??
You should break the task up into blocks that match the flow chart. My internet is currently down. When it is back, I will upload an annotated flow chart, labeling the blocks and framework code to fill in the blanks. Meanwhile, fill in some of those blocks. For example, where is the pic header file, config bits and init code? Update the cblock to include only the variables in the flow chart. I'll tag you when I am back on line..
@Don Omar
sorry for not including the rest of the code

Code:
TITLE "pwm_led.asm" ;
  List P=PIC16F684, R=DEC
  INCLUDE "p16f684.inc"
  ERRORLEVEL -302  ; suppress 'not in bank' messages

  CBLOCK 0x20
  del  ; variable used for delay
  temp  ; local temp variable
  FlashK  ; counts 1 ms delays to do flash
  flashcounter
  ENDC

  PAGE
  __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

  ;****************** PROGRAM BEGINS  ******************************

  ORG 0 ; start program at the beginning of mem

  bcf STATUS, RP0 ; activate BANK 0
  clrf PORTA ; initialize PORT A
  clrf PORTC ; initialize PORT C
  movlw 0x07
  movwf CMCON0 ; comparators OFF
  bsf STATUS, RP0 ; change to BANK 1

  ; ADC and PWM configuration
  bsf TRISA , 0 ; enable input on pin A0
  bsf ANSEL , 0 ; configure A0 as analog input
  movlw b'01110000' ; set ADC Frc clock
  movwf ADCON1
  movlw 0xFF
  movwf PR2  ; PWM period 244Hz

  bcf TRISC , 5 ; enable RC5 for output
  bcf STATUS, RP0 ; back to BANK 0

  bsf ADCON0, 0 ; Left justify, Vdd Vref, AN0, On
  movlw 7
  movwf T2CON ; enable Timer 2 with 1:16 prescaler
  movlw 0x0C ; enable single output PWM
  movwf CCP1CON

loop
  ;-------------------- PROCESS AN0 -> PWM  ------------------
  bsf ADCON0, GO  ; start ADC operation
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  bsf ADCON0,CHS0  ; select channel 1 for NEXT convert, to let it settle
  ; then process channel 0 result (PWM reading)

  bsf STATUS, RP0  ; change to BANK 1
  movf ADRESL,W  ; read 2 lower bits of ADC
  bcf STATUS, RP0
  movwf temp  ; save for shifts
  rrf temp, f  ; shift one right
  rrf temp, W  ; shift one right, dest is W
  andlw  B'00110000' ; strip other bits
  bcf CCP1CON,5  ; clear CCP1CON 5:4 without affecting W
  bcf CCP1CON,4
  iorwf  CCP1CON,F  ; combine temp >> 2 with CCP1CON 5:4

  movf ADRESH, W  ; get high 8 bits of ADC
  movwf CCPR1L  ; setup PWM duty cycle

  ;----------------- PROCESS AN1 -> FLASH RATE  ------------------
  bsf ADCON0, GO  ; start ADC operation
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1
  movf  ADRESH,W  ; get result
  movwf  FlashK  ; to flash counter
  decfsz  FlashK,F  ; flash msecs elapsed?
  goto  _flash1ms  ; nope, wait another ms towards finishing this flash
  clrf CCPR1L ; to turn LED off, set duty cycle to 0
  movlw B'11001111'
  andwf CCP1CON,F

_flash1ms
  bcf ADCON0,CHS0  ; select channel 0 for NEXT convert, let it settle

  movlw  1  ; delay 1 ms per loop
  movwf  del
  call  delay

  goto loop ; endless loop

  ;**************** UTILITIES  ****************************

delay             ; a delay for del milliseconds
  movlw 200
  sublw 1 ; this loop takes 5us*200 = 1ms
  sublw 0 ; for PIC16F684 @ 4 MHz
  btfss STATUS, Z
  goto $-3
  decfsz del, f
  goto delay
  return
  END
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
@Don Omar Progress, nice!

Here's what I was writing when the intertubes went down...

To help you I have annotated the flow chart with the functional steps in blue and the three necessary loop labels in red. I also have taken what you wrote and broke it into coded sections that match the blue functional steps in the flow chart. When shown that way the missing pieces are obvious no? I added a few lines here and there to show you how I would code those steps. You've added a lot so before going further, read below and get the code you wrote into the spaces in my listing that correspond to the flow diagram blocks -OR- add the annotated blocks to your code like I did mine. Either way, what code you have so far should be organized into annotated steps.

You will have to add the missing pieces. Add the init section from the last one that worked and detail it to match your hardware if necessary. Then take things carefully and thoughtfully, ONE BLOCK AT A TIME and code each block. Pay attention to the variables, too. For example your code used the new FlashCounter variable and the old FlashK. Do you see FlashK in the flow chart? Me neither. They are the same variable. I renamed it to be more descriptive.

Keep at it. If you have a question, don't stop and wait, code the next block. Assemble periodically and fix any errors as you go. Tag or like to alert when you have posted something.

Code:
;************** LED FLASHER/DIMMER  *********************

  TITLE "pwm_led.asm" ;
  List P=PIC16F684, R=DEC
  INCLUDE "p16f684.inc"
  ERRORLEVEL -302  ; suppress 'not in bank' messages

  ;------------
  ; RAM
  ; NOTE THAT THIS NEW STUFF SO ONLY ADD RAM TO FIT THE NEW STUFF!
  cblock 20h
  FlashCounter:1  ; declare one byte for 1ms flash counter
  del:1  ; delay parameter - 1ms increments
  endc

  __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

  ;******************* PROGRAM STARTS  *********************************
  ORG 0

  ;-------------
  ;INIT
;========================================================================
; add the init code here in previous posts everything from ORG 0 to loop
;========================================================================

main_loop:
  ;-------------
  ;ON-1  ; Read flash rate for ON half of cycle
  bsf ADCON0,CHS0  ; select channel 1 for NEXT convert, to let it settle
  movlw  .1  ; for 1 ms
  movwf  del
  call  delay

  bsf ADCON0, GO  ; start ADC conversion
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  ;-------------
  ;ON-2
  movf ADRESH,W  ; get result
  movwf FlashCounter  ; to 1ms flash counter

  ;-------------
  ;ON-3
wait_while_LED_on:
  bcf ADCON0,CHS0  ; select channel 0 for NEXT convert, to let it settle
  movlw  .1  ; for 1 ms
  movwf  del
  call  delay

  bsf ADCON0, GO  ; start ADC conversion
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  ;-------------
  ;ON-4

  ;-------------
  ;ON-5

  ;-------------
  ;ON-6

  ;-------------
  ;ON-7
  decfsz  FlashCounter,F
  goto  wait_while_LED_on

  ;-------------
  ;ON-8
  ; 'ON' time has elapsed.  Turn PWM OFF by setting its duty cycle to 0%
  ; then proceed to time the OFF time.

  ;-------------
  ;OFF-1

  ;-------------
  ;OFF-2

  ;-------------
  ;OFF-3
wait_while_LED_off:

  ;-------------
  ;OFF-4

  ;-------------
  ;OFF-5

  decfsz  FlashCounter,F
  goto  wait_while_LED_off

  goto  main_loop  ; 'OFF' time has elapsed, back the 'ON' sequence


  ;**************** UTILITIES  ****************************
  ; procedures
  ; a delay for del milliseconds

delay:
  movlw .200
  sublw 1 ; this loop takes 5us*200 = 1ms
  sublw 0 ; for PIC16F684 @ 4 MHz
  btfss STATUS, Z
  goto $-3
  decfsz del, f
  goto delay
  return

  END
 

Attachments

Thread Starter

Don Omar

Joined May 5, 2017
49
@Don Omar Progress, nice!

Here's what I was writing when the intertubes went down...

To help you I have annotated the flow chart with the functional steps in blue and the three necessary loop labels in red. I also have taken what you wrote and broke it into coded sections that match the blue functional steps in the flow chart. When shown that way the missing pieces are obvious no? I added a few lines here and there to show you how I would code those steps. You've added a lot so before going further, read below and get the code you wrote into the spaces in my listing that correspond to the flow diagram blocks -OR- add the annotated blocks to your code like I did mine. Either way, what code you have so far should be organized into annotated steps.


You will have to add the missing pieces. Add the init section from the last one that worked and detail it to match your hardware if necessary. Then take things carefully and thoughtfully, ONE BLOCK AT A TIME and code each block. Pay attention to the variables, too. For example your code used the new FlashCounter variable and the old FlashK. Do you see FlashK in the flow chart? Me neither. They are the same variable. I renamed it to be more descriptive.

Keep at it. If you have a question, don't stop and wait, code the next block. Assemble periodically and fix any errors as you go. Tag or like to alert when you have posted something.

Code:
;************** LED FLASHER/DIMMER  *********************

  TITLE "pwm_led.asm" ;
  List P=PIC16F684, R=DEC
  INCLUDE "p16f684.inc"
  ERRORLEVEL -302  ; suppress 'not in bank' messages

  ;------------
  ; RAM
  ; NOTE THAT THIS NEW STUFF SO ONLY ADD RAM TO FIT THE NEW STUFF!
  cblock 20h
  FlashCounter:1  ; declare one byte for 1ms flash counter
  del:1  ; delay parameter - 1ms increments
  endc

  __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

  ;******************* PROGRAM STARTS  *********************************
  ORG 0

  ;-------------
  ;INIT
;========================================================================
; add the init code here in previous posts everything from ORG 0 to loop
;========================================================================

main_loop:
  ;-------------
  ;ON-1  ; Read flash rate for ON half of cycle
  bsf ADCON0,CHS0  ; select channel 1 for NEXT convert, to let it settle
  movlw  .1  ; for 1 ms
  movwf  del
  call  delay

  bsf ADCON0, GO  ; start ADC conversion
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  ;-------------
  ;ON-2
  movf ADRESH,W  ; get result
  movwf FlashCounter  ; to 1ms flash counter

  ;-------------
  ;ON-3
wait_while_LED_on:
  bcf ADCON0,CHS0  ; select channel 0 for NEXT convert, to let it settle
  movlw  .1  ; for 1 ms
  movwf  del
  call  delay

  bsf ADCON0, GO  ; start ADC conversion
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  ;-------------
  ;ON-4

  ;-------------
  ;ON-5

  ;-------------
  ;ON-6

  ;-------------
  ;ON-7
  decfsz  FlashCounter,F
  goto  wait_while_LED_on

  ;-------------
  ;ON-8
  ; 'ON' time has elapsed.  Turn PWM OFF by setting its duty cycle to 0%
  ; then proceed to time the OFF time.

  ;-------------
  ;OFF-1

  ;-------------
  ;OFF-2

  ;-------------
  ;OFF-3
wait_while_LED_off:

  ;-------------
  ;OFF-4

  ;-------------
  ;OFF-5

  decfsz  FlashCounter,F
  goto  wait_while_LED_off

  goto  main_loop  ; 'OFF' time has elapsed, back the 'ON' sequence


  ;**************** UTILITIES  ****************************
  ; procedures
  ; a delay for del milliseconds

delay:
  movlw .200
  sublw 1 ; this loop takes 5us*200 = 1ms
  sublw 0 ; for PIC16F684 @ 4 MHz
  btfss STATUS, Z
  goto $-3
  decfsz del, f
  goto delay
  return

  END


@Johnlntx
thank you very much for that flow chart it does help a lot
so this what i have done there is few more to do i just want to check with u first


Code:
TITLE "pwm_led.asm" ;
  List P=PIC16F684, R=DEC
  INCLUDE "p16f684.inc"
  ERRORLEVEL -302  ; suppress 'not in bank' messages

  ;------------
  ; RAM
  ; NOTE THAT THIS NEW STUFF SO ONLY ADD RAM TO FIT THE NEW STUFF!
  cblock 20h
  FlashCounter:1  ; declare one byte for 1ms flash counter
  del:1  ; delay parameter - 1ms increments
  endc

  __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

  ;******************* PROGRAM STARTS  *********************************
  ORG 0

  ;-------------
  ;INIT
;========================================================================
; add the init code here in previous posts everything from ORG 0 to loop
;========================================================================

main_loop:
  ;-------------
  ;ON-1  ; Read flash rate for ON half of cycle
  bsf ADCON0,CHS0  ; select channel 1 for NEXT convert, to let it settle
  movlw  .1  ; for 1 ms
  movwf  del
  call  delay

  bsf ADCON0, GO  ; start ADC conversion
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  ;-------------
  ;ON-2
  movf ADRESH,W  ; get result
  movwf FlashCounter  ; to 1ms flash counter

  ;-------------
  ;ON-3
wait_while_LED_on:
  bcf ADCON0,CHS0  ; select channel 0 for NEXT convert, to let it settle
  movlw  .1  ; for 1 ms
  movwf  del
  call  delay

  bsf ADCON0, GO  ; start ADC conversion
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  ;-------------
  ;ON-4

  ;-------------
  ;ON-5
call delay
  ;-------------
  ;ON-6

  ;-------------
  ;ON-7
  decfsz  FlashCounter,F
  goto  wait_while_LED_on

  ;-------------
  ;ON-8
  ; 'ON' time has elapsed.  Turn PWM OFF by setting its duty cycle to 0%
  ; then proceed to time the OFF time.

  ;-------------
  ;OFF-1
  bsf ADCON0,CHS0  ; select channel 1 for NEXT convert, to let it settle
  movlw  .1  ; for 1 ms
  movwf  del
  call  delay

  bsf ADCON0, GO  ; start ADC conversion
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1
  ;-------------
  ;OFF-2

  movf ADRESH,W  ; get result
  movwf FlashCounter  ; to 1ms flash counter

  ;-------------
  ;OFF-3
wait_while_LED_off
  bcf ADCON0,CHS0  ; select channel 0 for NEXT convert, to let it settle
  movlw  .1  ; for 1 ms
  movwf  del
  call  delay
  bsf ADCON0, GO  ; start ADC conversion
  btfsc ADCON0, GO  ; and wait for its completion
  goto $-1

  ;-------------
  ;OFF-4

  ;-------------
  ;OFF-5

  decfsz  FlashCounter,F
  goto  wait_while_LED_off

  goto  main_loop  ; 'OFF' time has elapsed, back the 'ON' sequence


  ;**************** UTILITIES  ****************************
  ; procedures
  ; a delay for del milliseconds

delay:
  movlw .200
  sublw 1 ; this loop takes 5us*200 = 1ms
  sublw 0 ; for PIC16F684 @ 4 MHz
  btfss STATUS, Z
  goto $-3
  decfsz del, f
  goto delay
  return

  END[\code]
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
Quick look before I hit the rack..
You're getting the hang of this, keep up the good work.
In ON-5, you omitted the setting of 'del' to set up the 1ms delay.
In OFF-3, you are reading the ADC again but the OFF-3 step just says to do a 1ms delay.
You still need to add the init code, set up the ports, ADC inputs etc. That is more or less lines 29-55 in post #43. I don't know if those do the whole job but its a starting point. Read through each part of the init code and make sure you haven't missed anything.
Try to format your code so that labels start in column 1 and the code starts on the 1st tab like in my outline. It makes it much easier to read.

Assemble the code from time to time and fix any errors and warnings.

Carry on. If you get stuck, remember that each step in the chart can be considered a separate unit. Work on those that make sense then work on the harder ones. For example, all delay 1ms code should look the same (and could be subroutine but we'll leave that for later..).

Well done so far.
 

Thread Starter

Don Omar

Joined May 5, 2017
49
Quick look before I hit the rack..
You're getting the hang of this, keep up the good work.
In ON-5, you omitted the setting of 'del' to set up the 1ms delay.
In OFF-3, you are reading the ADC again but the OFF-3 step just says to do a 1ms delay.
You still need to add the init code, set up the ports, ADC inputs etc. That is more or less lines 29-55 in post #43. I don't know if those do the whole job but its a starting point. Read through each part of the init code and make sure you haven't missed anything.
Try to format your code so that labels start in column 1 and the code starts on the 1st tab like in my outline. It makes it much easier to read.

Assemble the code from time to time and fix any errors and warnings.

Carry on. If you get stuck, remember that each step in the chart can be considered a separate unit. Work on those that make sense then work on the harder ones. For example, all delay 1ms code should look the same (and could be subroutine but we'll leave that for later..).

Well done so far.

@johnlntx
Thanks for your support
i added the init code as the as some missing pieces could you please check it for me
the 1ms delay will it be a different subroutine code from the one i have already ?

TITLE "pwm_led.asm" ;
List P=PIC16F684, R=DEC
INCLUDE "p16f684.inc"
ERRORLEVEL -302 ; suppress 'not in bank' messages
; data segment
CBLOCK 0x20
temp: ; local temp variable
FlashCounter:1 ; declare one byte for 1ms flash counter
del:1 ; delay parameter - 1ms increments
ENDC

; code segment
PAGE
__CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

;****************** PROGRAM BEGINS ******************************

ORG 0 ; start program at the beginning of mem

;Init
clrf PORTA ; initialize PORT A
clrf PORTC ; initialize PORT C
bsf STATUS,RP0 ; select memory bank
movlw B'00001111' ;
movwf TRISA ;
movlw B'11100000' ;
movwf TRISC ;
movlw 0x07
movwf CMCON0 ; comparators OFF BANK 1 is selected, CMCON0 is in bank 0

bsf STATUS, RP0 ; change to BANK 1

; ADC and PWM configuration
movlw B'00001111' ; AN0 to AN3 are analog inputs
movwf ANSEL ;Bank 1
movlw B'01000000' ; left justified A/D result, VCC as ref????
movwf ADCON1 ;Bank 1 Should be ADCON0, and its not in bank 1
movlw b'01110000' ; set ADC Frc clock
movwf ADCON1

movlw 0xFF
movwf PR2 ; PWM period 244Hz
bcf TRISC , 5 ; enable RC5 for output
bcf STATUS, RP0 ; back to BANK 0
bsf ADCON0, 0 ; Left justify, Vdd Vref, AN0, On
movlw 7
movwf T2CON ; enable Timer 2 with 1:16 prescaler
movlw 0x0C ; enable single output PWM
movwf CCP1CON

loop This is not INIT code. Don't just blindly copy stuff without looking at it!
;-------------------- PROCESS AN0 -> PWM ------------------
; PWM controls brightness
; Assumes channel 0 is set
bsf ADCON0, GO ; start ADC operation
btfsc ADCON0, GO ; and wait for its completion
goto $-1
bsf ADCON0,CHS0 ; select channel 1 for NEXT convert, to let it settle
movf ADRESL,W ; read 2 lower bits of ADC
bcf STATUS, RP0
movwf temp ; save for shifts
rrf temp, f ; shift one right
rrf temp, W ; shift one right, dest is W
andlw B'00110000' ; strip other bits
bcf CCP1CON,5 ; clear CCP1CON 5:4 without affecting W
bcf CCP1CON,4
iorwf CCP1CON,F ; combine temp >> 2 with CCP1CON 5:4
movf ADRESH, W ; get high 8 bits of ADC
movwf CCPR1L ; setup PWM duty cycle

;========================================================================
; add the init code here in previous posts everything from ORG 0 to loop
;========================================================================

main_loop:
;-------------
;ON-1 ; Read flash rate for ON half of cycle
bsf ADCON0,CHS0 ; select channel 1 for NEXT convert, to let it settle
movlw .1 ; for 1 ms
movwf del
call delay
bsf ADCON0, GO ; start ADC conversion
btfsc ADCON0, GO ; and wait for its completion
goto $-1

;-------------
;ON-2
movf ADRESH,W ; get result
movwf FlashCounter ; to 1ms flash counter

;-------------
;ON-3
wait_while_LED_on:
bcf ADCON0,CHS0 ; select channel 0 for NEXT convert, to let it settle
movlw .1 ; for 1 ms
movwf del
call delay
bsf ADCON0, GO ; start ADC conversion
btfsc ADCON0, GO ; and wait for its completion
goto $-1

;-------------
;ON-4

;-------------
;ON-5
;-------------
;ON-6
movf ADRESH,W ; get result
movwf FlashCounter ; to 1ms flash counte
;-------------
;ON-7
decfsz FlashCounter,F
goto wait_while_LED_on

;-------------
;ON-8
; 'ON' time has elapsed. Turn PWM OFF by setting its duty cycle to 0%
; then proceed to time the OFF time.

movlw 0 ; use 'off' duty cycle value
movwf CCPR1L ; set PWM duty cycl
;-------------
;OFF-1 Added a subroutine for this
bsf ADCON0,CHS0 ; select channel 1 for NEXT convert, to let it settle
movlw .1 ; for 1 ms
movwf del
call delay

bsf ADCON0, GO ; start ADC conversion
btfsc ADCON0, GO ; and wait for its completion
goto $-1

;-------------
;OFF-2

movf ADRESH,W ; get result
movwf FlashCounter ; to 1ms flash counter

;-------------
;OFF-3
wait_while_LED_off:

;-------------
;OFF-4
movf ADRESH,W ; get result This does not decrement the counter, it loads it
movwf FlashCounter ; to 1ms flash counte
;-------------
;OFF-5

decfsz FlashCounter,F
goto wait_while_LED_off
goto main_loop ; 'OFF' time has elapsed, back the 'ON' sequence


;**************** UTILITIES ****************************
; procedures
; a delay for del milliseconds

delay
movlw .200
sublw 1 ; this loop takes 5us*200 = 1ms
sublw 0 ; for PIC16F684 @ 4 MHz
btfss STATUS, Z
goto $-3
decfsz del, f
goto delay
return

END
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
@Don Omar
OK, still making progress but you need to pay more attention to the content of what you are doing and avoid just block-copying code willy-nilly. I annotated your post above using my moderator super-powers to show some problems with that approach.
That said, I introduced the idea of using a subroutine for the 1ms delay so I wrote one for you. I also broke down and wrote a set of ReadADC routines incorporate the channel selection, delays etc. These post the conversion result in RAM so you don't have to switch banks to get the whole result. They also reduce the reading of the ADC to one call so you only have to debug the ADC read code one time. Same for the 1ms delay. Whenever you see the same thing being done over and over, consider a subroutine.

SO.. I fixed it up for you. You should see how I handled the fixes to init that I flagged and how much simpler the ON-x and OFF-x steps are getting since we now do common things in subroutines. I also combined steps ON-6 and ON-7 since using the decfsz instruction kind of does both. Same for the OFF cycle.

Here is the code. You still have to fill in the PWM blanks and the rest of the flowchart steps. A quick walkthrough on MPSIM said it should be getting close.
BTW: Your init is for 4 analog channels and you are using only two. You should fix that.

Have fun!
Code:
  TITLE "pwm_led.asm" ;
  List P=PIC16F684, R=DEC
  INCLUDE "p16f684.inc"
  ERRORLEVEL -302 ; suppress 'not in bank' messages

  ; data segment
  CBLOCK 0x20
  temp: ; local temp variable
  FlashCounter:1 ; declare one byte for 1ms flash counter
  del:1 ; delay parameter - 1ms increments

  ADCresultH:1  ; Left justified output of 'ReadADC' subroutine
  ADCresultL:1  ; high and low bytes.  dddddddd dd000000
  ENDC

  ; code segment
  __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

;****************** PROGRAM BEGINS ******************************

  ORG 0  ; start program at the beginning of mem

Init:
  clrf PORTA  ; initialize PORT A
  clrf PORTC  ; initialize PORT C
  movlw 0x07
  movwf CMCON0  ; comparators OFF

  ;----------------------------
  ;RAM BANK 1
  bsf STATUS,RP0  ; select memory bank 1
  movlw B'00001111'  ; RA0-RA3 are inputs
  movwf TRISA  ;
  movlw B'11000000'  ; RC6-RC7 are inputs
  movwf TRISC

  ; ADC and PWM configuration
  movlw B'00001111'  ; AN0 to AN3 are analog inputs
  movwf ANSEL  ; Bank 1
  movlw b'01110000'  ; set ADC Frc clock
  movwf ADCON1
  movlw 0xFF
  movwf PR2  ; PWM period 244Hz

  ;----------------------------
  ;RAM BANK 0
  bcf STATUS, RP0  ; back to BANK 0

  movlw B'00000001'  ; left justified A/D result, VDD as ref, ADC ON
  movwf ADCON0
  movlw B'00000111'
  movwf T2CON  ; enable Timer 2 with 1:16 prescaler
  movlw 0x0C  ; enable single output PWM
  movwf CCP1CON

main_loop:
  ;-------------
  ;ON-1  ; Read flash rate for ON half of cycle
  call  ReadADC_Ch1 ; ADC conversion ->ADCresultH,ADCresultL in RAM

  ;-------------
  ;ON-2
  movf  ADCresultH,W ; MSbyte of ADC is msec 'ON' time
  movwf  FlashCounter ; counts 1ms clicks

  ;-------------
  ;ON-3
wait_while_LED_on:
  call  ReadADC_Ch0 ; Channel 0 is PWM brightness
  ; returns value of ADC channel to RAM registers
  ;-------------
  ;ON-4

  ;** set PWM duty cycle from ADCresultH, ADCresultL in RAM **

  ;-------------
  ;ON-5


  ;-------------
  ;ON-6  ; test flash counter and loop if not 0 yet
  ;ON-7  ; both steps are done by the decfsz, sorry!
  decfsz FlashCounter,F
  goto wait_while_LED_on

  ;-------------
  ;ON-8
  ; 'ON' time has elapsed. Turn PWM OFF by setting its duty cycle to 0%
  ; then proceed to time the OFF time.

  movlw 0  ; set PWM duty cycle to 0%
  movwf CCPR1L  ; to turn LED off

  ;-------------
  ;OFF-1
  call  ReadADC_Ch1 ; Read channel 1 using subroutine

  ;-------------
  ;OFF-2
  movf  ADCresultH,W ; MSbyte of result is msec to delay
  movwf  FlashCounter

  ;-------------
  ;OFF-3
wait_while_LED_off:

  ;-------------
  ;OFF-4
  ;OFF-5
  decfsz FlashCounter,F
  goto wait_while_LED_off

  goto main_loop ; 'OFF' time has elapsed, back the 'ON' sequence


  ;**************** UTILITIES ****************************
  ; Two entry points:
  ; delay_1ms: delays for 1 ms always
  ; delay: delays for variable 'del' ms
  ; Expects/returns bank 0
delay_1ms:
  movlw  .1
  movwf  del
  ;*
delay:
  movlw .200
  sublw 1 ; this loop takes 5us*200 = 1ms
  sublw 0 ; for PIC16F684 @ 4 MHz
  btfss STATUS, Z
  goto $-3
  decfsz del, f
  goto delay
  return

  ;------------------- READ ADC  -------------------------
  ; Reads current channel of ADC, posts result in ADCresultH
  ; and ADCresultL in RAM so you don't have to read different
  ; banks each time.
  ;
  ; Expects, returns bank 0
  ; 3 Entry Points:
  ; ReadADC_Ch0  ; reads channel 0 (PWM brightness)
  ; ReadADC_Ch1  ; reads channel 1 (Flash Rate)
  ; ReadADC  ; reads current channel

ReadADC_Ch0:
  bcf  ADCON0,CHS0  ; select channel 0
  goto  ReadADC

ReadADC_Ch1:
  bsf  ADCON0,CHS0  ; select channel 1
  ;*
ReadADC:
  call  delay_1ms  ; let channel settle
  bsf  ADCON0,GO  ; start conversion

_waitADCdone:
  btfsc  ADCON0, GO  ; and wait for its completion
  goto  _waitADCdone

  movf  ADRESH,W  ; get MSbyte of conversion result
  movwf  ADCresultH
  bsf  STATUS,RP0  ; select bank 1
  movf  ADRESL,W  ; get LSbyte of conversion result
  bcf  STATUS,RP0  ; select bank 0
  movwf  ADCresultL
  return

  END
 

Thread Starter

Don Omar

Joined May 5, 2017
49
@Johnlntx

I dont know what i was going to do without you
Hey john i fixed the inputs and i add the 1ms elay for ON5
the only thing left i think is the PWM ON4 wish it does not make any sense to me

Code:
TITLE "pwm_led.asm" ;
  List P=PIC16F684, R=DEC
  INCLUDE "p16f684.inc"
  ERRORLEVEL -302 ; suppress 'not in bank' messages

  ; data segment
  CBLOCK 0x20
  temp: ; local temp variable
  FlashCounter:1 ; declare one byte for 1ms flash counter
  del:1 ; delay parameter - 1ms increments

  ADCresultH:1  ; Left justified output of 'ReadADC' subroutine
  ADCresultL:1  ; high and low bytes.  dddddddd dd000000
  ENDC

  ; code segment
  __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

;****************** PROGRAM BEGINS ******************************

  ORG 0  ; start program at the beginning of mem

Init:
  clrf PORTA  ; initialize PORT A
  clrf PORTC  ; initialize PORT C
  movlw 0x07
  movwf CMCON0  ; comparators OFF

  ;----------------------------
  ;RAM BANK 1
  bsf STATUS,RP0  ; select memory bank 1
  movlw B'00000011'  ; RA0-RA1 are inputs
  movwf TRISA  ;
  movlw B'11000000'  ; RC6-RC7 are inputs
  movwf TRISC

  ; ADC and PWM configuration
  movlw B'00000011'  ; AN0 to AN1 are analog inputs
  movwf ANSEL  ; Bank 1
  movlw b'01110000'  ; set ADC Frc clock
  movwf ADCON1
  movlw 0xFF
  movwf PR2  ; PWM period 244Hz

  ;----------------------------
  ;RAM BANK 0
  bcf STATUS, RP0  ; back to BANK 0

  movlw B'00000001'  ; left justified A/D result, VDD as ref, ADC ON
  movwf ADCON0
  movlw B'00000111'
  movwf T2CON  ; enable Timer 2 with 1:16 prescaler
  movlw 0x0C  ; enable single output PWM
  movwf CCP1CON

main_loop:
  ;-------------
  ;ON-1  ; Read flash rate for ON half of cycle
  call  ReadADC_Ch1 ; ADC conversion ->ADCresultH,ADCresultL in RAM

  ;-------------
  ;ON-2
  movf  ADCresultH,W ; MSbyte of ADC is msec 'ON' time
  movwf  FlashCounter ; counts 1ms clicks

  ;-------------
  ;ON-3
wait_while_LED_on:
  call  ReadADC_Ch0 ; Channel 0 is PWM brightness
  ; returns value of ADC channel to RAM registers
  ;-------------
  ;ON-4

  ;** set PWM duty cycle from ADCresultH, ADCresultL in RAM **
   movf  ADRESH,W  ; get MSbyte of conversion result
  movwf  ADCresultH
  bsf  STATUS,RP0  ; select bank 1
  movf  ADRESL,W  ; get LSbyte of conversion result
  bcf  STATUS,RP0  ; select bank 0
  movwf  ADCresult

  ;-------------
  ;ON-5
call  delay_1ms

  ;-------------
  ;ON-6  ; test flash counter and loop if not 0 yet
  ;ON-7  ; both steps are done by the decfsz, sorry!
  decfsz FlashCounter,F
  goto wait_while_LED_on

  ;-------------
  ;ON-8
  ; 'ON' time has elapsed. Turn PWM OFF by setting its duty cycle to 0%
  ; then proceed to time the OFF time.

  movlw 0  ; set PWM duty cycle to 0%
  movwf CCPR1L  ; to turn LED off

  ;-------------
  ;OFF-1
  call  ReadADC_Ch1 ; Read channel 1 using subroutine

  ;-------------
  ;OFF-2
  movf  ADCresultH,W ; MSbyte of result is msec to delay
  movwf  FlashCounter

  ;-------------
  ;OFF-3
wait_while_LED_off:
call  delay_1ms
  ;-------------
  ;OFF-4
  ;OFF-5
  decfsz FlashCounter,F
  goto wait_while_LED_off

  goto main_loop ; 'OFF' time has elapsed, back the 'ON' sequence


  ;**************** UTILITIES ****************************
  ; Two entry points:
  ; delay_1ms: delays for 1 ms always
  ; delay: delays for variable 'del' ms
  ; Expects/returns bank 0
delay_1ms:
  movlw  .1
  movwf  del
  ;*
delay:
  movlw .200
  sublw 1 ; this loop takes 5us*200 = 1ms
  sublw 0 ; for PIC16F684 @ 4 MHz
  btfss STATUS, Z
  goto $-3
  decfsz del, f
  goto delay
  return

  ;------------------- READ ADC  -------------------------
  ; Reads current channel of ADC, posts result in ADCresultH
  ; and ADCresultL in RAM so you don't have to read different
  ; banks each time.
  ;
  ; Expects, returns bank 0
  ; 3 Entry Points:
  ; ReadADC_Ch0  ; reads channel 0 (PWM brightness)
  ; ReadADC_Ch1  ; reads channel 1 (Flash Rate)
  ; ReadADC  ; reads current channel

ReadADC_Ch0:
  bcf  ADCON0,CHS0  ; select channel 0
  goto  ReadADC

ReadADC_Ch1:
  bsf  ADCON0,CHS0  ; select channel 1
  ;*
ReadADC:
  call  delay_1ms  ; let channel settle
  bsf  ADCON0,GO  ; start conversion

_waitADCdone:
  btfsc  ADCON0, GO  ; and wait for its completion
  goto  _waitADCdone

  movf  ADRESH,W  ; get MSbyte of conversion result
  movwf  ADCresultH
  bsf  STATUS,RP0  ; select bank 1
  movf  ADRESL,W  ; get LSbyte of conversion result
  bcf  STATUS,RP0  ; select bank 0
  movwf  ADCresultL
  return

  END
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
the only thing left i think is the PWM ON4 wish it does not make any sense to me
The PWM drives the LED at the brightness level set by the duty cycle which is in turn set by the value of CCPR1L. As the flow chart says
Read ADC channel 0
Put that value into CCPR1L to set the duty cycle


Slow down and read my previous post AND the comments in the ReadADC_Ch0 subroutine i.e.
posts result in ADCresultH and ADCresultL in RAM so you don't have to read different
banks each time.
Also, look at the other places where ReadADC is used to see how to call it and how to use the result.
So after you call the read ADC routine in ON-3 where is the result and what do you do with it? True it is still in ADRESH but the subroutine is designed to put the result in those RAM registers for your convenience so you don't have to change banks to get the lower byte of the result from the PIC's ADC result registers directly. Take the time to read through that subroutine, line by line, then you'll understand how to use it. Where the flow chart refers to ADCRESH, use ADCresultH.

Be sure to look at Figure 11-3 SIMLIFIED PWM BLOCK DIAGRAM in the datasheet for PWM operaton.
 
Last edited:
Top