@johnlntxThe 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.
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.
hey john,
this is what i did for ON4
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 ReadADC
movwf CCPR1L
;-------------
;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: