Let's Make Robots!

how to setup a PIC for A/D and PWM?


After some tries, i realy got some problems with making my PIC 16F876A working right.

I need it to be able to A/D konvert 3 analog inputs, 1 where it need to be able measure lenght (10-30cm), and the 2 others it only need to be able to see if there is someting or not. For detection objects.

I also need to use the 2 PWM outputs, where it shall be able to switch between speeds (slow and fast) Think i got the PWM to work on a 16F628.

Couting on using an ekstern 20Mhz crystal.

Right now, 1 of my problems is also that i think the __config isent set correct, but i cant figure out how to set it right.

I am writing the code in Asseamble. Using MPLAB with a picstart plus burner.

Not so good at making software, and it is begining to get on my nerves, that i cant get it to work right.

But the good news, is that my motor controller is finaly working :0)

This code, i will have a trim meter (10K ohm) at AN0, and then by turning the trim meter, i will have a binar reading on port B0-B7. But it wont work.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

What does the _DATA_CP_OFF do?

Cant get it to work, and i cant find it in the datasheet. My program says Symbol not previously defined.

Hi, Thanks for that info about the .INC file, dident know that there where 1.

Isent it confusing if i write all those OFF and ON instead of a binar value?

About the crystal, a friend told me it will work better if i where using a ekstern crystal. Until i get a crystal, i will use 20MHz for oscillator. But isent it by default set to oscillat at 20MHz?

This code i have postet is just a experiment to get the A/D converter to work. In my projekt it will have 3 Analog inputs:

1 from a sharp sensor(forward), and 2 from some IR detectors(L and R side) i have made by my self.

Where the sharp sensor is to tjeck if there is any objects in range (30cm), and if the range to an object is under 30cm then the PIC will turn the PWM down so the robot will drive forward in slow speed.

And then if any object is under 10cm then the PIC will make the robot stop, then turn and drive in another direction. 

The advantage of using BOREN_OFF, etc in the config word is that you can look at the command and immediately know that, for example, the Brown-Out Reset Enable (BOREN) is Off. You don't have to keep referring back to the datasheet this way.

The processor will run faster with a good external crystal, but you need to tell the micro to use the internal oscillator until you have an external oscillator connected. Since you've set the oscillator options to HS (High Speed external) in the config, the PIC will not use the default.

   LIST P=16F876A, W=2, X=ON, R=DEC
    __CONFIG    b'11111100111010'


#define bank1 bsf STATUS,RP0
#define bank0 bcf STATUS,RP0

count EQU 0x20 ; variabel til delay

 org 0x00
 goto fire
 org 0x0a


fire nop
 call init

igen bsf ADCON0,2 ; Start konvertering
vent btfsc ADCON0,2 ; Vent på den er slut
 goto vent
 movf ADRESH,W ; Flyt 8 højeste bit til W
 movwf PORTB  ; Skriv værdi på portB
 call delay  ; ikke køre for hurtigt
 goto igen  ; Start forfra


init nop
 bcf STATUS,RP1 ; RP1 sættes til 0
    ; bank 0 og 1 vælgws via
    ; mine defines
 clrf TRISB  ; hele B-porten er udaf
 bsf TRISA,0  ; indaf til analog sp.



 bsf ADCON0,7 ; 20 MHz cryst.
 bcf ADCON0,6 ; Neddeling med 32

 bcf ADCON0,5 ; En fast kanal til konvert.
 bcf ADCON0,4 ; Der bruges AN0
 bcf ADCON0,3 ; Kanalen styres af 3 bit

 bcf ADCON1,7 ; Venstrestil de 10 bit

 bcf ADCON1,3 ; Der konverteres fra max.
 bcf ADCON1,2 ; 5 kanaler. Jeg bruger 1.
 bsf ADCON1,1 ; Der konverteres ml. 0 og 5 V.
 bcf ADCON1,0 ; Styres af 4 bit.

 bsf ADCON0,0 ; Sæt strøm på converteren

 ;****** SLUT PÅ OPSÆTNING AF CONVERTER*****************************



delay nop
 clrf count
again decfsz count
 goto again



An easier way to set the _config word is to use a command like this:
Inside the PIC16F876A.INC file is a list of bit masks for each of the config options, so you can just AND them together to make the _config word. I recommend opening PIC16F876A.INC and having a look so you know what's in there.

You say you are "Couting on using an ekstern 20Mhz crystal.", does this mean you don't have one yet? If not, what oscillator are you using?

There is (usually) no need for a NOP after a label, you can just straight into the first subroutine instruction.

Between when the A/D Converter is enabled, and when you tell it to start converting, you need a short delay to proper initialise the A/D module. Two consecutive calls to 'delay' should do it.

Why don't you post your code, and a list of what settings you're trying to implement?