These will not exceed 16 bit unsigned ints. Like I said above, watch your type casting when performing math.These 4 byte integers. I think I do not need that more bitsC:unsigned long int ADC_Vtemp, ADC_V;
16 bit will do right ?
These will not exceed 16 bit unsigned ints. Like I said above, watch your type casting when performing math.These 4 byte integers. I think I do not need that more bitsC:unsigned long int ADC_Vtemp, ADC_V;
16 bit will do right ?
#define TMR0reload 169
#define ADCreload 64
unsigned int ADC_Vtemp, ADC_V;
unsigned int ADC_Temp, Volts;
unsigned char ADC_Loop_Counter;
bit Display;
char *Vout = "00.00";
void interrupt(){
if(INTCON.T0IF){
INTCON.T0IF = 0;
TMR0 += TMR0reload;
if(ADC_Loop_Counter){ // If loop counter is not zero
ADC_Vtemp += ADC_Read(0); // Read ADC and keep adding to accumulator(temp)
ADC_Loop_Counter--; // Decrement loop counter
}
if(ADC_Loop_Counter == 0){ // If loop counter is 0
ADC_Vtemp = ADC_Temp; // Copy accumulator
ADC_Vtemp = 0; // Clear accumulator
ADC_Loop_Counter = ADCreload; // reload loop counter
Display = 1; // set conversion flag
}
}
}
void main(){
OSCCON = 0x77;
ANSEL = 0x0F;
ANSELH = 0x20;
CM1CON0 = 0x07;
CM2CON0 = 0x07;
PORTA = 0;
PORTB = 0;
PORTC = 0;
TRISA = 0x3F;
TRISB = 0XF0;
TRISC = 0x07;
ADC_Init();
LCD_Init();
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);
Display = 0;
ADC_Vtemp = 0;
ADC_V = 0;
ADC_Loop_Counter = ADCreload;
OPTION_REG = 0x81; // Prescaler at 4
INTCON = 0;
PIE1 = 0;
PIE2 = 0;
INTCON.T0IF = 0;
TMR0 = 0;
INTCON.T0IE = 1;
INTCON.GIE = 1;
while(1){
if(Display){
Display = 0;
Volts = (ADC_Temp *2929.6875)/65536; // testing voltage scaling to 30V max
Vout[0] = Volts/1000+48; // Extract 1000th place
Vout[1] = (Volts/100)%10+48; // Extract 100th place
Vout[3] = (Volts/10)%10+48; // Extract 10th place
Vout[4] = (Volts/1)%10+48; // Extract 1st place
Lcd_Out(1,10,Vout); // Send to LCD
Lcd_Out(1,1,"Voltage:" ); // Send to LCD
Lcd_Out(2,1,"Current:" ); // Send to LCD
}
}
}
Well, since you are not writing your code the way I suggested, i.e. two interrupts, ignoring my comment regarding the extra unnecessary comparison, reloading TMR0 rather than just letting it roll over naturally, etc., there is little I am inclined to do to help you further.C:#define TMR0reload 169 #define ADCreload 64 unsigned int ADC_Vtemp, ADC_V; unsigned int ADC_Temp, Volts; unsigned char ADC_Loop_Counter; bit Display; char *Vout = "00.00"; void interrupt(){ if(INTCON.T0IF){ INTCON.T0IF = 0; TMR0 += TMR0reload; if(ADC_Loop_Counter){ // If loop counter is not zero ADC_Vtemp += ADC_Read(0); // Read ADC and keep adding to accumulator(temp) ADC_Loop_Counter--; // Decrement loop counter } if(ADC_Loop_Counter == 0){ // If loop counter is 0 ADC_Vtemp = ADC_Temp; // Copy accumulator ADC_Vtemp = 0; // Clear accumulator ADC_Loop_Counter = ADCreload; // reload loop counter Display = 1; // set conversion flag } } } void main(){ OSCCON = 0x77; ANSEL = 0x0F; ANSELH = 0x20; CM1CON0 = 0x07; CM2CON0 = 0x07; PORTA = 0; PORTB = 0; PORTC = 0; TRISA = 0x3F; TRISB = 0XF0; TRISC = 0x07; ADC_Init(); LCD_Init(); Lcd_Cmd(_LCD_CLEAR); Lcd_Cmd(_LCD_CURSOR_OFF); Display = 0; ADC_Vtemp = 0; ADC_V = 0; ADC_Loop_Counter = ADCreload; OPTION_REG = 0x81; // Prescaler at 4 INTCON = 0; PIE1 = 0; PIE2 = 0; INTCON.T0IF = 0; TMR0 = 0; INTCON.T0IE = 1; INTCON.GIE = 1; while(1){ if(Display){ Display = 0; Volts = (ADC_Temp *2929.6875)/65536; // testing voltage scaling to 30V max Vout[0] = Volts/1000+48; // Extract 1000th place Vout[1] = (Volts/100)%10+48; // Extract 100th place Vout[3] = (Volts/10)%10+48; // Extract 10th place Vout[4] = (Volts/1)%10+48; // Extract 1st place Lcd_Out(1,10,Vout); // Send to LCD Lcd_Out(1,1,"Voltage:" ); // Send to LCD Lcd_Out(2,1,"Current:" ); // Send to LCD } } }
LCD reading remains unchanged does not respond to POT.
Every reset loads a new value in to voltage reading and it remains stuck.
I am lost here..sorry.
This is one of the issues a C programmer always has to keep in mind. In .asm, there is no such thing as type casting. When different data types are mixed in a single expression, they all must be converted first to a common data type prior to the operation, and then the result cast to the destination variable data type. This can produce unexpected results.I am sorry joeyd999. I am not very good at this. Coding is not easy to understand.
I had to look up type casting thing when u said it. I still don't get it somewhat.
Yes. As discussed earlier your timer0 ISR should simply activate the conversion by setting the A/D go bit in the proper ADCON register. The A/D ISR captures the data, switches the MUXs, and accumulates the results.2 interrupts? But I cannot see two interrupts.
For simplicity, set the rollover time so that it equals your desired A/D sampling period.But I can let TMR0 roll over without reloading.
Line 16.I do not understand the "extra unnecessary comparison" part.
/*
#define TMR0reload 169
#define ADCreload 64
unsigned int ADC_Vtemp, ADC_Itemp;
unsigned int ADC_Voltage, Volts;
unsigned int ADC_Current, Amps;
unsigned char ADC_Loop_Counter;
bit Display;
char *Vout = "00.00";
char *Iout = "00.00";
/*
void interrupt(){
// if(INTCON.T0IF)
INTCON.T0IF = 0;
ADC_Vtemp = ADC_Read(0);
ADC_V += ADC_Vtemp;
ADC_Loop_Counter--; // Decrement loop counter
}
*/
void main(){
OSCCON = 0x77;
ANSEL = 0x0F;
ANSELH = 0x20;
CM1CON0 = 0x07;
CM2CON0 = 0x07;
PORTA = 0;
PORTB = 0;
PORTC = 0;
TRISA = 0x3F;
TRISB = 0XF0;
TRISC = 0x07;
ADC_Init();
LCD_Init();
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);
Display = 0;
ADC_Vtemp = 0;
ADC_Itemp = 0;
ADC_Voltage = 0;
ADC_Current = 0;
Amps = 0;
Volts = 0;
ADC_Loop_Counter = ADCreload;
OPTION_REG = 0x81; // Prescaler at 4
INTCON = 0;
PIE1 = 0;
PIE2 = 0;
INTCON.T0IF = 0;
TMR0 = 0;
INTCON.T0IE = 1;
INTCON.GIE = 1;
while(1){
/*
unsigned int ADC_Vtemp, ADC_Itemp;
unsigned int ADC_Voltage, Volts;
unsigned int ADC_Current, Amps;
unsigned char ADC_Loop_Counter;
*/
if(ADC_Loop_Counter >= 1){
ADC_Vtemp += ADC_Read(0);
ADC_Itemp += ADC_Read(2);
--ADC_Loop_Counter;
}
if(ADC_Loop_Counter == 0){
ADC_Loop_Counter = ADCreload;
ADC_Voltage = ADC_Vtemp;
ADC_Current = ADC_Itemp;
ADC_Vtemp = 0;
ADC_Itemp = 0;
Display = 1;
}
if(Display){
Display = 0;
Lcd_Out(1,1,"Voltage:" ); // Send to LCD
Lcd_Out(2,1,"Current:" ); // Send to LCD
Volts = (ADC_Voltage * 2929.69)/65536;
Vout[0] = Volts/1000+48; // Extract 1000th place
Vout[1] = (Volts/100)%10+48; // Extract 100th place
Vout[3] = (Volts/10)%10+48; // Extract 10th place
Vout[4] = (Volts/1)%10+48; // Extract 1st place
Lcd_Out(1,10,Vout); // Send to LCD
Amps = (ADC_Current * 195.3125)/65536;
Iout[0] = Amps/1000+48; // Extract 1000th place
Iout[1] = (Amps/100)%10+48; // Extract 100th place
Iout[3] = (Amps/10)%10+48; // Extract 10th place
Iout[4] = (Amps/1)%10+48; // Extract 1st place
Lcd_Out(2,10,Iout); // Send to LCD
}
}
}
It be difficult to do otherwise.Is that code with oversampling ?
I started a blog on writing .asm for PIC18F. Check it out, if you wish.I will buy the 18F's soon.