Jump to content

davidb

EstablishedMember
  • Content Count

    134
  • Joined

  • Last visited

Posts posted by davidb

  1. Hi Samith,

     

    Not sure what you are trying to achieve but I have made a few subtle changes to your code so that the lower 8-bits of the adc value are placed on Port B. See if that works on your hardware.

     

    Regards

     

    davidb

     

     
    #include <system.h>
    #pragma CLOCK_FREQ 4000000
    //#pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _LVP_OFF & _PWRTE_OFF & _CP_OFF
    unsigned int Read_adc(unsigned char ch);
    void Adc_init();
    void main()
    {
    //Initialise PortB
    trisb = 0; //configure port B
    portb = 0; //clear port B
    //initialise portA
    trisa = 1; //porta as input
    Adc_init();
    while(1)
    {
     unsigned short val; //10-bit Adc value
     val = Read_adc(0); //read channel 0 into val
     portb = (unsigned char) val; // Can only show lower 8 bits on port
    }
    }
    
    //AD intialisation
    void Adc_init()
    {
    set_bit( adcon1, ADFM ); // AD result needs to be right justified
    //clear_bit(adcon1,ADCS2); //this register only used for 877A
    clear_bit( adcon1, PCFG0 ); // one analogue in put
    set_bit( adcon1, PCFG1 ); // Vref+ = Vdd
    set_bit( adcon1, PCFG2 ); // Vref- = Vss
    set_bit(adcon1, PCFG3);
    clear_bit( adcon0, CHS0 ); // Channel 0
    clear_bit( adcon0, CHS1 ); //
    clear_bit( adcon0, CHS2 ); //
    set_bit( adcon0, ADCS1 ); // Select Tad = 32 * Tosc (this depends on the Xtal here 10 MHz, should work up to 20 MHz)
    clear_bit(adcon0,ADCS0);
    }
    unsigned int Read_adc(unsigned char ch) // ch not required as already fixed in function
    {
    unsigned short adcvalue;
    
    if(ch>4) return 0;
    clear_bit( adcon0, CHS0 ); // Channel 0
    clear_bit( adcon0, CHS1 ); //
    clear_bit( adcon0, CHS2 ); //
    delay_us(100);
    set_bit(adcon0,ADON);
    set_bit(adcon0,GO); // Start conversion
    while(adcon0.GO == 1);
    // clear_bit(adcon0,ADON); // Leave converter running
    
    MAKESHORT(adcvalue,adresl,adresh);
    return adcvalue; // Return 10-bit adc value
    } 
    

  2. Hello.

     

    In my heades file I decleare a variable:

     

    //Header test.h:

     

    #define TEST

     

    #ifndef TEST

    volatile bit spi_cs @ PORTC . 2;

    bit spi_cs_tris @ TRISC . 2;

    #endif // TEST

     

    //

    //

     

    Than on the main program I try to use the variable:

     

    main test.c

     

    spi_cs_tris = 0; // Portc,2 as output.

    spi_cs = 1; // Portc, 2 Hi.

     

    For some reason the variable "spi_cs" gives an error (variable not found) in compiling the main code.

    What is wrong?

     

    Thanks Martin

     

    Martin,

     

    You have defined TEST and then carried out a check to see if is NOT defined. Since this must be false then the variables will not be defined.

    Change the #ifndef TEST to #ifdef TEST and all should be fine.

     

    Regards

     

    davidb

  3. Hi,

     

    Problem: The following simply test code demonstrates the problem using

    signed data types and the comparison if (error > limit).

     

    Expected Behaviour: To work correctly x should be 1 less than y at the end

    of the comparison loop.

     

    If the code is compiled for a 16F887 then all works as expected with

    error defined as any data type; signed char, signed short or signed long.

     

    If the code is compiled for a 18F4520 then it fails if error is a signed short

    but works correctly for signed char and signed long.

     

    It also works correctly if the limit definition is changed to any signed data type.

     

    #include <system.h>
    static signed short error = -60;
    static unsigned char x;
    static unsigned char y;
    #define limit -50
    //signed short limit = -50;
    
    void main()
    {
    for (error = -60; error < 60; error++)
    {
     if (error > limit) //Fails
     {
      x++;
     }
    
     if (error >= limit) //O.K.
     {
      y++;
     }
    }
    for (;;
    }
    

     

    IDE: MPLAB V8.83

    Compiler: SourceBoost C V7.05.1

    Targets: PIC16F887, PIC18F4520

    Reproducible: 100%

    OS: XP Pro, Vista

     

    Regards

     

    davidb

  4. Hi iiyama87,

     

    Unfortunately you cannot directly compare a string with the contents of a string buffer.

     

    What you need to do is create a string parser that will process data in your buffer character by character.

     

    Try sending and detecting a single character (followed by NULL) first and build on that.

     

    All HyperTerminal is doing is receiving and displaying what you sent character by character.

     

    Google something like 'RS232 String Parser'.

     

    Good luck

     

    davidb

  5. No. LATx always reads as the last value written to it.

    Not always strictly true. To quote from PIC18F4520 datasheet:

    Pins RA6 and RA7 are multiplexed with the main oscillator pins; they are enabled as oscillator or I/O pins by the selection of

    the main oscillator in the configuration register (see Section 23.1 “Configuration Bits” for details). When they are not used as

    port pins, RA6 and RA7 and their associated TRIS and LAT bits are read as ‘0’.

    Hope that helps

     

    davidb

  6. Hi,

     

    Yes that works, i programmed he device, then read back the eeprom and it is correct.

     

    How strange. Any idea why MPLAB ignores the correct address? Where did 0xf000 come from?

     

    In case you don't know where to find it (once I spent a long time looking in the devices data sheet and it's not in there) , you can find the address that needs to used when programming the target device and wanting to write to EEPROM as part of this process in the devices "Memory Programming Specification" data sheet from Microchip.

     

    BTW: I know this doesn't help with the 0xf000 address question.

     

    Regards

    Dave

    Dave,

     

    The specification states that:

     

    The physical address range of the 256 byte data

    memory is 0000h-00FFh. However, these addresses

    are logically mapped to address 1E000h-1E1FFh in the

    hex file. This provides a way of differentiating between

    the data and program memory locations in this range.

    The format for data memory storage is one data byte

    per address location, LSb aligned.

     

    Note that it says mapped to the HEX file address.

    The hex file uses double bytes so the range 1E000h-1E1FFh gives 512 bytes for 256 bytes of EEPROM.

    Halving the hex address gives us F000 - F0FF which appears to be correct.

     

    davidb

  7. hi,

     

    I have used #pragma DATA _EEPROM, 99, 99, 99 successfully on a 12F device, but im now using a 16F1827, and MPLAB appears to not reconise the eeprom data?

     

    Can someone that knows hex files have a look to check this feature is working ?

     

     

     

    Thanks! :rolleyes:

     

    Microchip document DS41390C defines the physical address range for EEPROM on the 16F1827 as 0x1E000 to 0x1E1FF. SourceBoost PIC16F1827.h defines _EEPROM as 0x1E000 so all would appear to be well but as you point out it doesn't seem to work in MPLAB. However, changing the definition in PIC16F1827.h to 0xf000 seems to allow it to work in MPLAB. Not sure whether it works on a real device though!

     

    davidb

  8. Does anyone have C code that converts the hour portion of UTC to the local time's hour (offset -5 hours for EST, -4 hours for EDT, in my case)? The answer would seem obvious (UTC minus the offset), but this equation falls apart when UTC is between 00 and 05 hours.

     

    Any suggestions please?

    Perhaps I have misread your problem but how about something like:

     

    if (UTC_hour < offset) local_time = (UTC_hour + 24) - offset;
    else local_time = UTC_hour - offset;

    Regards

     

    davidb

  9. The value of tmp_value_m is always FFFF, so where is my failure?

     

    THX for help

    Fizzel

    You haven't told us which part you are using or shown your variable definitions.

    Also the maximum result from the ADC should only be 0x03ff.

     

    Your code for converting adresl and adresh to 16 bits is long winded and unless both tmp_h and tmp_value_m are defined as shorts then it will not work.

     

    If you use:

    tmp_value_m = (tmp_h <<8) | tmp_l;

    instead then that should work. However, the code would be more efficient if you re-define adresl as a short or alternatively use a union:

    unsigned short adresult @adresl;

    then simply copy the result:

    tmp_value_m = adresult;

     

    Regards

     

    davidb

  10. This problem also exists on V6.97

    #include <system.h>
    
    typedef struct {
    unsigned char DeviceAddress;
    unsigned char NumRxDataBytes;
    } TTestStruct;
    
    TTestStruct s;
    
    void main(void)
    {
    s.DeviceAddress = 1;
    s.NumRxDataBytes = 0x55;
    
    if (--s.NumRxDataBytes)
    {
    	 while(1);
    }
    }

    As does this but with a different error:

    #include <system.h>
    
    unsigned char s[] = {1,0x55};
    
    void main(void)
    {
    
    if (--s[1])
    {
    	 while(1);
    }
    }

     

    However this works:

    #include <system.h>
    
    typedef struct {
    unsigned char DeviceAddress;
    unsigned char NumRxDataBytes;
    } TTestStruct;
    
    TTestStruct s;
    
    void main(void)
    {
    s.DeviceAddress = 1;
    s.NumRxDataBytes = 0x55;
    
    if (--s.NumRxDataBytes != 0)
    {
    	 while(1);
    }
    }

    As does this:

    #include <system.h>
    
    unsigned char s[] = {1,0x55};
    
    void main(void)
    {
    
    if (--s[1] != 0)
    {
    	 while(1);
    }
    }

     

    Regards

     

    davidb

  11. Rather a lot of code to wade through and I don't have the time so just a few comments:

     

    I notice that in your i2c_is_data_ready() function you are clearing the SSPIF interrupt flag several times but have missed it after 'Master Write, Last Byte was Data'.

    You only need to clear this flag once so re-arrange the code and do it at the beginning and remove all the other instances.

     

    Secondly I would recommend that the slave receive function is carried out under interrupt with suitable data and address buffering rather than being polled.

    I haven't used I2C with the 16F88* family but when using it with an 18F4520 I found that using set_bit(sspcon1, CKP); at the end of the interrupt

    ensured that the clock line was always released thereby preventing lockups.

     

    Regards

     

    davidb

  12. Mark,

     

    For what you are trying to do you only need:

    uartTxInterruptHandler();
    uartRxInterruptHandler();

    in your interrupt function to handle the UART.

     

    These two functions handle the transmitting and receiving of characters to and from the PC via the UART entirely under interrupt control.

     

    uartRx() and uartTx() are effectively getc() and putc() respectively and access the rxBuffer[] and txBuffer[] buffers used by uartRxInterruptHandler() and uartTxInterruptHandler().

     

    In your main() to send data simply place it in the txBuffer[] using uartTx().

    Any data received will be in the rxBuffer[] so before reading it using uartRx() see if there is any data in it by checking if rxCnt > 0.

     

    How you handle the data after that is up to you!

     

    I haven't checked the rest of your code regarding UART setup etc.

     

    Regards

     

    davidb

  13. String question. How do I break up a large string so that it doesn’t run on past the right edge of the IDE code window?

    I have a HTML text string that is about ~150 chars long. I can’t seem to figure out how to split it up into multiple lines such that I can neatly view the whole thing in the IDE window. If I do the following the IDE hates it and the compiler serves up an error:

    rom char *httpHeader1 = "<html>
    <head>
    <title>Tower-Cam Test</title>
    <body>
    <h2>Tower Camera Sensors </h2>
    <p>Battery Voltage goes here:</P>
    <p> Temperature goes here:</p>
    <p>Time goes here:</p>
    </body>
    </html>";

     

    However if the string is all contained on one line extending well past the right edge, the IDE is happy and it compiles ok. Other compilers alow me to do this but not SB-C. So what have I missed? :unsure:

     

    You are including new line characters in your string so try using the continuation character after each line (not tested):

    rom char *httpHeader1 = "<html>\
    <head>\
    <title>Tower-Cam Test</title>\
    <body>\
    <h2>Tower Camera Sensors </h2>\
    <p>Battery Voltage goes here:</P>\
    <p> Temperature goes here:</p>\
    <p>Time goes here:</p>\
    </body>\
    </html>";

    Regards

     

    davidb

  14. #pragma DATA 0x300000,0x00,0x02
    #pragma DATA 0x300002,0x1a,0x0e
    #pragma DATA 0x300004,0x00,0x83
    #pragma DATA 0x300006,0x85,0x00
    #pragma DATA 0x300008,0x0f,0xc0
    #pragma DATA 0x30000a,0x0f,0xe0
    #pragma DATA 0x30000c,0x0f,0x40

    The following uses #pragma config and should produce the same configuration as above:-

    /* 18F4520 Configuration Words */
    
    /* Internal/External Oscillator config */
    
    #pragma config OSC = HS, FCMEN = OFF, IESO = OFF
    
    /* Power & Brown-out Reset Voltage config */
    
    #pragma config PWRT = ON, BOREN = ON, BORV = 3
    
    /* Watchdog Timer config */
    
    #pragma config WDT = OFF, WDTPS = 128
    
    /* Miscellaneous config */
    
    #pragma config CCP2MX = PORTC
    #pragma config PBADEN = ON
    #pragma config LPT1OSC = OFF
    #pragma config DEBUG = OFF
    #pragma config MCLRE = ON
    #pragma config STVREN = ON
    #pragma config LVP = ON
    #pragma config XINST = OFF
    
    /* Code protection config */
    
    #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
    #pragma config CPB = OFF, CPD = OFF
    
    /* Write block protection config */
    
    #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF
    #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
    
    /* Table read block protection config */
    
    #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF
    #pragma config EBTRB = OFF

    Regards

     

    davidb

  15. In addition to the above regarding debouncing, toggling the LED etc. your code has a few basic errors for real life operation (I never use the simulator so I can't comment on that):

     

    You have your switch on the wrong pin to use INTF - it should be on RB0 not RB1

    Depending on how your switch is connected you will probably need to set the edge direction and possibly the internal pullup in OPTION_REG.

     

    PEIE should also be set to enable the interrupts (INTCON = &d0)

     

    Regards

     

    davidb

  16. Hello folks.

     

    The expression "while ((!tmr0if) || (rcif == 0));" never is true, why? The idea is that, if no data is received from USART the timer overflow flag TMR0IF is set (INTCON,2) and the program continuous.

     

     

     

    The extraxt of the code is:

     

     

     

    volatile bit tmr0if@INTCON.2; // Timer0 overflow.

     

    volatile bit tmr0on@T0CON.7; // Timer0 enable bit.

     

     

     

    t0con = 00010011b; // disable timer, 16 bit, Prescaler 1/16.

     

    tmr0on = 1; // enable (starts) timer0.

     

     

     

    while ((!tmr0if) || (rcif == 0)); // for 8Mhz the delay is aprox. 0.5s.

     

    set_bit (portc,3); // LED on.

     

    tmr0on = 0; // (stops) timer0.

     

    After a quick glance I don't see a definition for rcif e.g. volatile bit rcif@PIR1.RCIF; or is this somewhere else?

    Alternatively use something like !(test_bit(intcon,TMR0IF)) and !(test_bit(pir1,RCIF)) instead of individually mapping bits.

     

    rcreg also needs to be read somewhere to ensure that the receive data interrupt flag is cleared.

     

    Also how about initialising timer0 and clearing the interrupt flag tmr0if before starting the timer so you know the initial conditions?

     

    Regards

     

    davidb

  17. Hello everybody.

    Can anybody tell me why the program works only if I configure the ADCON2 to Fosc/2. I use a 20Mhz external OSC. So I need (reading the datasheet of the PIC) at least 12 TAD to make the conversion correct. If I change the bits ADCS2-ADCS0 (ADCON2 registor) to something else then Fosc/2 the progrma stops working at all.

     

    Thanks for help. Martin

    Martin,

     

    Shouldn't

    while (Go_Done == 0);

    be [/code] or

    while (Go_Done != 0);

    For 20MHz Oscillator try using a Tad of 16Tosc and Tacq of 4Tad

    This gives an automatic 3.2uS aquisition time and 9.6uS conversion time

     

    Regards

     

    davidb

×
×
  • Create New...