Shop OBEX P1 Docs P2 Docs Learn Events
Need help with simple serial functions — Parallax Forums

Need help with simple serial functions

Hal AlbachHal Albach Posts: 747
edited 2013-11-29 11:37 in Learn with BlocklyProp
Using "Hello LCD.c" in the Example folder as a guide, I am trying to incorporate a LCD display into a clock/calender program I'm developing mainly to better learn C. The problem I have run up against is that that after 288 screen updates the propeller just stops. I'm using a serial LCD and this freezing/stopping occurs consistently. I think it may have to do with the fact that in the function that writes to the LCD I have to open a serial module before I can use dprint to display the information. I have tried to use the close function for the open modules but the compiler will not accept the statement. The error message is that an expression is expected before the word Serial in the parameter portion. x marks the spot the compiler is pointing to... serial_close(xserial *lcd); I have looked up the function in the library and I can't find anything requiring an expression at that point.
/*----------------------------------------------------------------------------------------------
                  convert bcd to binary and print time  */
void show_time()
{
  char sec, min, hour;
  serial *lcd = serial_open(11, 11, 0, 9600);
                                                      // Ex. BCD 53 is binary 83, to convert... 
  sec = ((bytes[0] >> 4) * 10) + (bytes[0] & 0x0F);   // BCD 53 >>4 = 05 * 10 = 50 + 03 = bin 53
  min = ((bytes[1] >> 4) * 10) + (bytes[1] & 0x0F);
  hour = ((bytes[2] >> 4) * 10) + (bytes[2] & 0x0F);


  dprint(lcd, "?x00?y0%%02d:%%02d:%%02d\n", hour, min, sec);        // %%02d prints a 0-padded 2 digit number
  serial_close(serial *lcd);
}


/*----------------------------------------------------------------------------------------------
Here's the compiler messages...
Project Directory: I:/Users/Admin/My Documents/simpleide/My Projects/PCF8583_RTC/


propeller-elf-gcc.exe -v GCC 4.6.1 (propellergcc_v1_0_0_2090)
propeller-elf-gcc.exe -I . -L . -I I:/Users/Admin/My Documents/simpleide/Learn/Simple Libraries/Utility/libsimpletools -L I:/Users/Admin/My Documents/simpleide/Learn/Simple Libraries/Utility/libsimpletools/cmm/ -I I:/Users/Admin/My Documents/simpleide/Learn/Simple Libraries/Text Devices/libsimpletext -L I:/Users/Admin/My Documents/simpleide/Learn/Simple Libraries/Text Devices/libsimpletext/cmm/ -I I:/Users/Admin/My Documents/simpleide/Learn/Simple Libraries/Protocol/libsimplei2c -L I:/Users/Admin/My Documents/simpleide/Learn/Simple Libraries/Protocol/libsimplei2c/cmm/ -o cmm/PCF8583_RTC.elf -Os -mcmm -Wall -m32bit-doubles -fno-exceptions -std=c99 PCF8583_RTC.c -lm -lsimpletools -lsimpletext -lsimplei2c -lm -lsimpletools -lsimpletext -lm -lsimpletools -lm
PCF8583_RTC.c: In function 'show_time':
PCF8583_RTC.c:52:16: error: expected expression before 'serial'
Done. Build Failed!


Click error or warning messages above to debug.
When I try to move the open statement outside of Main I get an error stating that "an initializer is not constant". I am obviously doing something wrong, but am at a loss as to what it is.

In the above function code the dprint line, the editor keeps dropping the percent 02 in front of the d's in the formatting, it accepts 2 of them but the actual code has only one for each.

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2013-11-27 21:14
    Use serial_close(lcd) instead.
  • Hal AlbachHal Albach Posts: 747
    edited 2013-11-28 05:47
    Thank you, Kuroneko! That took care of my problem.
  • edited 2013-11-29 06:19
    Another approach would be to just open the LCD serial connection once during initialization. To do that, just declare the LCD before main and initialize it in main. Then, your show time function will not have to open and close with each call.

    serial *lcd;

    int main()
    {
    lcd = serial_open(...
    ...
    }

    ...

    void show_time()
    {
    char sec, min, hour;
    ...
    dprint(lcd, "?x00?y0%%02d:%%02d:%%02d\n", hour, min, sec); // %%02d prints a 0-padded 2 digit number
    }
  • Hal AlbachHal Albach Posts: 747
    edited 2013-11-29 07:18
    Good Morning, Andy;
    Made the changes per your suggestion, unfortunately the LCD screen now remains blank. Compiles without error but does generate a warning re unused lcd variable. I added a dprint statement in Main and no more warning. Any dprint statement within Main outputs normally to the lcd but nothing from dprint in called functions. Doesn't the open statement lose scope outside of Main?
    PCF8583_RTC.c: In function 'main':
    PCF8583_RTC.c:16:11: warning: unused variable 'lcd' [-Wunused-variable]
    
  • jazzedjazzed Posts: 11,803
    edited 2013-11-29 07:45
    Hi Hal.

    Can you post your new code?
  • Hal AlbachHal Albach Posts: 747
    edited 2013-11-29 09:18
    Here it is, the set clock function needs to be tightened up, once I can sort out the serial thing....
    /*
     *    This is the main PCF8583_RTC program file.
      * As used in this program, locations 0x08 - 0xFF (248 bytes) are free ram.
      * Uses PH Anderson's LCD117 serial to LCD interface.
      * Uses the Direct TV remote in AV1 mode for setting the time and date.
    */
    
    
    #include "PCF8583_RTC.h"
    
    
    serial *lcd;
     //----------------------------------------------------------------------------------------------------------
    
    int main(void)
    {
      serial *lcd = serial_open(11, 11, 0, 9600);
      dprint(lcd,"?f");                                           // to prevent compiler warning
      set_clock();
    
      int flag = 1;
      int secpulse = 1;
    
    
      pause(5);
    
    
      while (1)
      {
        if (secpulse != 1) flag = 1;
    
    
        if (secpulse && flag) // Is this a new interrupt from the 8583?
        {
          clock_read();       // fetch the time
          show_time();        // convert and print the time
    //      show_date();        // convert and print the date
                                // turned off until I sort out dprint
          flag = 0;           // insure only one update per second
        }
        secpulse = input(13);
      }
    }
    
    
    /*----------------------------------------------------------------------------------------------
                      convert bcd to binary and print time  */
    void show_time()
    {
      char sec, min, hour;
                                                          // Ex. BCD 53 is binary 83, to convert... 
      sec = ((bytes[0] >> 4) * 10) + (bytes[0] & 0x0F);   // BCD 53 >>4 = 05 * 10 = 50 + 03 = bin 53
      min = ((bytes[1] >> 4) * 10) + (bytes[1] & 0x0F);
      hour = ((bytes[2] >> 4) * 10) + (bytes[2] & 0x0F);
    
    
      dprint(lcd, "?x00?y0%02d:%02d:%02d\n", hour, min, sec);        // %02d prints a 0-padded 2 digit number
    }
    
    
    /*----------------------------------------------------------------------------------------------
                      convert bcd to binary and print the date  */
    void show_date()
    {
      char mon, day;
    
      mon = (((bytes[4] & 0x10) >> 4) * 10) + (bytes[4] & 0x0F);
      day = (((bytes[3] & 0x30) >> 4) * 10) + (bytes[3] & 0x0F);
      dprint(lcd, "?n");
      dprint(lcd, "?x00?y1%02d/%02d/13\n", mon, day);
    }
    
    
    /*----------------------------------------------------------------------------------------------
                      set the clock    (seconds,minutes, hours, year/date, weekday/month) */
    void set_clock()
    {
    
    
      int c = 0;                        // console input buffer
    
    
      dprint(lcd, "?fDOW 1=Mon  ");
      c = sirc_button(ir_pin);          // 1 digit weekday
      dprint(lcd, "%d", c);
      bytes[4] =(c << 5);
      dprint(lcd, "?nDay 01-31  ");
      c = sirc_button(ir_pin);          //tens digit of Day
      dprint(lcd, "%d", c);
      bytes[3] = (c << 4);
      c = sirc_button(ir_pin);          //units digit of Day
      dprint(lcd, "%d", c);
      bytes[3] |= ( c & 0x0F);
      dprint(lcd, "?nMonth 01-12  ");
      c = sirc_button(ir_pin);          //tens digit of Month
      dprint(lcd, "%d", c);
      if (c == 1) bytes[4] = 0x10;
      c = sirc_button(ir_pin);          //units digit of Month
      dprint(lcd, "%d", c);
      bytes[4] |= ( c & 0x0F);
      dprint(lcd, "?nHour 00-24  ");
      c = sirc_button(ir_pin);          //tens digit of hour
      dprint(lcd, "%d", c);
      bytes[2] = (c << 4);
      c = sirc_button(ir_pin);          //units digit of hour
      dprint(lcd, "%d", c);
      bytes[2] |= ( c & 0x0F);
      dprint(lcd, "?fMin 00-59  ");
      c = sirc_button(ir_pin);          //tens digit of Min
      dprint(lcd, "%d", c);
      bytes[1] = (c << 4);
      c = sirc_button(ir_pin);          //units digit of Min
      dprint(lcd, "%d", c);
      bytes[1] |= ( c & 0x0F);
      dprint(lcd, "?nSec 00-59  ");
      c = sirc_button(ir_pin);          //tens digit of secs
      dprint(lcd, "%d", c);
      bytes[0] = (c << 4);
      c = sirc_button(ir_pin);          //units digit of secs
      dprint(lcd, "%d", c);
      bytes[0] |= ( c & 0x0F);
      dprint(lcd, "?f");
    
    
      ptr_bytes = bytes;                      // associate pointer to bytes array
      i2c_open(&rtcbus, SCL, SDA, 0);         // open the RTCbus device (bus pointer, SCL pin, SDA pin, SCL-drive 0=no drive)
    
    
      i2c_start(&rtcbus);                     // set the start condition for addressing
      i2c_writeByte(&rtcbus, rtc_write);      // send the RTC device ID as a write
      i2c_writeByte(&rtcbus, 2);              // send the address byte (device limited to one page)
    
    
      i2c_writeData(&rtcbus, ptr_bytes, 5);   // write 5 bytes to device
    
    
      i2c_stop(&rtcbus);                      // stop the bus transaction
    }
    
    
    /*----------------------------------------------------------------------------------------------------------
                      Start I2C bus, read 5 bytes, & stop bus   */
    void clock_read(void)
    {
      ptr_bytes = bytes;                    // associate pointer to bytes array
      i2c_open(&rtcbus, SCL, SDA, 0);       // open the device (bus pointer, SCL pin, SDA pin, SCL-drive 0=no drive)
    
    
      i2c_start(&rtcbus);                   // set the start condition for addressing
      i2c_writeByte(&rtcbus, rtc_write);    // send the RTC device ID as a write
      i2c_writeByte(&rtcbus, 2);            // send the address byte (device limited to one page)
    
    
      i2c_start(&rtcbus);                   // send the start sequence again for a read
      i2c_writeByte(&rtcbus, rtc_read);     // send the ID as a read
    
    
      i2c_readData(&rtcbus, ptr_bytes, 5);  // read 5 bytes from device
    
    
      i2c_stop(&rtcbus);                    // stop the bus transaction
    }
    
    
    //----------------------------------------------------------------------------------------------
    
    
    //   Sony remote control protocol
    
    
    
    
    int sirc_button(int pin)
    {
      int button = -1;
    
    
      while(button == -1)
      {
        button = sirc_code(pin, 7);
    
    
        //Correct for numeric keys
        if((button <= 9) && (button >=0)) button++;
        if(button == 10) button = 0;
      }
      pause(100);
      return button;
    }
      
    int sirc_code(int pin, int bits)
    {
      unsigned int irPulse;                
      int irCode = 0;
      do
      {
        irPulse = pulse_in(pin, 0);     // determine width of LOW level pulse
      }
      while((irPulse <= 2000) || (irPulse >= 2800));
      
      for(int i = 0; i < bits; i++)
      {
        irPulse = pulse_in(pin, 0);
        if((irPulse > 1100) && (irPulse < 1300)) irCode |= (1 << i);
        if((irPulse < 500) || (irPulse > 1300)) return -1;
      }
      return irCode;
    }
      
    //----------------------------------------------------------------------------------------------
    

    and the .h file
    /*
    * PCF8583_RTC.h
    */
    
    
    #include "simpletools.h"
    
    
    // PCF8583 Interrupt output to pin 13
    
    
    #define SCL 14
    #define SDA 15
    #define rtc_write 0xA0
    #define rtc_read 0xA1
    #define ir_pin 12
    
    
    const int ON = 22;
    const int CLR = 12;
    
    
    unsigned char bytes[5]; // byte storage (seconds,minutes, hours, year/date, weekday/month)
    unsigned char *ptr_bytes; // pointer for bytes array
    i2c rtcbus; // declare an i2c device variable
    
    
    // prototypes
    void clock_read(void);
    void show_time();
    void show_date();
    void set_clock();
    int sirc_button(int pin);
    int sirc_code(int pin, int bits);
    


    [/code]
  • jazzedjazzed Posts: 11,803
    edited 2013-11-29 11:03
    Don't re-declare serial *lcd inside of main, just use lcd which you've declared globally.
    By re-declaring lcd inside of main and opening to that, your other functions won't have access.

    Anything you declare inside of a function becomes local to the function ... like in spin.
    Anything you declare outside of a function will be global.
    serial *lcd;
    void main(void) {
      lcd = serial_open(-1, 11, 0 9600); // -1 says don't use rx ... you can't use the same pin number in both places.
    }
    
  • Hal AlbachHal Albach Posts: 747
    edited 2013-11-29 11:37
    Thank you, Jazzed! The serial function now works with a single open statement. (had a comma missing after the 0 in the param list, easily found and replaced). Now I can start tightening up that clock set function...
Sign In or Register to comment.