PIC16F877A using MBLAB IDE (HITECH C Compiler) Beginner Question

Discussion in 'Programmer's Corner' started by Dan_xd45, Nov 8, 2014.

  1. Dan_xd45

    Thread Starter New Member

    Oct 13, 2014
    5
    0
    Hey all,

    I am a newb when it comes to microprocessors and the C programming language. I am currently working on a project and have hit a programming standstill. I am using C to perform a calculation to a variable declared as an integer. I currently am trying to output that integer to LCD using 8 bit transfer over PORTB of my chip. I believe I have to convert the integer to BCD, then convert to ASCII before outputting. Currently, I have the math done, then separated the resulting integer to a high byte and low byte char's. I will paste my existing code in below. Any help/suggestions would be greatly appreciated.

    Code (Text):
    1.  
    2. #include <htc.h> //uses non-legacy pic16f877a.h
    3. #include <math.h>
    4.  
    5.  
    6. __CONFIG (0X02F0A);
    7.  
    8.  
    9. #define SNSR1 RA2             //Sensor1
    10. #define SNSR2 RA3             //Sensor2
    11. #define LCD_EN RA0             //LCD register select
    12. #define LCD_RS RA1             //LCD enable
    13. #define LCD_DATA PORTB         //LCD 8-bit parallel data
    14. int vol @ 0X40;
    15. unsigned char count @ 0X44;
    16. unsigned char hi_byte @ 0X4A;
    17. unsigned char lo_byte @ 0X4B;
    18. /************************************************************/
    19. /*       Apply a pulse to the LCD Enable (E) input          */
    20. /************************************************************/
    21. void lcd_toggle()
    22.     {
    23.     LCD_EN=1;
    24.     _delay(5);                //1us delay
    25.     LCD_EN=0;
    26.     }
    27.  
    28. /************************************************************/
    29. /*     Write one byte to LCD w/no change to RS line         */
    30. /************************************************************/
    31. void lcd_write(unsigned char c)
    32.     {
    33.     _delay(200);            //40us delay
    34.     LCD_DATA = (c);
    35.     lcd_toggle();            //put data (character) into LCD
    36.     }
    37.  
    38. /************************************************************/
    39. /*        Clear the LCD and go to home position             */
    40. /************************************************************/
    41. void lcd_clear(void)
    42.     {
    43.     LCD_RS = 0;
    44.     lcd_write(0x01);
    45.     _delay(10000);            //2ms delay
    46.     }
    47.  
    48. /************************************************************/
    49. /*  Set RS line hi and write string of characters to LCD    */
    50. /************************************************************/
    51. void lcd_charstring(const char * s)
    52.     {
    53.     LCD_RS = 1;             //write data (characters)
    54.     while(*s)
    55.     lcd_write(*s++);
    56.     }
    57.  
    58. /************************************************************/
    59. /*     Set RS line hi and write a character to LCD          */
    60. /************************************************************/
    61. void lcd_char(char c)
    62.     {
    63.     LCD_RS = 1;
    64.     lcd_write( c );
    65.     }
    66.  
    67. /************************************************************/
    68. /*       Set LCD cursor to a specific location LCD          */
    69. /************************************************************/
    70. void lcd_goto(unsigned char pos)
    71.     {
    72.     LCD_RS = 0;             //write instruction
    73.     lcd_write(0x80+pos);
    74.     }
    75.  
    76. /************************************************************/
    77. /* Initialize LCD - 0x30,0x30,0x30,0x38,0x0C,0x01,0x06,0x02 */  
    78. /************************************************************/
    79. void lcd_init()                //initialize to 8 bit mode
    80.     {
    81.     char init_value;
    82.     init_value = 0x30;
    83.     ADCON1=0b00000111;
    84.     TRISA=0b01100;             //PORTA all outputs (E and RS)
    85.     TRISB=0b00000000;         //PORTB all outputs (data lines)
    86.     LCD_RS = 0;
    87.     LCD_EN = 0;
    88.     _delay(75000);             //wait 15ms after power applied,
    89.     LCD_DATA = init_value;     //execute 3 times
    90.     lcd_toggle();             //put instruction into LCD
    91.     _delay(25000);            //5ms delay
    92.     lcd_toggle();
    93.     _delay(1000);            //200us delay
    94.     lcd_toggle();
    95.     _delay(1000);            //200us delay
    96.     LCD_DATA = 0x38;         //8-bit mode; 2 lines; 5x8 dots
    97.     lcd_toggle();
    98.     lcd_write(0x0C);         //display on, cursor off, position 0
    99.     lcd_clear();             //clear screen
    100.     lcd_write(0x06);        //set cursor mode to increment
    101.     }
    102.  
    103. /************************************************************/
    104. /*                       Intro Message                      */  
    105. /************************************************************/
    106. void lcd_intro()
    107.     {
    108.     lcd_init();
    109.     _delay(150000);
    110.     lcd_goto(0);
    111.     lcd_charstring("Infrared Ballistic Chronograph");
    112.     _delay(2500000);
    113.     lcd_clear();
    114.     }
    115.  
    116.  
    117. /************************************************************/
    118. /*                     Velocity Calculation                 */  
    119. /************************************************************/
    120. void calc()
    121.     {
    122.     hi_byte=0x00;
    123.     lo_byte=0x00;
    124.     vol=(50000/count);
    125.     hi_byte=(vol >> 8);
    126.     lo_byte=vol;
    127. //THIS IS WHERE I'M STUCK
    128.     }
    129.  
    130. /************************************************************/
    131. /*                       Main Program                       */  
    132. /************************************************************/
    133. void main(void)
    134.     {
    135.     count=0x64;
    136.     lcd_intro();
    137.         while(SNSR1 == 0 || SNSR1 == 1)
    138.         {
    139.             if (SNSR1 == 1)
    140.             {
    141.                 while(SNSR2 == 0)
    142.                 {
    143.                 _delay(100);    //20us delay
    144.                 count++;
    145.                 }
    146.             lcd_init();
    147.             _delay(150000);
    148.             lcd_goto(0);
    149.             calc();
    150.             for(;; );
    151.             }
    152.         }
    153.     }
    154.  
     
    Last edited by a moderator: Nov 9, 2014
  2. shteii01

    AAC Fanatic!

    Feb 19, 2010
    3,399
    497
    First. Hi Tech C has functions for lcd so you don't need to reinvent the wheel: http://electrosome.com/interfacing-lcd-with-pic-microcontroller-hi-tech-c/

    Second. The simple way is to just compare your integer to a known integer and when the comparrasing match, print the char on lcd:
    if(0==your varialbe that contains integer){send character zero to lcd}
    if(1==your varialbe that contains integer){send character one to lcd}
    and so forth. The problem with this approach is that you can only show on lcd integers that you have if statements for. For example lets say I have created if statements for numbers 0-9, what if I want to show 10, I will not be able to do it because the series of if statements that I created does not have an entry for 10. So while the approach above is clear and straightforward, it is also not very flexible. If you need to show on lcd just a few numbers (say 20 or less numbers), I would suggest simply creating the list of if statements to send the character you need to lcd. If you need more than that, I would come up with something more sophisticated.
     
  3. adam555

    Active Member

    Aug 17, 2013
    858
    39
    This is what I came up with last week as a quick fix for the same problem (I'm using 4 bits and XC8, not Hi-Tech):

    Code (Text):
    1. void LCD_WriteInt(uint32_t data)
    2. {
    3.     uint8_t i = 0;
    4.     unsigned char cdata[16];
    5.  
    6.     sprintf(cdata, "%lu\0", data);
    7.  
    8.     while(cdata[i]!='\0')
    9.     {
    10.         lcddata(cdata[i]);   // Call lcddata function to send characters
    11.                             // one by one from ?data? array
    12.         i++;
    13.     }
    14. }
     
  4. Dan_xd45

    Thread Starter New Member

    Oct 13, 2014
    5
    0
    I actually did some digging and found a way to do it too, probably nowhere near as efficient but it works:
    Code (Text):
    1.  
    2. void calc()
    3.     {
    4.     _delay(150000);        // 30ms delay
    5.     lcd_goto(0);        // go to home position
    6.     lcd_charstring("Projectle Velocity = ");
    7.     _delay(2500000);
    8.     lcd_goto(0x40);        // go to second line
    9.     int vol;            // declare velocity as integer
    10.     int temp=0;            // declare temp value to store remainder
    11.     unsigned char hun,ten,one;
    12.     vol=(50000/count);        //calculates velocity as integer
    13.     hun=vol/100;             //takes hundreds digit
    14.     hun=(hun+0X30);            //converts hun to ASCII
    15.     lcd_char(hun);            //prints hun to LCD
    16.     temp=vol%100;            //saves remaining digits in temp
    17.     ten=temp/10;             //takes tens digit
    18.     ten=(ten+0X30);            //converts tens to ASCII
    19.     lcd_char(ten);            //prints tens to LCD
    20.     one=temp%10;             //Puts last digit in one
    21.     one=(one+0X30);            //converts one to ASCII
    22.     lcd_char(one);            //prints ones to LCD
    23.     _delay(150000);            //30ms delay
    24.     lcd_charstring(" ft/s");
    25.     }
    26.  
    27.  
    [/QUOTE]

    Now I am struggling on the timing of the two inputs I am using to get a counter. I am trying to manipulate the main() to use conditional statements of when to count and when to run this calculation. I essentially have one input that I want to start counting with, but that input goes from high to low quickly. But I want to remain counting until the second input goes high, then calculate. I thought i had it working, but I was mistaken. Is there a way to do a conditional for just a quick pulse rather than an if (sensor1 == 1), do....... Because my timer is stopping when the sensor goes low.
     
  5. adam555

    Active Member

    Aug 17, 2013
    858
    39
    I guess you can do it with an interrupt. Furthermore, if you need a more reliable count that's not delayed by the display subroutine you could use a timer as a counter, also with its overflow interrupt.
     
  6. Dan_xd45

    Thread Starter New Member

    Oct 13, 2014
    5
    0
    I believe I had it correct with conditionals a few hours ago. However, finding out that your only problem was the two input wires that are crossed between the two dip switches kinda burns :|
     
  7. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,395
    1,607
    First, learn to use the code tags function. It is hidden in the reply icons under the 4th from the right. It adds <code> and </code> tags (but uses [] and not <>) which preserves your formatting.

    sprintf is a HUGE function, I've caught it adding 2,500 statements to my code just to do something simple (like make a string from an integer). Your library may have a function called itoa inside stdlib.h which converts an integer to a string. If not, Google it as some good short versions of it are out there.
     
  8. adam555

    Active Member

    Aug 17, 2013
    858
    39
    I guess sprintf it's not the best option if you are short for memory; in my case I still have 94% free space left.

    itoa was my first choice, but I decided to go with sprintf so I have better control over the output format and also because itoa did not work with the 32s bit integers I needed.

    Anyway, it was just an example for the OP of one of the simplest ways I chose for solving the problem.
     
    Last edited: Nov 8, 2014
  9. vishal12345

    New Member

    Dec 16, 2014
    8
    1
Loading...