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

Problem with DS3231 and PIC16F1847
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jake1272



Joined: 15 Mar 2021
Posts: 37

View user's profile Send private message

Problem with DS3231 and PIC16F1847
PostPosted: Sun Apr 11, 2021 5:15 am     Reply with quote

Hi everyone,
I am building a real-time clock/calendar with 2 alarm functions using the PIC16F1847 microcontroller and DS3231 RTC chip. Time, date, and alarms are displayed on a 20×4 LCD screen. But so far I cannot display anything on the LCD. Any suggestions?
The compiler is CCS v5.065
The IDE is MPLAB X IDE v5.40
Here is the driver and my code:

Code:
 // LCD module connections
#define LCD_RS_PIN      PIN_A2
#define LCD_RW_PIN      PIN_A3
#define LCD_ENABLE_PIN  PIN_A4
#define LCD_DATA4       PIN_A7
#define LCD_DATA5       PIN_A6
#define LCD_DATA6       PIN_B5
#define LCD_DATA7       PIN_B4
// end LCD module connections
 
// pin definitions
#define button1      PIN_B1
#define button2      PIN_B2
#define button3      PIN_B3
#define LED_PIN      PIN_B6
 
#include <16F1847.h>
#fuses  INTRC_IO ,NOMCLR,NOLVP,NOBROWNOUT,PUT,NOWDT
#use delay(internal = 8MHz)
#use I2C(MASTER, I2C1, SLOW = 100000, STREAM = DS3231_STREAM)
#use fast_io(b)
#use fast_io(a)
#include <lcd.c>     // include LCD driver source file
#include <DS3231.c>  // include DS3231 driver source file
 
int8 i;
// DS3231 library variable declaration
RTC_Time *mytime, *alarm1, *alarm2;
 
// external interrupt routine
#INT_EXT
void ext_isr(void)
{
  output_high(LED_PIN);
  clear_interrupt(INT_EXT);
}
 
// function for displaying day of the week
void dow_print()
{
  lcd_gotoxy(1, 2);
  switch(mytime->dow)
  {
    case SUNDAY   :  printf(lcd_putc, "Sun");  break;
    case MONDAY   :  printf(lcd_putc, "Mon");  break;
    case TUESDAY  :  printf(lcd_putc, "Tue");  break;
    case WEDNESDAY:  printf(lcd_putc, "Wed");  break;
    case THURSDAY :  printf(lcd_putc, "Thu");  break;
    case FRIDAY   :  printf(lcd_putc, "Fri");  break;
    default       :  printf(lcd_putc, "Sat");
  }
}
 
// a small function for buttons debounce
int1 debounce(int16 button)
{
  int8 count = 0;
  for(int8 i = 0; i < 5; i++)
  {
    if ( !input(button) )
      count++;
    delay_ms(10);
  }
 
  if(count > 2)  return 1;
  else           return 0;
}
 
void wait()
{
  set_timer0(0);
  while( (get_timer0() < 62500L) && (input(button1) || i >= 5) && input(button2) && (input(button3) || i < 5) ) ;
}
 
int8 edit(int8 x_pos, int8 y_pos, int8 parameter)
{
  if(i < 5)
    while( debounce(button1) );  // call debounce function (wait for B1 to be released)
  else
    while( debounce(button3) );  // call debounce function (wait for B3 to be released)
 
  lcd_gotoxy(x_pos, y_pos);  // move cursor to row y_pos, column x_pos
  while(TRUE)
  {
    while(!input(button2))
    {
      parameter++;
      if( (i == 0 || i == 5) && parameter > 23)   // if hours > 23 ==> hours = 0
        parameter = 0;
      if( (i == 1 || i == 6) && parameter > 59)   // if minutes > 59 ==> minutes = 0
        parameter = 0;
      if(i == 2 && parameter > 31)   // if day > 31 ==> day = 1
        parameter = 1;
      if(i == 3 && parameter > 12)   // if month > 12 ==> month = 1
        parameter = 1;
      if(i == 4 && parameter > 99)   // if year > 99 ==> year = 0
        parameter = 0;
 
      printf(lcd_putc, "%02u\b\b", parameter);
      delay_ms(200);
    }
 
    lcd_putc("  \b\b");
    wait();
    printf(lcd_putc, "%02u\b\b", parameter);
    wait();
 
    if( (!input(button1) && i < 5) || (!input(button3) && i >= 5) )
    {
      i++;                // increment 'i' for the next parameter
      return parameter;   // return parameter value and exit
    }
  }
}
 
void alarms_edit(int8 _alarm)
{
  int1 alarm_c;
  if(_alarm == 1) {
    lcd_gotoxy(38, 1);
    alarm_c = Alarm1_Status();
  }
  else {
    lcd_gotoxy(38, 2);
    alarm_c = Alarm2_Status();
  }
 
  while( debounce(button3) );  // call debounce function (wait for B3 to be released)
  while(TRUE)
  {
    while( !input(button2) )
    {
      alarm_c = !alarm_c;
      if(alarm_c)
        lcd_putc("ON \b\b\b");
      else
        lcd_putc("OFF\b\b\b");
      delay_ms(500);
    }
 
    lcd_putc("   \b\b\b");
    wait();
    if(alarm_c)  lcd_putc("ON \b\b\b");
    else         lcd_putc("OFF\b\b\b");
    wait();
 
    if( !input(button3) )
    {
      if(_alarm == 1)
      {
        if(alarm_c)  Alarm1_Enable();   // enable alarm1
        else         Alarm1_Disable();  // disable alarm1
      }
      else
      {
        if(alarm_c)  Alarm2_Enable();   // enable alarm2
        else         Alarm2_Disable();  // disable alarm2
      }
      return;
    }
  }
}
 
// main function
void main()
{
  setup_oscillator(OSC_8MHZ);  // set internal oscillator to 8MHz
  set_tris_b(0x0F);            // configure RB0~4 ins as inputs
  port_b_pullups(0x0E);        // enable RB1, RB2 & RB3 internal pull-ups
  enable_interrupts(GLOBAL);       // enable global interrupts
  enable_interrupts(INT_EXT_H2L);  // enable external interrupt (INT0) with edge from high to low
 
  delay_ms(1000);  // wait a second
  lcd_init();      // initialize LCD module
  IntSqw_Set(OUT_INT);  // DS3231 INT/SQW pin configuration (interrupt when alarm)
  Disable_32kHZ();      // disable DS3231 32kHz output
 
  while(TRUE)
  {
    // read current time and date
    mytime = RTC_Get();
    // print time
    lcd_gotoxy(1, 1);
    printf(lcd_putc, "%02u:%02u:%02u", mytime->hours, mytime->minutes, mytime->seconds);
    // print date
    dow_print();       // print week day
    lcd_gotoxy(5, 2);
    printf(lcd_putc, "%02u/%02u/20%02u", mytime->day, mytime->month, mytime->year);
 
    // read alarm1
    alarm1 = Alarm1_Get();
    // print alarm1
    lcd_gotoxy(21, 1);
    printf(lcd_putc, "A1: %02u:%02u:00", alarm1->hours, alarm1->minutes);
    lcd_gotoxy(38, 1);
    if( Alarm1_Status() )
      lcd_putc("ON ");
    else
      lcd_putc("OFF");
 
    // read alarm2
    alarm2 = Alarm2_Get();
    // print alarm2
    lcd_gotoxy(21, 2);
    printf(lcd_putc, "A2: %02u:%02u:00", alarm2->hours, alarm2->minutes);
    lcd_gotoxy(38, 2);
    if( Alarm2_Status() )
      lcd_putc("ON ");
    else
      lcd_putc("OFF");
 
    // read chip temperature
    signed int16 chip_temp = Get_Temperature();
    // print chip temperature
    lcd_gotoxy(11, 1);
    if (chip_temp < 0)  // if temperature is negative
        printf(lcd_putc, "T:-%02Lu.%02Lu%cC", abs(chip_temp) / 100, abs(chip_temp) % 100, 223);
    else
    printf(lcd_putc, "T: %02Lu.%02Lu%cC", chip_temp / 100, chip_temp % 100, 223);
 
    // if button B1 is pressed
    if( !input(button1) )
    if( debounce(button1) )        // call debounce function (make sure if B1 is pressed)
    {
      i = 0;
      setup_timer_0(T0_INTERNAL | T0_DIV_16);  // start Timer0 with internal clock & prescaler=16
 
      mytime->hours   = edit(1,  1, mytime->hours);    // edit hours
      mytime->minutes = edit(4,  1, mytime->minutes);  // edit minutes
      mytime->seconds = 0;                             // reset seconds
      while( debounce(button1) );  // call debounce function (wait for button B1 to be released)
 
      while(TRUE)
      {
        while( !input(button2) )  // if button B2 button is pressed
        {
          mytime->dow++;
          if(mytime->dow > 7) mytime->dow = 1;
          dow_print();     // print week day
          delay_ms(500);
        }
        lcd_gotoxy(1, 2);
        lcd_putc("   ");  // print 3 spaces
        wait();           // call wait() function
        dow_print();      // print week day
        wait();           // call wait() function
        if( !input(button1) )  // if button B1 is pressed
          break;
      }
 
      mytime->day     = edit(5,  2, mytime->day);    // edit day
      mytime->month   = edit(8,  2, mytime->month);  // edit month
      mytime->year    = edit(13, 2, mytime->year);   // edit year
 
      while( debounce(button1) );  // call debounce function (wait for button B1 to be released)
           // disable Timer0
     
      // write data to the RTC chip
      RTC_Set(mytime);
    }
 
    // if button B3 is pressed
    if( !input(button3) )
    if( debounce(button3) )  // call debounce function (make sure if B3 is pressed)
    {
      i = 5;
      setup_timer_0(T0_INTERNAL | T0_DIV_16);  // start Timer0 with internal clock & prescaler=16
 
      alarm1->hours   = edit(25,  1, alarm1->hours);    // edit alarm1 hours
      alarm1->minutes = edit(28,  1, alarm1->minutes);  // edit alarm1 minutes
      alarm1->seconds = 0;                              // reset alarm1 seconds
      Alarm1_Set(alarm1, HOURS_MINUTES_SECONDS_MATCH);  // alarm when hours, minutes and seconds match
      Alarm1_IF_Reset();  // reset alarm1 interrupt flag
      alarms_edit(1);     // edit alarm1 ON & OFF
 
      i = 5;
      alarm2->hours   = edit(25,  2, alarm2->hours);    // edit alarm2 hours
      alarm2->minutes = edit(28,  2, alarm2->minutes);  // edit alarm2 minutes
      Alarm2_Set(alarm2, HOURS_MINUTES_MATCH);          // alarm when hours and minutes match
      Alarm2_IF_Reset();  // reset alarm2 interrupt flag
      alarms_edit(2);     // edit alarm2 ON & OFF
 
      while( debounce(button3) );  // call debounce function (wait for button B3 to be released)
   
    }
 
    if( input(LED_PIN) && !input(button2) )
    {
      output_low(LED_PIN);
      if( Alarm1_IF_Check() )
      {
        Alarm1_IF_Reset();  // reset alarm1 interrupt flag
        Alarm1_Disable();   // disable alarm1
      }
      if( Alarm2_IF_Check() )
      {
        Alarm2_IF_Reset();  // reset alarm2 interrupt flag
        Alarm2_Disable();   // disable alarm2
      }
    }
 
    delay_ms(100);
  }
}
 
// end of code.


Last edited by jake1272 on Sun Apr 11, 2021 5:53 am; edited 2 times in total
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 5:28 am     Reply with quote

You need to remove the CCS DS3231 driver code from your posting.
Posting driver code is against CCS rules and copyright.
_________________
Google and Forum Search are some of your best tools!!!!
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 5:44 am     Reply with quote

re: But so far I cannot display anything on the LCD

'anything' ? hmm...
Can you simply display 'Hello World' on the LCD ?

You need to break down the program into parts.
1st, can you get the PIC to run a 1Hz blinking LED program ?
if no, stay here until it works....

2nd confirm you can display 'hello world' on the display. This will confirm the LCD code is good, I/O pins, etc.
if no, stay here until it works...

3rd NOW try the DS3231 portion of the program...
jake1272



Joined: 15 Mar 2021
Posts: 37

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 5:55 am     Reply with quote

dyeatman wrote:
You need to remove the CCS DS3231 driver code from your posting.
Posting driver code is against CCS rules and copyright.

I am really sorry I have not fully read the terms and conditions. My bad
jake1272



Joined: 15 Mar 2021
Posts: 37

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 5:58 am     Reply with quote

temtronic wrote:
re: But so far I cannot display anything on the LCD

'anything' ? hmm...
Can you simply display 'Hello World' on the LCD ?

You need to break down the program into parts.
1st, can you get the PIC to run a 1Hz blinking LED program ?
if no, stay here until it works....

2nd confirm you can display 'hello world' on the display. This will confirm the LCD code is good, I/O pins, etc.
if no, stay here until it works...

3rd NOW try the DS3231 portion of the program...


I am just trying to say the time and date cannot be displayed on the lcd Smile
Yes I can print on the LCD with this test code
Code:
 // LCD module connections
#define LCD_RS_PIN      PIN_A2
#define LCD_RW_PIN      PIN_A3
#define LCD_ENABLE_PIN  PIN_A4
#define LCD_DATA4       PIN_A7
#define LCD_DATA5       PIN_A6
#define LCD_DATA6       PIN_B5
#define LCD_DATA7       PIN_B4
// end LCD module connections
 

 
#include <16F1847.h>
#fuses NOMCLR NOBROWNOUT NOLVP INTRC_IO
#use delay(clock = 4MHz)
#include <lcd.c>
 
unsigned int8 i;
void lcd_shift_left(){
  lcd_send_byte(0,0x18);                         // Shift left command
}
void lcd_shift_right(){
  lcd_send_byte(0,0x1E);                         // Shift right command
}
void main(){
  setup_oscillator(OSC_4MHZ);                    // Set the internal oscillator to 4MHz
  lcd_init();                                    // Initialize LCD module
  lcd_putc('\f');                                // Clear LCD
  lcd_gotoxy(2, 1);                              // Go to column 2 row 1
  lcd_putc("PIC16F1847");                         // Display "PIC16F1847"
  delay_ms(1000);                                // Wait 1 second
  lcd_gotoxy(1, 2);                              // Go to column 1 row 2
  lcd_putc("LCD example");
  delay_ms(1000);
  lcd_gotoxy(21, 1);                             // Go to column 1 row 3
  lcd_putc("Hello world!");
  delay_ms(1000);
  for(i = 0; i < 8; i++){
    lcd_shift_right();                           // Shift right
    delay_ms(100);}
  for(i = 0; i < 4; i++){
    lcd_shift_left();                            // Shift left
    delay_ms(100);}
  for(i = 0; i < 200; i++){
    lcd_gotoxy(25, 2);                           // Go to column 5 row 4
    printf(lcd_putc,"%3u",i);                    // Write i with 3 numbers max
    delay_ms(200);
  }
  while(TRUE);                                   // Endless loop
}
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 6:20 am     Reply with quote

great... least PICs running and LCD is OK...
next step....

goto the code library, and downlode PCMPs 'I2C SCANNER' program, compile and burn and run.....
It should find the DS3231 chip. If not, recheck wiring and be sure I2C pullups are there. If the DS3231 is a module, they _may_ be on the PCB.....

stay in this loop until scanner finds the DS3231.

Jay
jake1272



Joined: 15 Mar 2021
Posts: 37

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 7:13 am     Reply with quote

Thank You, Jay. I have run the "I2C SCANNER" program and I got this print out in the terminal:
ACK addr: AE
ACK addr: D0

Number of i2c chips found: 2
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 7:54 am     Reply with quote

D0 is the DS3231 RTC chip.
no idea what the AE address is for.

I cut my own RTC code as I have an ancient compiler....

Jay
jake1272



Joined: 15 Mar 2021
Posts: 37

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 8:01 am     Reply with quote

I still have my pickit3 connected do you think that might be a problem? Which part of the code were you using when you are saying "you cut your own RTC code" ?
Thanks again
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 8:13 am     Reply with quote

I made my own DS3231 'driver'.
Having PK3 on shouldn't matter, I do that all the time..no pun intended.

Jay
jake1272



Joined: 15 Mar 2021
Posts: 37

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 9:43 am     Reply with quote

Thanks, Jay, I will keep trying in the meantime what library will you recommend to fulfill my goal. This what I am trying to do "In the circuit, there will be 3 push buttons for setting time, date, and alarms, and one LED for indicating the alarms when occurred".
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 10:22 am     Reply with quote

Big key difference between the working test and the problem code is
selecting fast_io. Don't. 99% of CCS code does not use fast_io....
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 10:36 am     Reply with quote

As Mr. T points out, get rid of the fast_io().....let the compiler automatically handle the I/O as required !
In 2 1/2 decades of 'playing with PICs' and CCS C, I've only needed fast_io() 2 or 3 times. In each case, i needed to have very specific timing for proprietory interfaces.

One problem with using fast_io() is that if you change a pin YOU must re-code tris settings and what WILL happen, is you'll forget to do that, then 'it doesn't work' problems show up.
In your case, LCD module and RTC are 'slow' devices.
While I don't have the CCS DS3231 driver, I'm fairly confident that it does work.
jake1272



Joined: 15 Mar 2021
Posts: 37

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 10:39 am     Reply with quote

Ttelmah wrote:
Big key difference between the working test and the problem code is
selecting fast_io. Don't. 99% of CCS code does not use fast_io...


Thanks for the suggestion I have removed that, still it doesn't solve the problem
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 11, 2021 11:42 am     Reply with quote

did you also delete all set_tris...() statements ?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
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