|
|
View previous topic :: View next topic |
Author |
Message |
bignick270
Joined: 11 Sep 2008 Posts: 44
|
Reading two channels of Adc |
Posted: Wed Oct 08, 2008 1:24 pm |
|
|
I have read through the multiple post on problems with multiple adc readings.
I am having trouble reading my first channel of adc but my second channel is being read. I will include my code below. The comm works and that is not part of the question.
Basically the hardware for this has two 10 position rotary switches used for selecting addresses of the ones and tens digits. The output from the switches goes to a comparator and then it is passed onto the PIC16F877A. The ones digit switch goes into pin A2 and the tens digit goes to pin A3. The hardware is done right because there is complete source code written for this board in assembly. For testing I am transmitting the raw adc values to the computer and will eventually make a algorithm to turn it in the 0-9 address that is selectable from the switch. I get raw adc data for the 10s digit and for the hundreds digit but nothing for the 1s.
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=18432000)
//This UART needs the errors statement or there are problems!
#use rs232(baud=38400, parity=E, xmit=PIN_C6, rcv=PIN_C7, bits=8, errors, stream=IN)
#use rs232(baud=38400, parity=E, xmit=PIN_C5, bits=8, FORCE_SW, stream=OUT)
//added the FORCE_SW---^ this is software UART
#BYTE TXSTA=0x98 //tx status and control register -- hex add of location
#bit TXEN=TXSTA.5
#define UART_TX_OFF TXEN=FALSE //disable C6 hardware UART pin
#define UART_TX_ON TXEN=TRUE //can turn C6 tx pin back to hardware UART
#define bitwiseop 0x7F //0b01111111 -> used to strip the 1 from first byte of address
// in order to get correct address
//=============================end SERIAL CONTROL OPERATIONS==============//
int8 i; //index value used in RDA - declared here
int8 j; //index value used in tx
int8 msg[3]; //global msg array for rx - only 3 bytes
int8 reply[4]; //sample canned reply array
int8 rxflag; //when message is all received then will set flag var
int8 addr10s;
int8 addr1s;
int8 addr100s;
int8 myadd;
int8 temp;
#int_RDA
void RDA_isr(void)
{
if(kbhit(IN))
{
msg[i] = fgetc(IN);
i++;
}
rxflag++;
}
////////////////////////delay function for transmit/////////////////////
//matches up to xxx's 5.35MS between rx and tx/
//used for testing, need to eliminate later as more code is added
void delay_full()
{
delay_ms(5);
delay_us(350);
}
void txsoft()
{
// disable_interrupts(INT_RDA); //may need later depending on timing, who knows
OUTPUT_HIGH(PIN_B2); //enable tx thru the RS485 chip
delay_full(); //delay the 5.35MS for initial testing
for(j=0; j<4; j++)
{
fputc(reply[j], OUT);
delay_us(490);
}
OUTPUT_LOW(PIN_B2); //disable tx and re-enable rx
//OUTPUT_LOW(PIN_B5);
//enable_interrupts(INT_RDA);
}
void addressing()
{
//addresses come from three sources
//1)ones: come from comparator connected to a rotary switch - comes into A2
//2)tens: come from comparator con to a rotary switch switch - comes into A3
//3)hundreds: come from a dip switch to C1 -> 0 = 0, 1 = 100
/*thoughts on reading dial positons
10 selectable postions (0-9) thru adc.running 8 bit = 256 possible (0-255)
256/10 = 25.6 incriments
same but using 10bit adc 1024/10 = 102.4 incriments
*/
set_adc_channel(3); //should get adc value from pin A2, 1s address
// delay_us(20);
addr1s = read_adc();
delay_us(20);
set_adc_channel(4); //should get adc value from pin A3, 10s address
//delay_us(20);
addr10s = read_adc();
addr100s = input_state(PIN_C1);
if(addr100s == 1)
{
addr100s = 100;
}
else
{
addr100s = 0;
}
//myadd = (addr100s + (addr10s*10) + addr1s);
}
void main()
{
setup_adc_ports(ALL_ANALOG);
//according to device header comments. A4 is not included in the ALL_ANALOG
//Includes: A0,A1,A2,A3,A5,E0,E1,E2, corresponds to asm file xsxxx.asm
setup_adc(ADC_CLOCK_DIV_2); //gives .4us per read, doubles as div doubles, internal gives 2-6 us
setup_psp(PSP_DISABLED); //disable while not needed
setup_spi(SPI_SS_DISABLED); //disable while not needed
setup_ccp1(CCP_OFF); //turn off while not needed
setup_ccp2(CCP_OFF); //same
setup_comparator(NC_NC_NC_NC); //off
setup_vref(FALSE); //off, need? dont know never used!
enable_interrupts(INT_RDA); //needed for receive
enable_interrupts(GLOBAL); //turn the bad boys on
OUTPUT_LOW(PIN_C3); //select signal for digital switch
OUTPUT_LOW(PIN_B2); //controls tx or rx function on rs485 chip
//keep low initally for rx
rxflag = 0;
i = 0;
///fill with random data to send
reply[0] = 0x00;
reply[1] = 0x40;
reply[2] = 0x5B;
reply[3] = 0x25;
while(1)
{
if(rxflag == 3) //if we have rxed 3 bytes then proceed if not keep running
{
rxflag = 0; //reset rxflag
i = 0;
txsoft(); //run tx thru software UART using UART stream OUT
}
else
{
addressing();
reply[1] = addr100s;
reply[2] = addr10s;
reply[3] = addr1s;
//this will set the arrays with the raw uart data to be transmitted
}
}
}
|
|
|
|
bignick270
Joined: 11 Sep 2008 Posts: 44
|
|
Posted: Wed Oct 08, 2008 1:34 pm |
|
|
Forgive me for posting this but I think I just figured out what was wrong. I got up left for a few minutes and came back and as soon as i sat down I happened to look at the datasheet and laying next to me and saw the listing for the channels, I was one off.
So moderators you can go ahead and delete this post if you need to. This has been an issue for almost 2 days so you can understand why i was hasty to post the message.
Sorry guys. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Oct 08, 2008 1:36 pm |
|
|
Quote: | #include <16F877A.h>
#device adc=8
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=18432000)
setup_adc(ADC_CLOCK_DIV_2); |
The ADC divisor is incorrect.
Download the 16F877A data sheet.
http://ww1.microchip.com/downloads/en/DeviceDoc/39582b.pdf
Look at page 131 (page 133 in the Acrobat reader). Look at this table:
Quote: | TABLE 11-1: TAD vs. MAXIMUM DEVICE OPERATING FREQUENCIES |
It shows that your selected divisor of "2" will only work properly with
a PIC oscillator frequency of 1.25 MHz maximum. So it's wrong for
your application. Look farther down the table. You can see that you
have to use a divisor of 32 for proper ADC operation.
Also, look in this part of the ADC section of the data sheet:
Quote: | 11.1 A/D Acquisition Requirements |
It says that when you change the ADC channel, you must allow enough
time for the internal Holding Capacitor to charge up. You have
commented out all the delays of 20 usec throughout your program.
Put those lines back in. |
|
|
|
|
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
|