CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Internal write_eeprom Question !!!

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Chipunused
Guest







Internal write_eeprom Question !!!
PostPosted: Tue Feb 28, 2006 2:53 pm     Reply with quote

Hello,
Anytime external interrupt occur, i receive the same value at the same address. Idealy, i would like to increment to new address with new value anytime i interrupt occur. (100 Max)
what am i doing wrong? Can you please give me some advises.
- thank you
TP
Code:

//////////////////////////////////////////////////////////////////////////
#include <16F877A.h>
#device ADC=10
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stddef.h>

#rom 0x2100={0x00}
//#rom 0x2100={0x55, 0xAA, 0x01, 0x23, 0x45, 0x67, 0x89}
#fuses HS,NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use delay(clock=8000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12
#include <input.c>
#define EEPROM_SIZE 256

float adresult =0;
int8 address,energyresult;

#int_rda
void rs232_irs()
{   
   char statusw,add;
   statusw = getc();
   if (statusw == 'R')
     {
       printf("\r\n\nEEPROM:\r\n");
      printf( "rda Read %X", read_eeprom(address) );
        printf("\n\r");         
     }
   else{
   break;  //for now
   }
}      
#int_ext
void external_isr()
{   
   output_high(PIN_B1);         //turn on relay
   delay_ms( 20 );             //delay 20ms
   adresult = read_adc();         //read ADC and save in adresult
   output_low(PIN_B1);          //turn off relay
   delay_ms(10);                //10ms delay for settling time

   energyresult = ((adresult*.02928267) - (.8048504)-4);       // Y=mX + B
   energyresult++;              //
   write_data = write_eeprom(address,energyresult);
   printf("Read: %X\n\r",read_eeprom(address));
   printf("\n\r");
}

void init()
{
   enable_interrupts(global);
   enable_interrupts(int_rda);          //turn on rs232 receive interrupt
   ext_int_edge(L_TO_H);             //rising edge interrupt on portb0
   enable_interrupts(int_ext);          // enable portb0 interrupt
   setup_adc_ports( AN0_AN1_VSS_VREF ); //an0 is analog input RA3 is reference voltage
   setup_adc(ADC_CLOCK_INTERNAL);       //use internal rc clock for a/d converter
   output_low(PIN_B1);                //
   set_adc_channel(0);                // read channel AN0   
   delay_us(10);                   //settling time delay
}
void main()
{
   init();            // initialize values 
   while(1){};       //do nothing loop wait for interrupt
}

I use this simple test from PC_Programmer, it works fine for hardcode values.
Code:

#rom 0x2100={0x55, 0xAA, 0x01, 0x23, 0x45, 0x67, 0x89}
#fuses HS,NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use delay(clock=8000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12
   
#int_ext
void external_isr()
{   
   char value, addr;
   output_high(PIN_B1);         //turn on relay
   delay_ms( 20 );             //delay 20ms
   adresult = read_adc();         //read ADC and save in adresult
   output_low(PIN_B1);          //turn off relay
   delay_ms(10);                //10ms delay for settling time

   for(addr = 0; addr < 9; addr++)
     {
      value = read_eeprom(addr);
      printf("erop: %X\n\r", value);
     }
      printf("\n\r");
}
Ttelmah
Guest







PostPosted: Tue Feb 28, 2006 4:08 pm     Reply with quote

The maths for 'energy result', will give -ve results for any incoming value below 164. Since energy result is only an int8, and not signed, this will result in silly values.
The actual code is really bad (sorry, but it has to be said). There is no point at all really in using an interrupt anywhere here, since as written, the code prevents them from working. Basically, if the 'R' character arrives on the RS232, the serial will be disabled for about 8mSec, leading to overflows if anything else is typed. Address is not initialised/changed anywhere, so what is the point of using a variable?. The 'edge' interrupt, will kill serial input for probably about 100 character times, again killing the reason to use interrupts. As a minor comment, don't use ADC_CLOCK_INTERNAL, above a 4mHz processor clock if you want accuracy.

Best Wishes
Chipunused
Guest







PostPosted: Tue Feb 28, 2006 7:34 pm     Reply with quote

Thank you for your comment, as a newbie @ programming, I learn alot from reading examples from this forum. Give me time, sure i will get better. Laughing Laughing
As far as increment write_eeprom (address, value). I can't find any example. if you see it somewhere please post me a link. All i would like to learn is how to use ext interrupt, Convert ADC, write_eeprom (from 0 to address 127 then wrap arround), read_eeprom (when receive a char).
once again, thank you for all your advises
TP
Ttelmah
Guest







PostPosted: Wed Mar 01, 2006 7:57 am     Reply with quote

This is only part of the code (you will need to sort out the initalisation, the artithmetic, etc., as well as checking the actual functionality - the code has not been checked at all), but gives an idea of how I'd possibly appoach the problem.
Code:

int8 address=0,last_address=0;

int8 sbuff[8];
int8 inp_loc=0,out_loc=0;
int8 tbuff[32];
int8 tinp_loc=0;tout_loc=0;

/*Note that neither the receive or transmit handlers have any checking for
overflow.
Hopefully the buffers are large enough to avoid this, but it may need to be
considered/added, depending on what else is done in the code. */

//Receive character and add it to the input buffer
#int_rda
void rs232_receive_isr(void) {   
   sbuff[inp_loc]=getc();
   inp_loc = (inp_loc+1)&7;
}

//Check if a character is present in the input buffer
#define sbuff_kbhit() (inp_loc!=out_loc)

//Get a character from the input buffer
int8 sbuff_getc(void) {
   int8 temp;
   while (!sbuff_kbhit()) ;
   temp=out_loc;
   outloc = (out_loc+1)&7;
   return (sbuff[temp]);
}

//Check if a character is waiting in the output buffer
#define tbuff_data_waiting() (tinp_loc!=tout_loc)

//Handle character transmission
#int_tbe
void rs232_transmit_isr(void) {
   /* If characters are waiting in the buffer, the next one is transferred
   to the UART
   otherwise the interrupt is disabled, waiting for the next transmission. */
   if tbuff_data_waiting() {
     putc(tbuff[tout_loc]);
     tout_loc=(tout_loc+1)&31;
   }
   else
     DISABLE_INTERRUPTS(INT_TBE);
}

void rs_putc(int8 val) {
   /*Routine to send a character to the interrupt driven transmit handler
   */
   disable_interrupts(INT_TBE);
   tbuff[tinp_loc]=val;
   tinp_loc = (tinp_loc+1)&31;
   enable_interrupts(INT_TBE);
}   

void main(void) {
   int8 temp;
   int1 old_input;
   int16 adresult;
   //Note don't bother to enable external interrupt in init, also
   //don't enable the
   //int_tbe. The code handles this automatically, when data is printed.
   init();
   old_input=input(PIN_B0);
   //Loop checking if the input pin is active, or a character is received
   while (true) {
     if (sbuff_kbhit()) {
        //Here a serial character has been received
        temp=sbuff_getc();
        if (temp=='R' || temp=='r') {
           //Retrieve fom the _last_ written address
           printf(rs_putc,"\r\n\nEEPROM Read: %2X\n\r",read_eeprom(last_address));
        }
     }
     if (old_input!=input(PIN_B0)) {
        //Here the input pin has changed
        if (old_input==0) {
           //Here there is a rising edge
           output_high(PIN_B1); //Turn on relay
           delay_ms(20);
           adresult=read_adc();
           output_low(PIN_B1);  //Turn off relay
           last_address=address;
           //Now the arithmetic should provide the required settling time
           //At this point, you need to sort out the arithmetic.
           //With the current code, for an adc value of '0', the code will give
           //0 - 4.8048504 = -4
           //For a value of 100, this will give
           //2.928267 - 4.8048504 = -1
           //While for a maximum input of 1023, it'll give
           //29.95617141 - 4.8048508 = 25
           //A maximum reading of just 25, when trimmed to an integer....
           //Do your maths here, and write the value to the EEPROM
           //Then if required, print the result (to rs_putc).

           

           old_input=1;
           //Now move so that the _next_ write, will be to the next address
           //in the EEPROM
           address = (address+1) % 100;
        }
        else old_input=0;
     }
   }
}

Note that the response to the input pin is not interrupt based. There is no advantage to interrupt response here - an interrupt will take at least 30 instruction times to respond, and will result in other interrupt events being stopped while the code handles this, which as it has long delays, is 'non desirable.
Note also, you should add 'errors' to your RS232 initalisation.

Best Wishes
Chipunused
Guest







PostPosted: Fri Mar 03, 2006 12:51 pm     Reply with quote

Thank you Ttelmah. You are going really far to help other
TP
Chipunused
Guest







16F877A ADC what could be wrong?
PostPosted: Wed Mar 08, 2006 7:09 pm     Reply with quote

What can be wrong? using PCW 3.236, MPLAP7.30
Input to pin B1 is a ramp up from 600mV for 2mS. Increase Input from 0.6V to 1V. ADC --> output won't change.
Code:
ADRESH = 0x03
ADRESL = 0xFF.

And Result is alway 1D
including is my code, can someone take a look please.
Thank you for your time.
TP

Code:
#include <16F876A.H>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 8000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

void main()
{
   int16 result;
//   set_tris_a(0xFF);
     enable_interrupts(global);
     ext_int_edge(L_TO_H);   
   enable_interrupts(int_ext); 
   setup_adc_ports(AN0_AN1_VSS_VREF);    //an0 is analog input RA3 is reference voltage
// setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_DIV_16);  //use internal rc clock for a/d converter
   set_adc_channel(0);                // read channel AN0   

while(1)
  {
   output_high(PIN_B1);      // Cap on
   delay_ms(20);
   result = read_adc();
   printf("\r\nResult: %2X\n\r", result);
   output_low(PIN_B1);      // Cap off
   delay_ms(500);
  }
}
Ttelmah
Guest







PostPosted: Thu Mar 09, 2006 3:50 am     Reply with quote

Obvious first comment. Are you using RA3 as a reference or not?
You have two setup_adc_ports lines. The second will override the first, and neither uses RA3 as a reference, mentioned in the comment.
The 'A' chips, have a comparator module as well as the ADC connected to the analog inputs. Try turning this off (setup_comparators(NC_NC_NC_NC)). There is a nasty habit on some compiler versions, of leaving this enabled...
I'd suspect that possibly it is the two setup lines causing an unexpected configuration, and the chip is not actually seeing a reference voltage (from either Vdd, or RA3), hence is always returning 1023 (which is what you will get when the signal is at or above the reference voltage).
Alternatively, the input is at a different voltage to what you expect. Can you check with a scope, what voltage is actually on the input?.

Best Wishes
Chipunused
Guest







PostPosted: Thu Mar 09, 2006 2:45 pm     Reply with quote

Using MPLAP ICE 2000 with PCM16XK1 moudule for 16F877. ADC result as expected. when i use PCM16XV0 moudle for 16F877A. (Vref is 4.096V)(Comparators off). Result from ACD alway the same number, it doens't matter what input range. (PIN_A0 is connected to Follower Buffer). Could it be impedance?
Thank you
TP
Ttelmah
Guest







PostPosted: Thu Mar 09, 2006 3:42 pm     Reply with quote

What sort of 'follower buffer'?. Op-amp as a voltage follower?. Emitter follower?. etc. etc..
How is Vref fed?. What is the voltage at the chip?.
What is your actual line for setup_adc_ports?.
Using the simulator, check that the registers for the ADC are correctly configured. There have been problems at times in the past, with the compiler accessing the wrong registers on particular chips. I don't remember this applying to 3.236, but it might be..

Best Wishes
Chipunused
Guest







PostPosted: Fri Mar 10, 2006 8:59 am     Reply with quote

I use Op-amp as a voltage follower for PIN_A0.
Vref is fed by Volt Ref MCP1541.
For ports setup i use:
setup_adc_ports(AN0_AN1_VSS_VREF); and also try (ALL_ANALOG);
setup_comparators(NC_NC_NC_NC);
Registers for ADC are correctly configured.

Thanks,
TP
Ttelmah
Guest







PostPosted: Sat Mar 11, 2006 9:45 am     Reply with quote

If the reference voltage is actually at the Vref pin, has it's required decoupling capacitor, and the voltage on the analog input is at a sensible value, the code ought to work.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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