|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
Incorrect output from pic16f877 |
Posted: Sun Nov 12, 2006 8:18 pm |
|
|
I'm tryin to integrate an A/D converter ADS7816 with a PIC16F877. Without adding the ADC, i've programmed my pic with the following code.
Code: | #include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000) //tell compiler clock is 20Mhz for delay function
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) //baud rate 9600; output pin C6; input pin C7;
void main(){
/*Declare Variables*/
int8 msb,lsb; // 8 bit upper,lower, bit storage
int16 result;
//defined as char for transmitting using putc()
/*Initialise Ports*/
//Settings: input 1 output 0; Format: Port7-Port0; Default:inputs;
//set port A for analog and digital input/output
set_tris_A(0b01111110); //set Port A7 as output or CS ADC
set_tris_C(0b10110111); //Port C6:tx to rx232 & C3: SCK to ADC
//Programming C5=SDO as input, SPI module only receives data
set_tris_E(0b1111110);//Port E2 (CS) for ADC
output_high(PIN_E2); //switch off CS for external ADC
/*Setup SPI*/
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16);
//master mode, trigger low to to high edge, spi clock:20/16=1.25Mhz, T=0.8us
output_high(PIN_A0); //show SPI has started up
delay_ms(3); //delay for microcontroller to get ready
/*Data Acquisition & Transmission*/
while(true){
output_low(PIN_E2); //chip select for ADC
delay_us(2); //wait for data conversion 2 clk cycles (1.6us)
msb=spi_read(0); //1 byte (8bits) filled. |B11|B10|B9|B8|B7|B6|B5|B4|
lsb=spi_read(0); //first 4 bits filled. last 4 bits repeated. |B3|B2|B1|B0|---|B1|B2|B3|B4|
output_high(PIN_E2); //stop ADC read (required by ADC) Hi to Lo to restart
result = make16(msb, lsb);
result >>= 3;
putc(msb); //transmit upper bits
putc(lsb); //transmit lower bits
delay_ms(4); // Delay: Sample every 4ms for sampling of 250Hz for ECG
}
} |
my tx pin keeps fiving me rubbish.. i tot it shld give mostly bits zero when i input 0V into the SPI pin (C4) and mostly bits one if i input 5V in. Am i wrong? or is my code wrong? My email address is ghostz13[at]hotmail[dot]com. Thanks in advance. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Nov 12, 2006 8:37 pm |
|
|
You're sending the raw data. You need to convert it to ASCII characters
so that it can be displayed in the terminal window.
Get rid of the two putc() statements, and use a printf() statement instead.
The following line will display the result in Hexadecimal:
Code: | printf("%LX \n\r", result); |
Also, you need a delay in your loop of much more than 4 ms.
Try using 500 or 1000 ms. That's much more reasonable, if your
goal is to periodically display the output on a serial terminal, to see
if your program is working properly. |
|
|
Guest
|
|
Posted: Sun Nov 12, 2006 9:00 pm |
|
|
Hi, Thanks for quick reply. I'm using an oscilloscope to check my output from the tx pin(C6) of the pic16f877. if that is the case, is my raw data output wrong?
also, i intend to connect it to a max232cpe to convert it (tx pin) to rs232 format. i dun really know how to use a terminal (noob) but am i correct to say i shld use a hyperterminal in windows, increase my delay and connect it to com 1?
PCM programmer wrote: | You're sending the raw data. You need to convert it to ASCII characters
so that it can be displayed in the terminal window.
Get rid of the two putc() statements, and use a printf() statement instead.
The following line will display the result in Hexadecimal:
Code: | printf("%LX \n\r", result); |
Also, you need a delay in your loop of much more than 4 ms.
Try using 500 or 1000 ms. That's much more reasonable, if your
goal is to periodically display the output on a serial terminal, to see
if your program is working properly. |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Nov 12, 2006 9:10 pm |
|
|
Quote: |
I'm using an oscilloscope to check my output from the tx pin(C6) of the
pic16f877. if that is the case, is my raw data output wrong? |
No, but it's better to view it on a terminal window because you easily
see the data in decimal or hex format, instead of having to watch
pulses moving around.
See this thread for links on how to setup Hyperterminal and the MAX232
chip, etc.
http://www.ccsinfo.com/forum/viewtopic.php?t=26898 |
|
|
Guest
|
|
Posted: Mon Nov 13, 2006 12:18 am |
|
|
thanks for the help, i've been able to connect to my pic through the hyperterminal n receive output. My question now is my ADC outputs format in the way...
MSB: |B11|B10|B9|B8|B7|B6|B5|B4|
LSB: |B3|B2|B1|B0|---|B1|B2|B3|B4|
so i've done tis to remove the repeated bits
lsb=(0xF0 & lsb); //remove repeated bits in lsb
how does the make16 function work? also i get a 0000 for a 0V input and a 1ffe for a 5V input. Was thinkin i wld get a 0000 for a 0V input and a 00ff for a 5V input.
still cannot get my adc (ADS7816) to work properly so i m throwing values to the SPI.
Thanks in advance.. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 13, 2006 1:07 am |
|
|
Comments:
1. You haven't told the compiler to use fast i/o mode, so your set_tris
statements aren't necessary. Because you are using standard_io
mode (which is the default mode of the compiler), the compiler will
automatically insert code to properly setup the TRIS for these
functions: output_high(), output_low(), setup_spi(), #use rs232().
You can delete all the set_tris_x() statements.
2. According to the bottom diagram in Figure 1 of the ADS7816
data sheet (page 9), the chip requires 3 "run-in" clocks before
it will start outputting data to the PIC. You're doing two calls
to spi_read(), which will generate 16 clocks. The A/D chip puts
out 12 bits of data, so that means a cycle consists of 3 run-in
clocks, 12 data bits, and then 1 more clock. So it looks like
you need to do this, to get a 12-bit, right-justfied result:
Code: |
result = make16(msb, lsb);
result &= 0x1FFE; // Mask off the top 3 bits and the LSB.
result >>= 1; // Shift it right by 1 bit.
|
3. Your SPI mode is incorrect. You're using SPI mode 1, and you
you should be using SPI mode 0. Here's how to do it:
Put these #define statements above main().
Code: |
#define SPI_MODE_0_0 0x4000
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0010
#define SPI_MODE_1_1 0x4010 |
Then in main(), do the setup_spi() statement like this:
Code: | setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16); |
|
|
|
Guest
|
|
Posted: Mon Nov 13, 2006 2:24 am |
|
|
Thanks PCM programmer!! you've solved all my problems! After integrating with my ADS7816 (works!), with an input of 0V i now get 0026~0028 and with a 5V input i get 0fff (in hyperterminal). Thanks again!! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|