0
votes

I am trying to get a pic16 controller to run an initialization function that displays some text on an LCD only once and then goes on to display other things

The LCD output is working fine the problem is that the initialization function keeps executing. What am I doing wrong ?

/*
 * File:   main.c
 *
 * Created on Sep 1, 2013, 12:09 PM
 */


#include <pic.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "delay.h"

__CONFIG(WDTE_ON & PWRTE_ON & MCLRE_ON & BOREN_ON & FOSC_INTRCIO );

static int exec_counter = 0;

#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))      // bit mask macros
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define flip_bit(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define test_bit(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define E  RC4         //  Define the LCD Control Pins
#define RS RC5
int i;                 //  Use Global Variables for Debug

LCDWrite(int LCDData, int RSValue)
{

    PORTC = (LCDData >> 4) & 0x0F;  //  Get High 4 Bits for Output
    RS = RSValue;
    E = 1;  E = 0;                   //  Toggle the High 4 Bits Out

    PORTC = LCDData & 0x0F;          //  Get Low 4 Bits for Output
    RS = RSValue;
    E = 1;  E = 0;                   //  Toggle the Low 4 Bits Out

    if ((0 == (LCDData & 0xFC)) && (0 == RSValue))
        DelayMs(5);
    else
        DelayUs(200);

}  //

void writeLines(char top[],char bottom[]){
    for (i = 0; top[i] != 0; i++)   //  Write Line 1
        LCDWrite(top[i], 1);

    LCDWrite(0b11000000, 0);        //  Move Cursor to the Second Line

    for (i = 0; bottom[i] != 0; i++)//  Write Line 2
        LCDWrite(bottom[i], 1);

}

int countelems(char arr[]){
    for (i = 0; arr[i] != 0; i++){}
    return i;
}
void pad_number(char number[],char numberout[],char unit[]){
    int size_n = countelems(number);        // get length of number array by reference
    int size_u = countelems(unit);          // get length of unit array by reference
    int size = size_u + size_n + 1;         // calculate total size of text with 1 space between number and unit
    int L_space = floor((16-size)/2)-1;     // calculate space required on left side of display to center text
    for (i = 0; i <= 15; i++)
        numberout[i] = 0b10100000;          // fill output char array with spaces
    for (i = 0; i <= (size_n); i++){
        numberout[i+(L_space+1)] = number[i];       // fill output char array with number
    }
    numberout[L_space+size_n+1] = 0b10100000;       // put space in output char array between number and unit
    for (i = 0; i <= size_u; i++){
        numberout[i+(L_space+size_n+2)] = unit[i];  // fill output char array with unit
    }
}
void pad_text(char text[],char textout[]){
    int size = countelems(text);            // get length of char array by reference
    int L_space = floor((16-size)/2);       // calculate space required on left side of display to center text
    for (i = 0; i <= 15; i++)
        textout[i] = 0b10100000;            // fill output char array with spaces
    for (i = 0; i <= 15; i++){
        if( i >= L_space && i <= (L_space+size)){
            textout[i] = text[i-L_space];   // fill middle of output char array with text
        }
    }
}
void getAnalog(int channel,char parameter[], char unit[]){
    char output_parameter[16];
    char output_number[16];
    char number[16];
    ADCON0 = channel << 2;                  // select channel
    //set_bit(ADCON0,7);                    // set ADFM flag so LSB is bit 0 of ADRESL
    set_bit(ADCON0,0);                      // switch ADC on = set ADON flag 0b00000001
    sampleTime();                           // wait required aquisition time
    set_bit(ADCON0,1);                      // start conversion = set GO/DONE bit
    while(test_bit(ADCON0,1)){/* wait for ADC to complete conversion */;}
    int ADCresult = (ADRESL+ADRESH)/10;     // get result from ADC
    itoa(number,ADCresult,10);              // convert ADC result to charstring
    LCDWrite(0b00000001, 0);                //  Clear LCD
    pad_text(parameter,output_parameter);
    pad_number(number,output_number,unit);
    writeLines(output_parameter, output_number);
}
void init(){
    DelayMs(20);                //  Wait for LCD to Power Up

    PORTC = 3;                  //  Start Initialization Process
    E = 1;  E = 0;              //  Send Reset Command
    DelayMs(5);

    E = 1;  E = 0;              //  Repeat Reset Command
    DelayUs(200);

    E = 1;  E = 0;              //  Repeat Reset Command Third Time
    DelayUs(200);
    PORTC = 2;                  //  Initialize LCD 4 Bit Mode
    E = 1;  E = 0;
    DelayUs(200);

    LCDWrite(0b00101000, 0);    //  LCD is 4 Bit I/F, 2 Line

    LCDWrite(0b00000001, 0);    //  Clear LCD

    LCDWrite(0b00000110, 0);    //  Move Cursor After Each Character

    LCDWrite(0b00001110, 0);    //  Turn On LCD and Enable Cursor
    //          "0123456789012345"
    writeLines( "  INITIALIZE    ",
                "     TEXT       ");

}
void main(void) {
    OPTION_REG |= 0x7;  // set prescaler to 1:128 or 2.3 Seconds
    OPTION_REG |= 0x8;  // assign prescaler to WDT
    TRISA = 0b00000101; // configure PORTA set RA0 and RA2 to analog input;
    ANSEL = 0b00000101; // disable input buffers if I/O pins RA0 and RA2
    TRISC = 0;          // configure PORTC as output
    ADCON1 = 0;         // select FOSC2
    if (exec_counter == 0){
        exec_counter++;
        init();
        DelayS(4);
    }
    PORTC = 0;

    while (1) {
        getAnalog(0,"VELOCITY","KM/H");
        DelayS(4);
        getAnalog(2,"ACCELERATION","M/S^2");
        DelayS(4);
    }
    return;
}

/*
 * File:   delay.c
 *
 * Created on Sep 3, 2013, 12:09 PM
 */

#include "delay.h"
#include <pic.h>
#define _XTAL_FREQ 4000000

void DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
        do {
                DelayUs(996);
        } while(--cnt);
#endif

#if    XTAL_FREQ > 2MHZ
        unsigned char   i;
        do {
                i = 4;
                do {
                        DelayUs(250);
                } while(--i);
        } while(--cnt);
#endif
}

void DelayS(unsigned int count){
    for (int i=0; i<=count;i++){
        NOP();
        CLRWDT();
        DelayMs(1000);
    }
}

void sampleTime(){
    // TC = – 10pF ( 1k Ω + 7k Ω + 1k Ω ) ln(0.0004885)
    //    = 0.686 μS
    // TACQ = 5μS + 0.686μS + [ ( 50°C- 25°C ) ( 0.05μ S /°C ) ]
    //      = 6.936 μS /
    // 1 instruction cycle = 4μS @ 1 mHz
    // 1 instruction cycle = 1μS @ 4 mHz
    // 1 instruction cycle = 500nS @ 8 mHz
    // 1 instruction cycle = 200nS @ 20 mHz
    // TACQ @  1 mHz is 6.936 μS / 4 μS   or ~  2  instruction cycles
    // TACQ @  4 mHz is 6.936 μS / 1 μS   or ~  7  instruction cycles
    // TACQ @  8 mHz is 6.936 μS / 0.5 μS or ~  14 instruction cycles
    // TACQ @ 20 mHz is 6.936 μS / 0.2 μS or ~  35 instruction cycles
    DelayUs(8);
}
1
... no idea. Are you sure "//do stuff" is not causing soemething funny? Have you tried substrituting it for nothing/blinking led?Vorac
where is your initialization function ? I dont see it in the code postedPradheep
Is it possible that the watchdog keeps resetting your controller?dialer
Please post your init() function. Can't help you otherwise.It'sPete
thanks for feedback modified original post to include entire codeuser2740888

1 Answers

0
votes

The char number[] = ""; array is very small, yet you use it in itoa(), thus overwriting random memory.