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.

Using a PIC to async a 16 bit ADC..

Not open for further replies.


Well-Known Member
Hi, I've got to send a 16-bit lot of data, wireless (ie, radio, IR) and I'm using a serial ADC. I need a way to add start/stop bits to the signal.
The output from the ADC is as follows, with CS held low, each sample consists of 8 '0's (for sampling time) and then the 16 data bits. Does anyone think its possible simply to use a PIC to output a zero(start bit), then move the data from the ADC to the output of the PIC (basically, connect the adc to the output of the system) and then, after 16 CLK's, and a stop bit and wait 6 CLK's, to then output the second start bit. I know this sounds basic bit its proving to be a lot harder than I anticipated, I'm thinking about using a simple PLD for the job.

Just to re-itterate: All I'm doing is adding start and stop bits to the original signal coming OUT of the ADC (00000000111111111111111) <--assuming that the ADC is sampling its highest value.

So it becomes: (0000'S'1111111111111111'St'00) note: the stop bit is actually added when the sampling time begins, since I need to use the first eight '0's to add start AND stop bits. I oppologise for the state of this message, I'm completely confused :(
Well all you have to do is get your data into the pic in a word size variable.

Something like this:

2. SAVE BITx into VAR1.x (VAR1 as word)
3. x = x+1
4. Do 16 times (1 and 2)
5. Send STARTBIT thru PINA
6. X=1
7. Send VAR1.x thru PINA
8. CLOCK receiving device
8. x = x+1
9. Do 16 times (7 and 8 )
10. Send STOP bit
11. CLOCK 6 times
12. goto (1)

I know that you probably knew how to do that.
You can do it with PICBASIC PRO, good luck. :wink:

Thanks for replying so quickly.
I'm not fully familiar with PIC programming but I have done a fair bit of work with the 8051 (+variants) and PLDs/FPGAs, I have thought about doing it the way you suggested, in fact, I've got some notes here I made which look exactly the same (almost word-for-word)!!

However, like always I tend to over-compliacate things by trying to make them simpler, a contradiction in terms, I know.

So what are saying is store the information provided by the ADC in registers, then send the start bit, data then stop bit. Ideally this is how it should be done, but, its a bit confusing considering the comstraints on the system, which I probably should have included in my first thread.

Theses are :

1)Sample rate > 30Khz - which means that a mimimum of 18*30000Bps is required. = 480kbs. (16 data, start/stop). BUT, this would mean that the ADC and PIC would be out of sync and data will constantly be accumulated and eventually lost. Because of the 8 '0's pause, data would be sent in pulses with a 6 bit gap. Hence the ACTUAL frequency of the data is 24*30000 = 720kbs. I think thats right??!

1a)Just remembered another one. The clock that the ADC runs off of determinds the sample rate. ie sample rate = CLK/24. It derectly determinds the rate of the data produced by the ADC.

2)Ideally the PIC and the ADC should be in sync, hence running off the same clock, or the ADC can run off of an integer of the clock, ie: CLK/2

3)This is the killer....delay between the sample and the end of the transmitted data should be kept to an absolute minimum. This is why I wanted a rather unorthadox approach, such as, while the ADC is in its 8 '0's I could output a start bit, then just move data from the input port(ADC) to the output port (to IR LED/radio), then, when its finished, outputing a stop bit during the next conversion.

I'm not planning on using this system with any existing standards, my own design of Tx and my own Rx, as long as they have the same rules it should be fine.

I'm completely confused. But I have been trying to make the ADC run at its minimum data rate, so its constantly sampling rather than having gap between each sample. I suppose I could run it at double the sample rate and tell it to sample, retreive the data, send the data out through the PIC and then smaple again. With me? I'm not :)
I think I am not following you quite all the way.

1)Sample rate > 30Khz - which means that a mimimum of 18*30000Bps is required. = 480kbs. (16 data, start/stop)

Actually it wold be more like 540kbs. A PIC using a 4MHz crystal has a speed of 1usec per instruccion cycle. Now you can even get a 20Mhz PIC and have plenty of speed to generate the sample rate at 200nsec per instruction cycle.

You can't do multitask with a PIC, so forget about receiving data while sending the data. YOu have to read the data from the ADC into the PIC register, and output it with the STOP/START bits you need.

Also the PIC would be generating the CLOCK signal to the ADC. The PIC would be consider the "Master" and the ADC the slave. You mention you would like to have a same clock for the PIC and ADC and that would completly would not allow the microcontroller do it's magic. You should let the microcontroller cotrol :)

How fast do you really have to have your analog data converted and transmited?

Since it is a serial ADC you need two I/O from the PIC, one you make it the CLOCK, and the other one the DataIN. YOu are going to have a DataIN ready for you to read for each CLOCK pulse you send. So you control the clock speed.

If you really want to keep close track of the time and generate a faster code you will have to program in assembly.

Hope it gives you some ideas

finally, I understand!!!


Thankyou so much for your advice, after re-reading your last post about 10 times it finally sunk in what you were suggesting :idea: , you see, I'm not very good at explaining/understanding ideas from words, i'm much more of a diagram person. :D

So, lets assume the ADC has no aquisition time, just for convenience.
The PIC sends one clock pulse to the ADC, then moves the data from the input (ADC), to the output (or a register, then the output). And this process is repeated for all 16 bits. correct? It seems like it the simplest way, didn't think of it before :oops:

With the above process I could send the data 'on the fly' as opposed to storing all 16 bits in a 'buffer', reducing the delay tremendously.

When you first mentioned clocking the adc from the PIC I assumed that the data would be aquired from the ADC ...and then sent to the serial-out.

How fast do you really have to have your analog data converted and transmited?

Well the minimum samplle rate is about 25khz. The minimum resolution is 16 bits. And the delay bewteen the time the sample is taken (at the transmitter) to the time when the DAC at the reciever outputs the analogue voltage must be less than 10ms. So I want the delay from the sample to the last bit transmitted to be as small as possible, hence my hesitation to 'buffer' the data. However, there is room for some delay, about 2ms.

With the 'on the fly' the speed of the data coming out of the PIC will be the same as the data coming from the ADC, this is the most efficient way, bandwidth wise, because outputing the data very quickly leaves a BIG gap between frames in the bit stream. Meaning that the highest frequncy in the bit stream is higher than the baud. - sorry, I'm babling :oops:

Now I just need to learn the basic instructions for the PIC, I'm well versed in assembly (8051) I assume it can't be that different.

Now I just need to find a crystal to give me a decent sample rate. 20MHz/4= 5MHz, for every bit retrieved from the ADC reqires 3/4 instructions (2 for clock, and 1/2 to move data). I was hoping that the chip would have a timer or something thats independent of the program but I don' think they work that way. Anyway, for 16 bits that 16*4 = 64. 16 more are need to clock the ADC during the aquisition time and 3 more for start,stop and 'return to zero' giving 83 minimum.
That takes: 0.2 * 83 = 16.6us. For a sample rate of 25khz, the total time allowed for the program to run is 1/25k = 40us, nice! enough room to make things easier. Sorry for all the maths, I'm just typing what I'm thinking.

Thanks again man, you've been a lot more help than my lecturers, who told me that going digital was too much hard work. :!:


I was hoping that the chip would have a timer or something thats independent of the program but I don' think they work that way.

Even the lowly 16F84 has timer0 which can generate a periodic interrupt. To get a 25Khz from a 20Mhz crystal, the ff. calculations apply:

20Mhz -> 5Mhz instruction clock.

Prescale value = 1:2 -> timer0 clock input = 2.5Mhz

Initialize timer to -100 (9Ch). This results in a 100:1 clock divide (2.5Mhz/100 = 25Khz). When timer0 overflows to 0, in the interrupt service routine, use the ff. code to reload the counter. There is a slight error because the prescale counters are reset during timer0 reload.

    MOVLW    -100

Mid-range level PICs (e.g. 16F627) have more timers and the capture/compare module to give a more precise timer function. No need to do a software reload like above.
Oops upon further review..., it seems you need a faster bit rate than 25Khz. The 10ms and 2ms values threw me off.

Anyway, you can use the SPI modules in PIC16F87Xs to reduce the PIC's load. Since SPI is only 8-bits, you may have to read-in the 16-bit data in two steps.
Cheers motion, I think I've got a final idea that I'm about to convert to code. I was initally going to use SPI, since the ADC has a SPI compatable port, but as I explained above I'm very reluctant to use anything that will cause delay of any length. In a ideal world the data will come straight from the ADC to the transmitter, but this isn't an ideal world, so I'm basically just using the PIC to add the start and stop bits around the data. The data itself is moved from the input pin, to a register and then to an output pin, so really its like connecting the ADC directly to the transmitter. As far as I can tell this seems to be the simplest, most effient way for my system as it does not need to be compatible with any standards, just my own reciever. :shock:

About timers. I've been reading up about watchdog timers, since my system will be constantly sampling for however long the unit is switched on, I personally think its a good idea. Also, I could use the timer to initiate the sample (taking the sample and sending it off is basically the entire code) this means that I could have a nice round sample rate, that's not purely based on the number of instructions and the CLOCK. For example. for 104 instructions with a 20Mhz crystal. the program will run
48076.92 times a second. - Not an ideal sample rate, but high enough.
The timer could be set to make the program run 40k per second, a better number.

Again, I would like to thank Ivancho (and motion) for your patience and your help. Although this is for a Degree project, I've got the 'PIC bug' now, and currently have a 5 page list of applications I would like to use it for. :D
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips