Paritoshgiri
Member level 5
There is actually nothing wrong with the Microchip C18 Compiler, it has compiled the code as instructed.
There are several minor issues and one main issue with your code.
Your main issue was the following line of code:
Code:voltage = (ADRESH << 8) | ADRESL;
The assignment statement above assumes a implicit cast conversion of a Char type to an Integer type before the final result of calculations on the Right Hand Side (RHS) of the assignment.
This implicit cast conversion is neither ANSI Standard C nor traditional C (K&R), the rule of implicit assignment type conversion or promotion, as it is sometimes referred, is as follows:
MikroC clearly violates this rule, by the implicit type conversion of the ADRESH from type unsigned char to unsigned int before the final calculations of the RHS.
The proper way to carry out this assignment type conversion, as per ANSI Standard C rules, is as follows:
Code:voltage = ((unsigned int)ADRESH << 8) | ADRESL;
Another option, if you do not wish to explicitly cast ADRESH from unsigned char to unsigned int, is as follows:
Code:voltage = ADRESH; voltage <<= 8; voltage |= ADRESL;
In place of the statement above.
The following has been tested on a PIC18F4550 using Microchip C18 Compiler and yields the expected results:
Code:#include <p18f4550.h> #include <delays.h> void Read_ADC(void); void Send_Value (void); unsigned int adc; unsigned float result; unsigned int voltage; void main(void) { TRISA = 0b00000001; ADCON0 = 0b00000001; // A/D is ON ADCON1 = 0b00001110; // Vref- set to Vss // Vref+ set to Vdd // AN0 is analog - others are digital ADCON2 = 0b10111111; // right justify // Acq time 20TAD // clk Frc TXSTA = 0b10100010; // 8-bit // async // low speed (BRGH=0) RCSTA = 0b10010000; SPBRG = 77; while (1) { Read_ADC(); Send_Value(); Delay10KTCYx(240); //Delay 200 ms Delay10KTCYx(240); //Delay 200 ms } } void Read_ADC (void) { voltage = 0; //globally defined as unsigned long Delay10TCYx(24); // Delay for 240TCY allow sampling cap to charge ADCON0bits.GO = 1; //start converting while (ADCON0bits.DONE == 1); //wait for EOC voltage = ((unsigned int)ADRESH << 8) | ADRESL; //combines two bytes into a long int result = (float)(voltage * 5)/1023; adc = result * 1000; //voltage = voltage * 5000; //Vref is in milliVolts //voltage = voltage/1023; //10 bit ADC } void Send_Value (void) { char ch; ch = (adc/1000) % 10; //extract thousands digit ch = ch + 48; // now it is in ASCII while (PIR1bits.TXIF == 0); { TXREG = ch; } while (PIR1bits.TXIF == 0); TXREG = '.'; //We need a decimal point ch = (adc/100) % 10; //extract hundredth digit ch = ch + 48; while (PIR1bits.TXIF == 0); TXREG = ch; ch = (adc/10) % 10; //extract tenth digit ch = ch + 48; while (PIR1bits.TXIF == 0); TXREG = ch; ch = adc % 10; ch = ch + 48; while (PIR1bits.TXIF == 0); TXREG = ch; while (PIR1bits.TXIF == 0); TXREG = '\n'; while (PIR1bits.TXIF == 0); TXREG = '\r'; while (PIR1bits.TXIF == 0); }
I should also mention the C18 Compiler comes with an extensive library of routines which could greatly simplify this task to only a few statements.
BigDog
Thank u so much. So the problem was that, I compiled your code in MPLAB and its working fine. The only problem is that the last digit is now showing. I think I need to follow Bjuric's suggestion of putting
while (TXSTA.TRMT == 0);
---------- Post added at 06:00 ---------- Previous post was at 05:57 ----------
Dude, did I even mentioned you?
I was referring to Paritoshgiri's code, check post #40.
Code:unsigned long adc; [B]unsigned float result;[/B] unsigned int voltage;
I installed mikroC Pro v1.65 and compiled the code you send me and its working fine. The hex file is good and the results are correct. Thank u so much. I think there was compatibility problem of mikroC code with MPLAB. However, BigdogGuru's code is also working fine now in MPLAB. Thank u so much for your help. Take care