Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

pwm and 16F877A

Status
Not open for further replies.

williB

New Member
i have a problem with the 877A
Below i've recycled a Pwm pgm which worked on a F88 , but needed some changes on the 877A
specifically the 877 has no ANSEL register , it took me a few hours to essentially remove two lines and correct the bits put into ADCON1
i was able to load the program into the F877 and run it ,which may not sound like much , but for me it was alot.
no joy on the either ccp/pwm pin :(

is there anything in the factory config settings , that would prevent this from working? because i havnt changed them
pwm is not my strong suit, which is why i checked both outputs :)
if someone could check the pwm for me i would be very greatfull

the Fosc is 5 Mhz but i can divide it down with counters if needed , i'm looking to get 20 - 25 khz varible pwm out
thanks for reading :)






Code:
        LIST    P=16F877A 
        include "P16F877A.inc" 
        errorlevel      -302    ;Eliminate bank warning
                          
TEMP    EQU     0x20 
ADON    EQU     0X00 
ADIF    EQU     0X06 
GO_DONE EQU     0X02 
TMR2ON  EQU     0X02 
TMR2IF  EQU     0X01 
RP0     EQU     0x05 
RP1     EQU     0x06 
W                            EQU     H'0000' 
F                            EQU     H'0001' 

;----- Register Files------------------------------------------------------ 

INDF                         EQU     H'0000' 
TMR0                         EQU     H'0001' 
PCL                          EQU     H'0002' 
STATUS                       EQU     H'0003' 
FSR                          EQU     H'0004' 
PORTA                        EQU     H'0005' 
PORTB                        EQU     H'0006' 
PCLATH                       EQU     H'000A' 
INTCON                       EQU     H'000B' 
PIR1                         EQU     H'000C' 
PIR2                         EQU     H'000D' 
TMR1L                        EQU     H'000E' 
TMR1H                        EQU     H'000F' 
T1CON                        EQU     H'0010' 
TMR2                         EQU     H'0011' 
T2CON                        EQU     H'0012' 
CCPR1L                       EQU     H'0015' 
CCPR1H                       EQU     H'0016' 
CCP1CON                      EQU     H'0017' 
RCSTA                        EQU     H'0018' 
TXREG                        EQU     H'0019' 
RCREG                        EQU     H'001A' 
ADRESH                       EQU     H'001E' 
ADCON0                       EQU     H'001F' 

OPTION_REG                   EQU     H'0081' 
TRISA                        EQU     H'0085' 
TRISB                        EQU     H'0086' 
PIE1                         EQU     H'008C' 
PCON                         EQU     H'008E' 
PR2                          EQU     H'0092' 
TXSTA                        EQU     H'0098' 
SPBRG                        EQU     H'0099' 
EEDATA                       EQU     H'010C' 
CMCON                        EQU     H'009C' 
EECON2                       EQU     H'018D' 
ADRESL                       EQU     H'009E' 
ADCON1                       EQU     H'009F' 



        org     0x00 		; Reset Vector
                                        
        clrf    PORTA      	;B0           
        clrf    PORTB           ;B0
        CLRF    STATUS 		;B0
          			;B0
	Banksel TRISA		;B1 
        CLRF    TRISA 		;B1
        CLRF    TRISB 		;B1
				;B1
        BCF     STATUS ,RP0 	;B0
				;B0
        CLRF    T2CON 		;B0
        MOVLW   D'000' 		;B0
        MOVWF   CCPR1L 		;B0
        BSF     STATUS,RP0 	;B1
        MOVLW   d'255'-1 	;B1
        MOVWF   PR2 		;B1
        BCF     STATUS,RP0 	;B0
        MOVLW   b'00001100' 	;B0
        MOVWF   CCP1CON 	;B0
        BSF     T2CON,TMR2ON 	;B0
				;B0
        BSF     STATUS,RP0 	;B1
        MOVLW   b'00000001'	;B1 
        MOVWF   TRISA 		;B1
       				;B1
	                       	;B1
        MOVLW   b'10001111' 	;B1  AN0 as input: AN2 as Vref- 
        MOVWF   ADCON1 		;B1  : AN3 as Vref+
        BCF     STATUS,RP0 	;B0
        MOVLW   b'01000000' 	;B0
        MOVWF   ADCON0 		;B0
        BSF     ADCON0,ADON 	;B0 turn on A2D
        CLRF    PIR1 		;B0
				;B0
LOOP    CALL    ADC 		;B0
        MOVWF   CCPR1L 		;B0
        GOTO    LOOP 		;B0
				;B0
ADC     BTFSS   PIR1,TMR2IF 	;B0
        GOTO    ADC 		;B0
        BCF     PIR1,TMR2IF 	;B0
				;B0
        MOVF    ADRESH,W 	;B0
        BSF     ADCON0,GO_DONE 	;B0
        RETURN 

        END
 
ok Programming these little beasties is not my strong suit , at all.
something just isnt clicking , if ya'll could consider me a noob programmer that would be fine

constructing and interfacing sensors i'm not too bad at
designing digital and analog circuits also not to bad at
i was once a little better at programming PICs but after a year of not trying to program them , alot escapes me :)
i understand the interactions of the various components on earlier uProcessors , but the PICs have you jumping all over the place to get ANYTHING done. for example on the F877a , to set the analog input pin to RA0 , and Vref+ and Vref- pins required setting bits on both the ADCON1 and ADCON2 registers , not too bad ,but the pwm i dont think i understand at all !! and timers forget it. :(
i dont expect anyone to try and explain it , but if it was presented from a different point of view in the data sheets that might help , i'm not sure

i've used Mikekl8h's method for keeping track of the banks , that helps .
again thanks for reading and any help with the program would be greatly appreciated
 
ok lets analyze your program if you dont mind?

why are you bank selecting PORTA , fourth instruction down.

for those as little unsure , Banksel is an assembler directive for setting the current bank
**broken link removed**
this is a good source of info on assembler directives there may very well be an explaination in MPLab , but i couldnt find it.

i understand banksel ADCON1 , and then using it , but i dont understand why you would select bank 0 ,Banksel PORTA ,and do nothing once you get there?


Code:
Initialise:
    	BANKSEL  ADCON1		;turn off A2D
    	MOVLW    0x06
    	MOVWF    ADCON1
    	BANKSEL  PORTA
    	BANKSEL  TRISC
    	MOVLW    0		;set PORTC as all outputs
    	MOVWF    TRISC
    	BANKSEL  PORTC

   	MOVF     CCP1CON,W	;set CCP1 as PWM
    	ANDLW    0xF0
    	IORLW    0x0C
    	MOVWF    CCP1CON

    	MOVF     CCP2CON,W	;set CCP2 as PWM
    	ANDLW    0xF0
    	IORLW    0x0C
    	MOVWF    CCP2CON

    	MOVLW    126		;set highest PWM value
    	BANKSEL  PR2		;over this (127) is permanently on
    	MOVWF    PR2
    	BANKSEL  TMR2

    	MOVF     T2CON,W	;set prescaler to 16
    	ANDLW    0xF8		;PWM at 2500HZ
    	IORLW    0x02
    	MOVWF    T2CON

    	MOVF     T2CON,W	;set postscaler to 1
    	ANDLW    0x07
    	IORLW    0x00
    	MOVWF    T2CON
    	
    	CLRF	CCPR1L		;set PWM to zero
    	CLRF	CCPR2L

    	BSF      T2CON, TMR2ON	;and start the timer running
	RETURN
 
williB said:
ok lets analyze your program if you dont mind?

why are you bank selecting PORTA , fourth instruction down.

for those as little unsure , Banksel is an assembler directive for setting the current bank
**broken link removed**
this is a good source of info on assembler directives there may very well be an explaination in MPLab , but i couldnt find it.

Try the MPASM helpfile, as it's an assembler directive, which MPLAB simply calls (MPLAB isn't an assembler).

i understand banksel ADCON1 , and then using it , but i dont understand why you would select bank 0 ,Banksel PORTA ,and do nothing once you get there?

Simply to return to bank 0, in this case I could have dispensed with it, because immediately afterwards I change banks again:

Code:
    	BANKSEL  PORTA
    	BANKSEL  TRISC

These two lines aren't really needed, but don't do any harm (apart from wasting a few bytes) - mostly it's because the sections of code were cut and pasted there, but also because it's a REALLY BAD idea not to keep account of the bank you're in.
 
Fair enough :)
I also see why you are ANDing & ORing the the CCP1CON & CCP2CON , because whatever is in there the lower four bits will allways end up as b'xxxx1100', when ANDed and ORed with those values

after this it starts getting fuzzy i'll go back and study what you have written about the next section
thanks!
 
The next step is to set T2CON, this sets the frequency of the PWM, as it's derived from the 20MHz system clock it runs too at too high a frequency, there are two possibilities here - setting the prescaler divides the frequency before the PWM section, and the postscaler afterwards. For this example we set the prescaler to divide by 16, this gives us a PWM frequency of 2500Hz.
i'm a little confused here 20Mhz/ 16 is 1250khz , what am i missing?

EDIT: now i see , i think.
the pwm period = (pr2+1) (4)(Tosc)(Prescale value)
 
Last edited:
so with a PR2 value of 0x7F and a Fosc of 10Mhz & a prescale of one
should give me a 19.53Khz pwm frequency .
right?
ok i'm getting some wierd numbers for the duty cycle or what to load into ccpr1L & the two bits of ccp1CON <5>& <4>..??
10 bits is 1024 resolution , but when i calculated the resolution i got 8.97 bits , what does that mean?
 
williB said:
so with a PR2 value of 0x7F and a Fosc of 10Mhz & a prescale of one
should give me a 19.53Khz pwm frequency .
right?
ok i'm getting some wierd numbers for the duty cycle or what to load into ccpr1L & the two bits of ccp1CON <5>& <4>..??
10 bits is 1024 resolution , but when i calculated the resolution i got 8.97 bits , what does that mean?

The amount of resolution is dependent on the speed of the PWM, once the PWM gets above a certain figure you start to lose resolution - there's a chart in the datasheet that gives representative values.

Check page 212 of the mid-range reference manual, at 20MHz you can get 10 bit resolution upto 19.53KHz.
 
It was actually Mike, K8LH who did the work , with helping me out , with the origional PWM code for the F88.
all i did was realize the F877A didnt have an analog register that the F88 did ,the ANSEL register i believe is not on the F877A

in fact the code segment below , which i changed myself , is not right , because with the MSB as a ONE , only gave me two bits of resolution ,four possible states or values, because it changed the justification ,which was interresting to see one scope BTW

Code:
 MOVLW   b'10001111' 	;B1  AN0 as input: AN2 as Vref- 
 MOVWF   ADCON1 	;B1  : AN3 as Vref+

But i did sucessfully change and use the Vref+ and Vref- pins , whoopdidoo..

I guess what i want to say is Thank you Mike, K8LH !!
 
I thought i would share the joy of having a program run
below ive included the assembly code and the hex code for pwm on a 16F877A .
the PWM is varible by connecting a 10K varible resistor (pot) between ground and +5V and using the wiper output as the analog input to pin 2.
Pin 17 is the PWM output
Pin 2 is the analog input pin
Pin 4 is the Vref- (can be connected to ground)
Pin 5 is the Vref+ ( can be connected to 5V ) or lower if need be.

one more thing i havnt changed the config bits yet so it runs on a 'stock' chip if you notice there are no config bit settings at the beginning of the assembly listing

the electrotech online wouldnt let me list the whole .lst file , sorry .
but if you copy and paste the source , and save it as a .asm file then run MPASM it will create one.

the assembly code
Code:
        LIST    P=16F877A 
        include "P16F877A.inc" 
        errorlevel      -302    ;Eliminate bank warning
                          
TEMP    EQU     0x20 
ADON    EQU     0X00 
ADIF    EQU     0X06 
GO_DONE EQU     0X02 
TMR2ON  EQU     0X02 
TMR2IF  EQU     0X01 
RP0     EQU     0x05 
RP1     EQU     0x06 
W                            EQU     H'0000' 
F                            EQU     H'0001' 

;----- Register Files------------------------------------------------------ 

INDF                         EQU     H'0000' 
TMR0                         EQU     H'0001' 
PCL                          EQU     H'0002' 
STATUS                       EQU     H'0003' 
FSR                          EQU     H'0004' 
PORTA                        EQU     H'0005' 
PORTB                        EQU     H'0006' 
PCLATH                       EQU     H'000A' 
INTCON                       EQU     H'000B' 
PIR1                         EQU     H'000C' 
PIR2                         EQU     H'000D' 
TMR1L                        EQU     H'000E' 
TMR1H                        EQU     H'000F' 
T1CON                        EQU     H'0010' 
TMR2                         EQU     H'0011' 
T2CON                        EQU     H'0012' 
CCPR1L                       EQU     H'0015' 
CCPR1H                       EQU     H'0016' 
CCP1CON                      EQU     H'0017' 
RCSTA                        EQU     H'0018' 
TXREG                        EQU     H'0019' 
RCREG                        EQU     H'001A' 
ADRESH                       EQU     H'001E' 
ADCON0                       EQU     H'001F' 

OPTION_REG                   EQU     H'0081' 
TRISA                        EQU     H'0085' 
TRISB                        EQU     H'0086' 
PIE1                         EQU     H'008C' 
PCON                         EQU     H'008E' 
PR2                          EQU     H'0092' 
TXSTA                        EQU     H'0098' 
SPBRG                        EQU     H'0099' 
EEDATA                       EQU     H'010C' 
ANSEL                        EQU     H'009B' 
CMCON                        EQU     H'009C' 
EECON2                       EQU     H'018D' 
ADRESL                       EQU     H'009E' 
ADCON1                       EQU     H'009F' 



        org     0x00 		; Reset Vector
                                        
        clrf    PORTA      	;B0           
        clrf    PORTC           ;B0
        CLRF    STATUS 		;B0
          			;B0
	Banksel TRISA		;B1 
        CLRF    TRISA 		;B1
        CLRF    TRISC 		;B1
				;B1
        BCF     STATUS ,RP0 	;B0
				;B0
        CLRF    T2CON 		;B0
        MOVLW   D'000' 		;B0
        MOVWF   CCPR1L 		;B0
        BSF     STATUS,RP0 	;B1
        MOVLW   d'254'   	;B1
        MOVWF   PR2 		;B1
        BCF     STATUS,RP0 	;B0
        MOVLW   b'00001100' 	;B0
        MOVWF   CCP1CON 	;B0
        BSF     T2CON,TMR2ON 	;B0
				;B0
        BSF     STATUS,RP0 	;B1
        MOVLW   b'00000001'	;B1 
        MOVWF   TRISA 		;B1
       				;B1
	                       	;B1
        MOVLW   b'00001111' 	;B1  AN0 as input: AN2 as Vref- 
        MOVWF   ADCON1 		;B1  : AN3 as Vref+
        BCF     STATUS,RP0 	;B0
        MOVLW   b'01000000' 	;B0
        MOVWF   ADCON0 		;B0
        BSF     ADCON0,ADON 	;B0 turn on A2D
        CLRF    PIR1 		;B0
				;B0
LOOP    CALL    ADC 		;B0
        MOVWF   CCPR1L 		;B0
        GOTO    LOOP 		;B0
				;B0
ADC     BTFSS   PIR1,TMR2IF 	;B0
        GOTO    ADC 		;B0
        BCF     PIR1,TMR2IF 	;B0
				;B0
        MOVF    ADRESH,W 	;B0
        BSF     ADCON0,GO_DONE 	;B0
        RETURN 

        END

the listing file
Code:

the hex output
Code:
:020000040000FA
:10000000850187018301831603138501870183120C
:100010009201003095008316FE30920083120C305E
:10002000970012158316013085000F309F00831250
:1000300040309F001F148C011F2095001C288C1C31
:0A0040001F288C101E081F15080071
:00000001FF
 
williB said:
one more thing i havnt changed the config bits yet so it runs on a 'stock' chip if you notice there are no config bit settings at the beginning of the assembly listing

The 'stock' setting for the config include,
Watchdog Timer On

So, I think your code is reseting every so often due to the WDT (and lack of CLRWDT). It obviously makes no difference at the moment as your code simply resets and continues doing the same thing. However, if you add more functionality, then this could cause a problem.

Anyway, well done on getting it working. Have you a particular use for this code now it is working?

Mike.
 
Yes , i use pwm all the time to cut foam , when i'm makeng foam windmill blades.
it makes a really nice way to adjust/ Control the current through a stainless wire when cutting foam.
it starts cutting at about .5A , and i usually run it at .75A , also since i got it going at 20kHZ i may try to use it in a boost converter .
 
williB said:
one more thing i havnt changed the config bits yet so it runs on a 'stock' chip if you notice there are no config bit settings at the beginning of the assembly listing

It's essential that you set the config bits - it's not a 'default' setting if you don't, just an unprogrammed one, and the settings from that are unlikely to be the ones you want!.

If you can't be bothered to write the massive string required (I never can!), just use the hexadecimal value like my tutorials do.

As pommie suggested, the blank setting includes the watchdog timer, which isn't a good idea!.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top