Click here to Skip to main content
15,879,613 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi
I wish to take the samples from pic16f877a,4Mhz HS( if it is given a sine wave input) and plot the same.I am giving 230vp sine wave 50hz as input and transformed it into 5v range and level shifted it into positive voltages.

This is my code
float val,val1;//Declare the adcvalue stored variables
char uart_rd[50],uart_rd1[50];

void rmsv();
void adc_uart();//adc read and uart write
void interrupt(){
  if (PIR1.ADIF) {
    PIR1.ADIF=0; // clear AD interrupt flag

        val= (ADRESH << 8) | ADRESL; // read dadta from channel 0
            {


       val1=(val*325.0)/1023.0;
        FloatToStr(val1,uart_rd1);
       strncpy(uart_rd,uart_rd1,3);
       UART1_Write_Text(uart_rd1);

       //UART1_Write(10);
      UART1_Write(13);
      delay_us(1);
    }

         Delay_Cyc(3); //wait acquisition time
    ADCON0.F2=1; //start conversion again
  }
       }
void main()
{
    TRISA=0XFF;//porta as input
ADCON1 = 0x82; // AN0->AN4 selected as analog input
  ADCON0 = 0b11000001; // Configue analog mode
  INTCON.GIE = 1; //Enable global interrupt
  INTCON.PEIE = 1; //Enable peripheral interrupt
  PIE1.ADIE = 1; //Enable ADC interrupt
  Delay_us(20); //wait for acquisition time
  ADCON0.F2 = 1; //start conversion
    // ADCON1=0X81;
     UART1_Init(9600);               // Initialize UART module at 9600 bps
     //ADC_Init();


    while(1);

 }



I have checked the values in hyperterminal and see that the controller not even sample the peak voltage.I wish to have the samples correctly so that I can able to plot the waveform correctly.
Posted

Ok I had a quick look at the datasheet for the PIC16F877 and the ADC is 10 bit

I have not checked but I assume this line does the right thing and bring the high and low ADC results together

val= (ADRESH << 8) | ADRESL;

I am not sure why on earth you want this in a float rather than just carry it in a 16 bit integer. You are on a micro-controller stop playing with floats when you don't need they are incredibly slow on a micro avoid them like the plague.

So lets look at things logically

Val is 10 bits and so it goes between 0 and 1023
Next you need to multiply it by 325 so the largest number is 325x1023 = 332475

That result will fit into a long being 32 bits so I suggest you change val to a long.

You can then do the division but you just throw the decimals away anyhow keeping only 3 characters at end I can see so lets rewrite the whole lot. I am sure the division is supposed to be 1024 for 10 bits not 1023 but I will leave that to you.

I also can't for the life of me work out why you want to move the strings thru 2 buffers and your attempt at CR and LF will not work :=)

Try something like

unsigned long Val;
char uart_rd[50];

.... <snip> .....

Val = (ADRESH << 8) | ADRESL;   // read dadta from channel 0
Val *= 325;                     // Multiplys Val x 325 result still in val (short hand for val = val *325)
Val /= 1023;                    // Divid Val by 1023 leave result in val (This will truncate the result)

// I guarantee you at this point Val is an integer value between 0-325 which are you 3 digits you want
// Now you need to convert it to ascii so you can use ltoa or itoa the compiler should support one
 
ltoa(Val, &uart_rd[0], 10);     // Convert Val into uart_rd buffer in radix base 10 in other words decimal

strcat(&uart_rd[0], "\r\n");    // add CR + LF to the number string

UART1_Write_Text(&uart_rd1[0]); // Now send the string out serial port 1

.... <snip> ....... 
 
Share this answer
 
v3
Comments
Member 10415564 3-May-14 9:29am    
itoa is not defined for pic16f877a mikroc
The joys of standard functions the code for them is everywhere on the net :-)
/* The Itoa code is in the puiblic domain .. daniweb*/
 char* Itoa(int value, char* str, int radix) {
 static char dig[] = "0123456789""abcdefghijklmnopqrstuvwxyz";
 int n = 0, neg = 0;
 unsigned int v;
 char* p, *q;
 
    if (radix == 10 && value < 0) {
       value = -value;
       neg = 1;
    }
    v = value;
    do {
       str[n++] = dig[v%radix];
       v /= radix;
    } while (v);
    if (neg) str[n++] = '-';
    str[n] = '\0';
    p = str;
    q = p;
    while(q && *q) ++q;
    for(--q; p < q; ++p, --q){
      *p = *p ^ *q;
      *q = *p ^ *q;
      *p = *p ^ *q;
    };
    return str;
 }

That is one of the simpler versions of the function but is only correct for negative numbers in base 10 which doesn't really matter to you.
 
Share this answer
 
v6
Comments
Member 10415564 4-May-14 12:43pm    
I included itoa function instead of float to str and though it compiles successfully,the problem is still der.
leon de boer 5-May-14 1:47am    
Be more specific what problem you should be definitely getting values between 0-325 no other option is possible assuming your UART1_Write_Text routine works.
Member 10415564 5-May-14 10:58am    
the values am getting now are

204
204
139
139
167
167
176
176
129
129
212
212
95
95
292
292
27
27
282
282
53
53
188
188
155
155
151
151
192
192
115
115
227
227 like dis///
leon de boer 5-May-14 11:55am    
Yes that is correct?

The only two issues I can see are the min/max are not reached which most likely means you have not scaled your analog input properly. You could easily check that by disconnecting the input and manually connecting it to gnd somewhere and check the code starts spitting 0 and then connect it to +5V rail and see if it starts spitting 325.

The other issue it possibly looks like there may be timing problem because it isn't following a sinosoid but that could also be the above problem. However it could also be a timing problem and I would really like to see what the code in the function

Delay_Cyc(3); //wait acquisition time

look like
Member 10415564 5-May-14 12:05pm    
i just a delay of 3 cycles pause for adc acqisition

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900