|
|
View previous topic :: View next topic |
Author |
Message |
POPE19
Joined: 27 Jun 2017 Posts: 71
|
error Reading Multiple ADC Inputs |
Posted: Mon Jul 31, 2017 6:35 am |
|
|
Hello. I am using pic16f914 to read the analog output of a accelerometer ADXL335. I can read 1 channel correctly but when i am trying to read all 3 channels and display the values on LCD it does not work. I am using CCS PCWH 5.074 compiler.
The output of a ADXL is as follows (Readings with ADXL positioned Flat on table) :
1) X - channel (AN0 on PIC ) - 1.59 V
2) Y - channel (AN1 on PIC) - 1.61 V
3) Z- channel (AN5 on PIC ) - 1.977 V
I am using VREF+ = 3.3V (actual 3.25volts) and Vss=0;
Following are readings when channels measured individually:
AN0 - 504 for (1.596 volts)
AN1 - 510 for (1.610 volts)
AN5 - 625 for (1.979 Volts)
Now i am measuring all 3 channels. I am getting 337 on display.
Following is my code:
Code: |
#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)
//#define VSS_VREF
//#define VREF_VREF
//============================================================================================//
//===========================================================================================//
// LCD Configuration //
//==========================================================================================//
// Digit segments A B C D E F G DP
// b7 b6 b5 b4 b3 b2 b1 b0
#define DIGIT5 COM0+17, COM1+17, COM2+17, COM3+17, COM2+18, COM0+18, COM1+18, COM3+18
#define DIGIT4 COM0+3, COM1+3, COM2+3, COM3+3, COM2+2, COM0+2, COM1+2, COM3+2
#define DIGIT3 COM0+1, COM1+1, COM2+1, COM3+1, COM2+0, COM0+0, COM1+0, COM3+0
#define DIGIT2 COM0+19, COM1+19, COM2+19, COM3+19, COM2+20, COM0+20, COM1+20, COM3+20
// ComX+Y is combination of Backplan0-3 and Segment0-SegmentXX
//=======================================================================================//
// character 0 1 2 3 4 5 6 7 8 9 Null
byte const Digit_Map[11] = {0xFD,0x61,0xDB,0xF3,0x67,0xB7,0xBF,0xE1,0xFF,0xF7,0x01}; //Decimal
byte const Digit_Map_1[11] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0x00}; //no Decimal
//=======================================================================================//
// Segments Initilization //
// Seg23 Seg22 ... Seg12 Seg11 Seg10 Seg9 Seg8 Seg7 Seg6 Seg5 Seg4 Seg3 Seg2 Seg1 Seg0 //
// 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 //
// if bit_SegX is 1, SegX is set as Segment Output. Otherwise //
////=====================================================================================//
#define Segments 0x1E000F // Initilize LCD SegmentX
//============================================================================//
#define INTS_PER_SECOND 76 // (20000000/(4*256*256))
int int_count=INTS_PER_SECOND;
int count5 = 0;// after decimal
int count_5 = 0;
int count4=0; // 1st digit
int count_4=0; // 1st digit
int count3=0; // 2nd digit
int count_3=0;
int count2=0; // 3rd digit
int count_2=0;
long seconds=0;
long reading;
long reading1;
long reading2;
long reading3;
#int_rtcc //This function is called
//============================================================================//
void clock_isr()
{ //every time the RTCC (timer0)
//overflows (255->0)
//For this program this is apx
//31 times per second.
if(--int_count==0)
{
seconds++;
int_count=INTS_PER_SECOND;
}
}
//============================================================================//
void Disp_num()
{
if(reading < 10)
{
count_5=reading;
count_2=11;
count_3=11;
count_4=11;
}
if(10<= reading < 100)
{
count_5=reading%10;
count_4=reading/10;
count_3=11;
count_2=11;
}
if(100 <= reading <999)
{
count_5=reading%10;
count_4=reading%100/10;
Count_3=reading%1000/100;
count_2=11;
}
if(1000 <= reading < 1024)
{
count_5=reading%10;
count_4=reading%100/10;
Count_3=reading%1000/100;
count_2=reading%10000/1000;
}
if(reading >= 1024)
{
count_5=11;
count_4=11;
count_3=11;
count_2=11;
}
}
//=============================================================================//
void sec_disp()
{
count4=count_4;
count5=count_5;
count2=count_2;
count3=count_3;
}
//============================================================================//
void Display()
{
lcd_symbol (Digit_Map_1[count5], DIGIT5);
lcd_symbol (Digit_Map[count4], DIGIT4);
lcd_symbol (Digit_Map_1[count3], DIGIT3);
lcd_symbol (Digit_Map_1[count2], DIGIT2);
}
//============================================================================//
void Digit()
{
if(seconds>=1)
{
set_adc_channel (0);
// VCFG0 = 1; // Enable Vref+. Fix for compiler bug in set_adc_channel().
delay_us(20);
reading1 = read_adc();
delay_us(20);
reading=reading1;
// delay_ms(1000);
}
if(seconds>=2)
{
set_adc_channel (1);
delay_us(20);
reading2 = read_adc();
delay_us(20);
reading=reading2;
// delay_ms(1000);
}
if(seconds>=3)
{
set_adc_channel (5);
delay_us(20);
reading3 = read_adc();
delay_us(20);
reading=reading3;
// delay_ms (1000);
//seconds=0;
}
seconds=0;
}
//void ADC_reading()
//{
// if
//===========================================================================//
//============================================================================//
//get VCFG0 bit (to clear ccs bug which clears VCFG0 bit & due to that Vref
//is always defaulted to Vpp.
#bit VCFG0 = getenv("BIT:VCFG0")
//===========================================================================//
void main()
{
set_tris_a (0xdf);
set_tris_b (0xc0);
set_tris_c (0x07);
setup_adc_ports(sAN0);
setup_adc_ports(sAN1);
setup_adc_ports(sAN5);
setup_adc (ADC_CLOCK_INTERNAL);
// enable_interrupts(GLOBAL);
// setup_timer_1 (T1_DISABLED); // disable timer 1
// setup_timer_2 (T2_DISABLED,0,1); // disable timer 2
// setup_vref (FALSE); // disable Voltage reference
// setup_adc (ADC_OFF); // disable ADC
// setup_wdt (WDT_OFF); // disable Watch Dog Timer
// setup_ccp1 (CCP_OFF); // disable compare/capture
// setup_comparator (NC_NC_NC_NC); // disable comparators
//#byte VRCON = 0x009D // VR control register
// VRCON = 0x00; // VR is disabled
//#byte CMCON0 = 0x009C // Comparator configuration register
// CMCON0 = 0x0007; // Comparator is disabled
// #byte ANSEL = 0x0091 // Analog select register
// ANSEL = 0x00; // Digital I/O
// #byte ADCON0 = 0x00a3 // A/D control register
// ADCON0 = 0x00; // A/D is shut off
set_rtcc(0);
setup_counters (RTCC_INTERNAL, RTCC_DIV_256);
enable_interrupts (INT_RTCC);
enable_interrupts(GLOBAL);
setup_lcd(LCD_MUX14|LCD_STOP_ON_SLEEP,3, Segments); // set segments
count5 = 8;
count4 = 8;
count3 = 8;
count2 = 8;
Display ();
delay_ms (1000);
while (TRUE) /* Modify on 9/19/2012 */
{
digit();
Disp_num();
sec_disp();
display();
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 31, 2017 7:49 am |
|
|
Remember that the set_adc_channel() function is defective.
It clears the VCFG0 bit. So we gave you a fix. The fix
consists of manually setting the VCFG0 bit to 1, after each
call to set_channel(). But in your posted code, you are not
doing this. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Jul 31, 2017 7:51 am |
|
|
setup_adc_ports does not work like that. The syntax is:
setup_adc_ports(sAN0 | sAN1 | sAN5);
Currently you will only be connecting AN5 to the multiplexer....
You are also running with Vss to Vdd, not the 3.3v reference, and have not got the bugfix posted by PCM_programmer.... |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Mon Jul 31, 2017 8:26 am |
|
|
Hi,
You are also going backward on things previously pointed out to you, in this case by PCM programmer.
Example:
Code: |
#int_rtcc //This function is called
//============================================================================//
void clock_isr()
{ //every time the RTCC
|
Successful programming demands care, and attention to detail. Randomness is not a good programming attribute..... _________________ John
If it's worth doing, it's worth doing in real hardware! |
|
|
POPE19
Joined: 27 Jun 2017 Posts: 71
|
|
Posted: Mon Jul 31, 2017 8:28 am |
|
|
i HAVE TRIED TO PASTE VCFG0 = 1; AFTER SELECTION OF ADC channel but it shows me error it says unidentified identifier. And also i am unaware of where to paste this code for channel 1 and 5. Please suggest. Sorry i have made modifications bringing #INT rtcc but while copy pasting i don't realize how i ended up having pasted old version.
Code is as shown:
Code: |
#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)
//#define VSS_VREF
//#define VREF_VREF
//============================================================================================//
//===========================================================================================//
// LCD Configuration //
//==========================================================================================//
// Digit segments A B C D E F G DP
// b7 b6 b5 b4 b3 b2 b1 b0
#define DIGIT5 COM0+17, COM1+17, COM2+17, COM3+17, COM2+18, COM0+18, COM1+18, COM3+18
#define DIGIT4 COM0+3, COM1+3, COM2+3, COM3+3, COM2+2, COM0+2, COM1+2, COM3+2
#define DIGIT3 COM0+1, COM1+1, COM2+1, COM3+1, COM2+0, COM0+0, COM1+0, COM3+0
#define DIGIT2 COM0+19, COM1+19, COM2+19, COM3+19, COM2+20, COM0+20, COM1+20, COM3+20
// ComX+Y is combination of Backplan0-3 and Segment0-SegmentXX
//=======================================================================================//
// character 0 1 2 3 4 5 6 7 8 9 Null
byte const Digit_Map[11] = {0xFD,0x61,0xDB,0xF3,0x67,0xB7,0xBF,0xE1,0xFF,0xF7,0x01}; //Decimal
byte const Digit_Map_1[11] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0x00}; //no Decimal
//=======================================================================================//
// Segments Initilization //
// Seg23 Seg22 ... Seg12 Seg11 Seg10 Seg9 Seg8 Seg7 Seg6 Seg5 Seg4 Seg3 Seg2 Seg1 Seg0 //
// 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 //
// if bit_SegX is 1, SegX is set as Segment Output. Otherwise //
////=====================================================================================//
#define Segments 0x1E000F // Initilize LCD SegmentX
//============================================================================//
#define INTS_PER_SECOND 76 // (20000000/(4*256*256))
int int_count=INTS_PER_SECOND;
int count5 = 0;// after decimal
int count_5 = 0;
int count4=0; // 1st digit
int count_4=0; // 1st digit
int count3=0; // 2nd digit
int count_3=0;
int count2=0; // 3rd digit
int count_2=0;
long seconds=0;
long reading;
long reading1;
long reading2;
long reading3;
//============================================================================//
#int_rtcc //This function is called
void clock_isr()
{ //every time the RTCC (timer0)
//overflows (255->0)
//For this program this is apx
//31 times per second.
if(--int_count==0)
{
seconds++;
int_count=INTS_PER_SECOND;
}
}
//============================================================================//
void Disp_num()
{
if(reading < 10)
{
count_5=reading;
count_2=11;
count_3=11;
count_4=11;
}
if(10<= reading < 100)
{
count_5=reading%10;
count_4=reading/10;
count_3=11;
count_2=11;
}
if(100 <= reading <999)
{
count_5=reading%10;
count_4=reading%100/10;
Count_3=reading%1000/100;
count_2=11;
}
if(1000 <= reading < 1024)
{
count_5=reading%10;
count_4=reading%100/10;
Count_3=reading%1000/100;
count_2=reading%10000/1000;
}
if(reading >= 1024)
{
count_5=11;
count_4=11;
count_3=11;
count_2=11;
}
}
//=============================================================================//
void sec_disp()
{
count4=count_4;
count5=count_5;
count2=count_2;
count3=count_3;
}
//============================================================================//
void Display()
{
lcd_symbol (Digit_Map_1[count5], DIGIT5);
lcd_symbol (Digit_Map[count4], DIGIT4);
lcd_symbol (Digit_Map_1[count3], DIGIT3);
lcd_symbol (Digit_Map_1[count2], DIGIT2);
}
//============================================================================//
void Digit()
{
if(seconds>=1)
{
set_adc_channel (0);
VCFGO = 1; // Enable Vref+. Fix for compiler bug in set_adc_channel().
delay_us(20);
reading1 = read_adc();
delay_us(20);
reading=reading1;
// delay_ms(1000);
}
if(seconds>=2)
{
set_adc_channel (1);
VCFGO = 1;
delay_us(20);
reading2 = read_adc();
delay_us(20);
reading=reading2;
// delay_ms(1000);
}
if(seconds>=3)
{
set_adc_channel (5);
VCFGO = 1;
delay_us(20);
reading3 = read_adc();
delay_us(20);
reading=reading3;
// delay_ms (1000);
//seconds=0;
}
seconds=0;
}
#bit VCFG0 = getenv("BIT:VCFG0")
//===========================================================================//
void main()
{
set_tris_a (0xdf);
set_tris_b (0xc0);
set_tris_c (0x07);
setup_adc_ports(sAN0|sAN1|sAN5);
setup_adc (ADC_CLOCK_INTERNAL);
// enable_interrupts(GLOBAL);
// setup_timer_1 (T1_DISABLED); // disable timer 1
// setup_timer_2 (T2_DISABLED,0,1); // disable timer 2
// setup_vref (FALSE); // disable Voltage reference
// setup_adc (ADC_OFF); // disable ADC
// setup_wdt (WDT_OFF); // disable Watch Dog Timer
// setup_ccp1 (CCP_OFF); // disable compare/capture
// setup_comparator (NC_NC_NC_NC); // disable comparators
//#byte VRCON = 0x009D // VR control register
// VRCON = 0x00; // VR is disabled
//#byte CMCON0 = 0x009C // Comparator configuration register
// CMCON0 = 0x0007; // Comparator is disabled
// #byte ANSEL = 0x0091 // Analog select register
// ANSEL = 0x00; // Digital I/O
// #byte ADCON0 = 0x00a3 // A/D control register
// ADCON0 = 0x00; // A/D is shut off
set_rtcc(0);
setup_counters (RTCC_INTERNAL, RTCC_DIV_256);
enable_interrupts (INT_RTCC);
enable_interrupts(GLOBAL);
setup_lcd(LCD_MUX14|LCD_STOP_ON_SLEEP,3, Segments); // set segments
count5 = 8;
count4 = 8;
count3 = 8;
count2 = 8;
Display ();
delay_ms (1000);
while (TRUE) /* Modify on 9/19/2012 */
{
digit();
Disp_num();
sec_disp();
display();
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 31, 2017 9:07 am |
|
|
In the previous thread, I said to do this:
Quote: | To fix it, add this line above main():
Code:
#bit VCFG0 = getenv("BIT:VCFG0") |
But you didn't put that line in your current program.
I also said:
Quote: | Then set VCFG0 in code, just after setting the channel:
Code:
set_adc_channel(0);
VCFG0 = 1; // Enable Vref+. Fix for compiler bug in set_adc_channel(). |
After every call to set_adc_channel(), you need to add the VCFG0 = 1;
line.
I should have made a better fix, such as a macro to replace the built-in
set_adc_channel() function, but I wanted to post a fix quickly so I posted
the simple one. |
|
|
POPE19
Joined: 27 Jun 2017 Posts: 71
|
|
Posted: Mon Jul 31, 2017 9:27 am |
|
|
IT IS THERE JUST ABOVE MAIN . ALSO I M ADDING VCFG0 = 1 ; LINE AFTER EVERY set_adc_channel LINE. BUT I M GETTING ERROR UNIDENTIFIED IDENTIFIER .
Code: |
void Digit()
{
if(seconds>=1)
{
set_adc_channel (0);
VCFG0 = 1; // Enable Vref+. Fix for compiler bug in set_adc_channel().
delay_us(20);
reading1 = read_adc();
reading=reading1;
}
if(seconds>=2)
{
set_adc_channel (1);
VCFGO = 1;
delay_us(20);
reading2 = read_adc();
reading=reading2;
}
if(seconds>=3)
{
set_adc_channel (5);
VCFGO = 1;
delay_us(20);
reading3 = read_adc();
reading=reading3;
}
seconds=0;
}
//===========================================================================//
//============================================================================//
//get VCFG0 bit (to clear ccs bug which clears VCFG0 bit & due to that Vref
//is always defaulted to Vpp.
#bit VCFG0 = getenv("BIT:VCFG0")
//===========================================================================//
void main()
{
set_tris_a (0xdf);
set_tris_b (0xc0);
set_tris_c (0x07);
setup_adc_ports(sAN0|sAN1);
setup_adc (ADC_CLOCK_INTERNAL);
// enable_interrupts(GLOBAL);
// setup_timer_1 (T1_DISABLED); // disable timer 1
// setup_timer_2 (T2_DISABLED,0,1); // disable timer 2
// setup_vref (FALSE); // disable Voltage reference
// setup_adc (ADC_OFF); // disable ADC
// setup_wdt (WDT_OFF); // disable Watch Dog Timer
// setup_ccp1 (CCP_OFF); // disable compare/capture
// setup_comparator (NC_NC_NC_NC); // disable comparators
//#byte VRCON = 0x009D // VR control register
// VRCON = 0x00; // VR is disabled
//#byte CMCON0 = 0x009C // Comparator configuration register
// CMCON0 = 0x0007; // Comparator is disabled
// #byte ANSEL = 0x0091 // Analog select register
// ANSEL = 0x00; // Digital I/O
// #byte ADCON0 = 0x00a3 // A/D control register
// ADCON0 = 0x00; // A/D is shut off
set_rtcc(0);
setup_counters (RTCC_INTERNAL, RTCC_DIV_256);
enable_interrupts (INT_RTCC);
enable_interrupts(GLOBAL);
setup_lcd(LCD_MUX14|LCD_STOP_ON_SLEEP,3, Segments); // set segments
count5 = 8;
count4 = 8;
count3 = 8;
count2 = 8;
Display ();
delay_ms (1000);
while (TRUE) /* Modify on 9/19/2012 */
{
digit();
Disp_num();
sec_disp();
display();
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 31, 2017 9:29 am |
|
|
OK, here's a revision. Put it above any other code. Example:
Code: |
#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)
#bit VCFG0 = getenv("BIT:VCFG0") // Put it here
|
Also, get rid of these two lines. They don't do anything and are not needed:
//#define VSS_VREF
//#define VREF_VREF |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Jul 31, 2017 10:04 am |
|
|
He is also still not selecting the Vref, and ADC_CLOCK_INTERNAL is not recommended 1MHz.
He had the wrong idea that this controlled Tacq. Not Tad.
Both of these were pointed out in the earlier thread, he is ignoring/not reading what is being posted... :(
Can I suggest:
Code: |
#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)
#bit VCFG0 = getenv("BIT:VCFG0") // Put it here
#define SET_AN_CHANNEL(x) set_adc_channel (x); VCFG0 = 1
//Then select a channel with
SET_AN_CHANNEL(0); //etc.
delay_us(5); //This is the Tacq
//Configure the ADC in the main with:
setup_adc_ports(sAN0 | sAN1 | sAN5, Vss_Vdd);
setup_adc (ADC_CLOCK_DIV_32);
|
I know the VCFG write overrides the adc_ports setup, but it ensures the other bit is off, and means it will be compatible if he switches to another chip.
Last edited by Ttelmah on Mon Jul 31, 2017 10:17 am; edited 1 time in total |
|
|
POPE19
Joined: 27 Jun 2017 Posts: 71
|
|
Posted: Mon Jul 31, 2017 10:15 am |
|
|
I will do that. I am sorry guys i am not ignoring previous instructions as you suggested but because somehow i end up with the old version i am going to start all over again.
I really appereciate your help. I will keep you guys updated. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Jul 31, 2017 10:18 am |
|
|
I edited my post to make a tidier suggestion while you were typing. This is what I'd do. |
|
|
POPE19
Joined: 27 Jun 2017 Posts: 71
|
|
Posted: Mon Jul 31, 2017 11:49 am |
|
|
i have wrote a program to read just 2 channels (ch 0-x reading of adxl & ch 4-z reading of adxl), it seems like it only reads channel-0 and does not read channel 4. I noticed one thing when I'm taking input from channel 4 and putting it on channel 1, it reads 608. I have preset all I/O ports using tris command. But still it is not displaying both readings one after another but it just displays first reading which it measures at channel-0.
Code: |
//============================================================================//
// Inclinometer //
// Date: 7-24-2017 //
// //
//============================================================================//
#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)
#bit VCFG0 = getenv("BIT:VCFG0")
#define SET_AN_CHANNEL(x) set_adc_channel (x); VCFG0 = 1
//============================================================================================//
//===========================================================================================//
// LCD Configuration //
//==========================================================================================//
// Digit segments A B C D E F G DP
// b7 b6 b5 b4 b3 b2 b1 b0
#define DIGIT5 COM0+17, COM1+17, COM2+17, COM3+17, COM2+18, COM0+18, COM1+18, COM3+18
#define DIGIT4 COM0+3, COM1+3, COM2+3, COM3+3, COM2+2, COM0+2, COM1+2, COM3+2
#define DIGIT3 COM0+1, COM1+1, COM2+1, COM3+1, COM2+0, COM0+0, COM1+0, COM3+0
#define DIGIT2 COM0+19, COM1+19, COM2+19, COM3+19, COM2+20, COM0+20, COM1+20, COM3+20
// ComX+Y is combination of Backplan0-3 and Segment0-SegmentXX
//=======================================================================================//
// character 0 1 2 3 4 5 6 7 8 9 Null
byte const Digit_Map[11] = {0xFD,0x61,0xDB,0xF3,0x67,0xB7,0xBF,0xE1,0xFF,0xF7,0x01}; //Decimal
byte const Digit_Map_1[11] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0x00}; //no Decimal
//=======================================================================================//
// Segments Initilization //
// Seg23 Seg22 ... Seg12 Seg11 Seg10 Seg9 Seg8 Seg7 Seg6 Seg5 Seg4 Seg3 Seg2 Seg1 Seg0 //
// 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 //
// if bit_SegX is 1, SegX is set as Segment Output. Otherwise //
////=====================================================================================//
#define Segments 0x1E000F // Initilize LCD SegmentX
//============================================================================//
#define INTS_PER_SECOND 76 // (20000000/(4*256*256))
int int_count=INTS_PER_SECOND;
int count5 = 0;// after decimal
int count_5 = 0;
int count4=0; // 1st digit
int count_4=0; // 1st digit
int count3=0; // 2nd digit
int count_3=0;
int count2=0; // 3rd digit
int count_2=0;
long seconds=0;
long reading;
long reading1;
long reading2;
//============================================================================//
#int_rtcc //This function is called
void clock_isr()
{ //every time the RTCC (timer0)
//overflows (255->0)
//For this program this is apx
//31 times per second.
if(--int_count==0)
{
seconds++;
int_count=INTS_PER_SECOND;
}
}
//============================================================================//
void Disp_num()
{
if(reading < 10)
{
count_5=reading;
count_2=11;
count_3=11;
count_4=11;
}
if(10<= reading < 100)
{
count_5=reading%10;
count_4=reading/10;
count_3=11;
count_2=11;
}
if(100 <= reading <999)
{
count_5=reading%10;
count_4=reading%100/10;
Count_3=reading%1000/100;
count_2=11;
}
if(1000 <= reading < 1024)
{
count_5=reading%10;
count_4=reading%100/10;
Count_3=reading%1000/100;
count_2=reading%10000/1000;
}
}
//=============================================================================//
void sec_disp()
{
count4=count_4;
count5=count_5;
count2=count_2;
count3=count_3;
}
//============================================================================//
void Display()
{
lcd_symbol (Digit_Map_1[count5], DIGIT5);
lcd_symbol (Digit_Map[count4], DIGIT4);
lcd_symbol (Digit_Map_1[count3], DIGIT3);
lcd_symbol (Digit_Map_1[count2], DIGIT2);
}
//============================================================================//
void Digit()
{
if(seconds>=1)
{
SET_AN_CHANNEL (0); // selecting Channel A0;
delay_us(5); // TACQ > 4.67 us as per data sheet
reading1 = read_adc();
reading = reading1;
}
if(seconds>=2)
{
SET_AN_CHANNEL (4);
delay_us(5);
reading2 = read_adc();
reading = reading1;
}
seconds=0;
}
void main()
{
set_tris_a (0xe9); //set RA-0,3,5,6,7 as inputs
set_tris_b (0xc0);
set_tris_c (0x07);
set_tris_e (0x08);
setup_adc_ports(sAN0|sAN4,VSS_VREF);
setup_adc (ADC_CLOCK_DIV_32);
set_rtcc(0);
setup_counters (RTCC_INTERNAL, RTCC_DIV_256);
enable_interrupts (INT_RTCC);
enable_interrupts(GLOBAL);
setup_lcd(LCD_MUX14|LCD_STOP_ON_SLEEP,3, Segments); // set segments
count5 = 8;
count4 = 8;
count3 = 8;
count2 = 8;
Display ();
delay_ms (1000);
while (TRUE)
{
digit();
Disp_num();
sec_disp();
display();
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Jul 31, 2017 12:11 pm |
|
|
The channel select code is totally wrong....
Replace it with this:
Code: |
#byte ADCON0=getenv("SFR:ADCON0")
#define SET_AN_CHANNEL(x) ADCON0=((ADCON0 & 0xC3)+(x<<3))
|
This fixes the selection and the Vref configuration.
Amazing it hasn't been spotted in ten years!...
I'm not in the lab at the moment, but will pull the old paper data sheet I have and see if this shows the selection as the code is doing, when I get in tomorrow. |
|
|
POPE19
Joined: 27 Jun 2017 Posts: 71
|
|
Posted: Mon Jul 31, 2017 12:33 pm |
|
|
Ttelmah,
this brings back the same problem of Vref+ referece selection & still reads the first channel only. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 31, 2017 12:48 pm |
|
|
Quote: | The channel select code is totally wrong....
Replace it with this:
Code:
#byte ADCON0=getenv("SFR:ADCON0")
#define SET_AN_CHANNEL(x) ADCON0=((ADCON0 & 0xC3)+(x<<3))
|
I don't see how you get that the channel (0 to 7) should be shifted left 3.
Look at page 180 (pg 182 in the Adobe reader) of the 16F914 datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/41250F.pdf
It shows the ADCON0 register bit layout.
Quote: | REGISTER 12-1: ADCON0: A/D CONTROL REGISTER 0 |
To move the channel parameter into the CHSx bitfield, is should be
shifted left by 2 bit positions. Here is the layout:
Code: | 7 6 5 4 3 2 1 0
ADFM VCFG1 VCFG0 CHS2 CHS1 CHS0 GO/DONE ADON |
Also, you see from the bit layout that 0xC3 is wrong as the mask.
It should be 0xE3. This mask will clear the CHSx bits only. |
|
|
|
|
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
|