RTC MONTH NAME DISPLAY

Go To Last Post
57 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello My name is Anshumaan and I am new to avr microcontroller. i want to create a rtc timer and for that i want to display months names instead of numbers indicating months .Please check the code and give me some advice how can i do this.

Attachment(s): 

This topic has a solution.

anshumaan kumar

Last Edited: Thu. Oct 31, 2019 - 05:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
sprintf(buffer, "%02x/%02X %5s ", date, day, months[month]);

 

try to avoid using globals to pass data. Create a structure for your time/date.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Create a structure for your time/date.

 

struct display {
    int    second;
    int    minute;
    int    hour;
    int    day;
    int    date;
    int    month;
    int    year;
    struct display;    // Anonymous structure; no name needed
} rtc_data_access;

 

Look man i have created this how can i display the variables inside.?

 

I have tried this:

 

sprintf(buffer, "%02x/%02X %5s ", rtc_data_access);

 

But unfortunately this displays only the time (accurate value of time) but shows 00/00 in place of date and month .I have no clue why it shows like this.

Sorry i forgot i dont need to display the year so plese take that out of consideration.

Attachment(s): 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to brush up on the basics of the C language.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ya. Indeed no doubt but please can you also define which topics i should see into to solve this problem? 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you fix your original problem? Or have you included my suggestion of using a struct into the mix? Solve one problem at a time.

 

 Surely if I can Google 'wigner energy' , you can Google 'C structs'?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From Post#1 attached file:

char* months[12]= {"JAN","FEB","MAR","APR","MAY","JUNE","JULY", "AUG", "SEP", "OCT", "NOV", "DEC"};

...

sprintf(buffer, "%02x/ %5s ", date, day, months);

1) months is an array of strings but you haven't provided an index.

2) you have 2 numbers (date and day), but you only have 1 "%02x".

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for such a late reply. I was a little busy i have studied c structs but i am still confused how to use them here actually i am confused on how to access the variables inside the struct. I have made the following changes in the code although this doesnt have any struct still unfortunately. I have written what I could. Everthing works except for the thing I require - "The Months names". Please see and tell what i could change here. Thanks for replying.

 

[to save others having to open the attachment, here's the current code - Cliff]:

#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "I2C_Master_H_file.h"
#include "LCD16x2_4Bit.h"

#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */


int second,minute,hour,day,date,month,year;



void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	second = I2C_Read_Ack();						/* Read second */
	minute = I2C_Read_Ack();						/* Read minute */
	hour = I2C_Read_Nack();							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(Device_Write_address);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(Device_Read_address);

	day = I2C_Read_Ack();							/* Read day */ 
	date = I2C_Read_Ack();							/* Read date */
	month = I2C_Read_Ack();							/* Read month */
	year = I2C_Read_Nack();							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

int main(void)
{
	char buffer[20];
	char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
        char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};

	I2C_Init();										/* Initialize I2C */
	lcdinit();										/* Initialize LCD16x2 */

    while(1)
    {
		RTC_Read_Clock(0);							/* Read the clock with second address i.e location is 0 */
		
			sprintf(buffer, "%02x:%02x:%02x  ", (hour & 0b00011111), minute, second);
			lcd_print_xy(0,0,buffer);

		RTC_Read_Calendar(3);						/* Read the calender with day address i.e location is 3 */
	    sprintf(buffer, "%02x/ %5s /%02x %3s ", date, months[month-1], year,days[day-1]);
		lcd_print_xy(1,0,buffer);
    }
}

 

Attachment(s): 

anshumaan kumar

Last Edited: Wed. Oct 16, 2019 - 03:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code "looks" as if it should work.

 

Obviously you should test the sprintf() with numbers first.

Remember that DS1307 registers are in BCD.   So October is going to be 0x10.   You only have 10 month names.

Either put some dummy pointers in the array e.g. from 0xA to 0xF or convert BCD to regular number.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:
i am confused on how to access the variables inside the struct

That is a standard 'C' thing - nothing specific to AVR.

 

I would suggest that you practice that part on a "normal" computer - such as a PC - before you get into the added complications of the small embedded microcontroller!

 

See: https://www.avrfreaks.net/commen...

 

And: https://www.avrfreaks.net/commen...

 

And: https://www.avrfreaks.net/commen...

 

But, when you do get to the AVR, one of the key difference is that memory - and RAM in particular - are very limited.

 

Therefore you need to think carefully about your variable types & sizes:

struct display {
    int    second;
    int    minute;
    int    hour;
    int    day;        // day of week  ?
    int    date;       // day of month ?
    int    month;
    int    year;       // full year, or just 0-99 ?

    struct display;    // Anonymous structure; no name needed
} rtc_data_access;

In AVR GCC, an 'int' is two bytes:  https://gcc.gnu.org/wiki/avr-gcc#Type_Layout

 

Every one of those values (except, perhaps, the year) will fit into a single byte.

 

Also, an 'int' is signed - which makes no sense for any of those values.

 

So it would make more sense to have:

struct display {
    uint8_t     second;
    uint8_t     minute;
    uint8_t     hour;
    uint8_t     day_of_week;
    uint8_t     day_of_month;
    uint8_t     month;
    uint16_t    year;       // full year; eg, 2019

    struct display;    // Anonymous structure; no name needed
} rtc_data_access;

 

For instructions on how to get the code to appear properly formatted like that, see Tip #1.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Oct 16, 2019 - 04:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well if you want to know how to use structs it's simply that this collection of variables (which at present are all separate):

int second,minute,hour,day,date,month,year;

could be grouped together into a single variable:

struct {
    int second;
    int minute;
    int hour;
    int day;
    int date;
    int month
    int year;
} date_time;

Now when setting these things you just use the name of the struct (the "group") first followed by the element within. So code like:

	second = I2C_Read_Ack();						/* Read second */
	minute = I2C_Read_Ack();						/* Read minute */
	hour = I2C_Read_Nack();							/* Read hour with Nack */

might now become:

	date_time.second = I2C_Read_Ack();						/* Read second */
	date_time.minute = I2C_Read_Ack();						/* Read minute */
	date_time.hour = I2C_Read_Nack();						/* Read hour with Nack */

but where this really comes into it's own is that you could actually do something like:

#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "I2C_Master_H_file.h"
#include "LCD16x2_4Bit.h"

#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */


typedef struct {
    int second;
    int minute;
    int hour;
    int day;
    int date;
    int month;
    int year;
} date_time_t;


void RTC_Read_Clock(date_time_t & dt)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(0);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	dt->second = I2C_Read_Ack();						/* Read second */
	dt->minute = I2C_Read_Ack();						/* Read minute */
	dt->hour = I2C_Read_Nack();							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(date_time_t & dt)
{
	I2C_Start(Device_Write_address);
	I2C_Write(3);
	I2C_Repeated_Start(Device_Read_address);

	dt->day = I2C_Read_Ack();							/* Read day */ 
	dt->date = I2C_Read_Ack();							/* Read date */
	dt->month = I2C_Read_Ack();							/* Read month */
	dt->year = I2C_Read_Nack();							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

date_time_t RTC_Read_Date_Time() {
    date_time_t retval;
    RTC_Read_Clock(&retval);
    RTC_Read_Calendar(&retval);
    return retval;
}

int main(void)
{
	char buffer[20];
	char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
        char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
    date_time_t now;

	I2C_Init();										/* Initialize I2C */
	lcdinit();										/* Initialize LCD16x2 */

    while(1)
    {
	now = RTC_Read_Date_Time();
		
	sprintf(buffer, "%02x:%02x:%02x  ", (now.hour & 0b00011111), now.minute, now.second);
	lcd_print_xy(0,0,buffer);

	sprintf(buffer, "%02x/ %5s /%02x %3s ", now.date, months[now.month-1], now.year, days[now.day-1]);
	lcd_print_xy(1,0,buffer);
    }
}

The point being that you can pass the whole group of things about as one block. For example, when I call your RTC_Read_Clock() and RTC_Read_Calendar() functions I now pass the address of a variable group (struct) to each function in turn and within those functions it sets some fields. they use the -> operator because what is being passed is simply a pointer to an already created struct (that is "date_time_t retval;" within RTC_Read_Date_Time()). The RTC_read_Date_time() function itself, like all C functions can only have one variable that it returns but in this case it is the whole struct that has been created and filled in.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you guys due to you now i can really use structs in my programming. One more thing "david.prentice", I know how to print numbers as well as characters with sprintf but i dont know how to convert BCD to char using sprintf. After so much searching i still cant find it ? Can you please pass me some examples that i can use ???Thank you.

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sprintf won't convert BCD to char - this might explain your dilemma.

 

The issue is you read two bcd values - you want to combine these to form an integer value. 

 

uint8_t bcd_value = 0x23;   //23 decimal as two bcd numbers

 

 

uint8_t val = (bcd_value & 0xf0) >> 4;  //get the '2'

 

val *= 10; //

 

val += bcd_value & 0x0f;

 

//val now equals 23 decimal.

 

sprintf(buff,"Day: %02d",val);  //bingo!

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
sprintf won't convert BCD to char

Indeed.

 

Again, this is standard 'C' - nothing specific to AVR.

 

http://www.cplusplus.com/reference/cstdio/sprintf/

 

An alternative could be:

uint8_t bcd_value = 0x23;   //23 decimal as two BCD digits

decimal.sprintf( buff, "Day: %01d%01d", bcd_val >> 4, bcd_val & 0x0F );  //bingo!

 

EDIT

 

Or, as 0x23 represents "23", you could simple do:

sprintf( buff, "Day: %02x", bcd_val );  // bingo!

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Sat. Oct 19, 2019 - 01:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Go on.   The problem is bcd2bin() function to access the correct index for the months[ ] array.

Displaying BCD registers as human values is easy.  Just use %02X

 

You can write your own bcd2bin() function.

 

Or bear in mind that the range of valid month is 0x01-0x09, 0x10-0x12.

        char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", //0x01-0x09
                            "", "", "", "", "", "", "OCT", "NOV", "DEC"     //0x0A-0x0F, 0x10, 0x11, 0x12
                           };

Then you could use the raw BCD month value to index the array.

 

bcd2bin() is a more straightforward solution.

 

David.

Last Edited: Sat. Oct 19, 2019 - 01:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Displaying BCD registers as human values is easy.  Just use %02X

Embarrassed that it took me so long to realise that!

 

blush

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman example works I am now able to display BCD to the lcd I have made the following changes to display only 12 values instead of 23 decimal values because i need only 12 to display the months names now but i have no idea how this will help me to display the name of the month i have tried to assign each value a name but that's i think is not the way to go please help me how i can assign the BCDs to their respective months names so that i can show the months names instead of showing the numbers..

 

uint8_t bcd_value = 0x12;  

uint8_t val = (bcd_value & 0x78) >> 4;  //get the '2'

 

val *= 10; //

 

val += bcd_value & 0x78;

 

sprintf(buff,"Day: %02d",val); 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Go on.  Sit down with pencil and paper.

 

Trace your statements by hand.

 

I could write the function for you.   But Kartman has already done it.

 

Hand-trace Kartman's statements.    Do they work?   Can you find an error?

 

David.

Last Edited: Sat. Oct 19, 2019 - 09:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Aye aye aye!

bcd_value is the input value! Where did you get the 0x78 from?

Do you realise there a zillions of examples on how to do this on the internet? You’re not the first person to use a rtc chip that has bcd.

Last Edited: Sat. Oct 19, 2019 - 10:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is simple to write the function yourself.

 

Trace some example values on paper.    Test typical values,  edge values,  illegal values.   Job done.

 

If you try and do it all in your head,  it only makes your head hurt.

Seriously,    invest in a pencil.    It is so much easier to see something on paper.

 

Although bcd2bin() is fairly trivial,  it is a good exercise.    You will gain confidence for writing other functions.

 

David.    

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay i get it i have understood a little off the track i get it Kartman has written a program on how to print two bcd values on the lcd by combining them and then printing them that worked but now i have problems on how to assign the input an array i.e. i want "bcd_value" to have an array of the months bcd values so that i can print its name instead of the number..Did you guys get what i am asking and please i am not asking for the code David i can do the work just need some guidance. Sorry no offence.smiley

Thank you guys for answering.

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you add/subtract/multiply/divide? This is what we’re doing here. The 10’s digit is multiplied by 16 (hexadecimal), so to get it back to decimal, we divide by 16, then multiply it by 10. Then add the units digit.

So create a function that takes bcd_value and returns val. This is bcd2bin that David talks about.

 

The problem is so common, that if I Google 'bcd2bin' what do I find?

Last Edited: Sun. Oct 20, 2019 - 05:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok. so are you talking about this :

 

int convert (uint8_t  bcd_value)

{

uint8_t val = 0;

val = (bcd_value & 0xf0);

val *= 10;

val += bcd_value & 0x0f;

return val;

}

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

Go on. Write the code on paper.
Then step through the code with some typical BCD values like 0x12, 0x45, ...
And then try edge values like 0x00, 0x99
Then try illegal values like 0x0A or 0xFF
.
Seriously, you will never get anywhere until you learn how to trace code.
It is just the same process that you learned in Maths class at school.
.
Now compare your function with the method suggested by Kartman in #13.
Do the same exercise i.e. trace some values.
There is no need to trace all 256 possible uint8_t values. Just some sensible example values.
You do the same technique to test an int32_t or float function. You can never test every value. Just test typical, edge, bad data.
.
David.

Last Edited: Sun. Oct 20, 2019 - 07:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You have already been pointed to the instructions on how to get the code to appear properly formatted - see Tip #1.

 

david.prentice wrote:
Write the code on paper. Then step through the code

 

As David says, this is a key skill.

 

I find it helps to use squared paper, and have columns alongside the code where you record the values of each variable.

 

If you think paper is too "old school", you can do this in a spreadsheet.

 

Again, this is standard 'C' stuff - not specific to AVR - so it would be easier to do it on a PC, where it's far simpler to step through the code, and watch what's happening.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Seriously.   Don't do it on a spreadsheet.

 

Paper and pencil are fine.

Marker and Whiteboard are fine.

Chalk and Blackboard is fine.

 

Anything that is convenient and you can rub out and start again

Yes,  I know a spreadsheet is alterable.    Humans are less likely to experiment on a screen than on paper.

 

Cigarette packets were invented for this purpose.   Discard the cigarettes.   Draw on the packet.

 

I find that a cup of tea helps.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
   Humans are less likely to experiment on a screen than on paper.

 

Not sure I agree with that, but that's not the point.

 

The point is to do it!

 

the medium is secondary.

 

I do use paper and spreadsheets.

 

I find that a cup of tea help

Just one ??

 

surprise

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

david.prentice wrote:

I find that a cup of tea help

Just one ??

 

surprise

 

About 12 mugs in a typical day.

 

I take your point about "functions in general"  i.e. use whatever suits.

 

I was trying to point out that an 8 line function will fit on a fag packet, envelope, junk mail, ...

You can study it on a bus, train,  queue, ...

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Here is another common way to use strings that are stored in flash memory. 

You need to include the library for accessing program memory.

 

 

const char month01[] PROGMEM = "January";                              
const char month02[] PROGMEM = "February";                             
const char month03[] PROGMEM = "March";                                
const char month04[] PROGMEM = "April";                                
const char month05[] PROGMEM = "May";                                  
const char month06[] PROGMEM = "June";                                 
const char month07[] PROGMEM = "July";                                 
const char month08[] PROGMEM = "August";                               
const char month09[] PROGMEM = "September";                            
const char month10[] PROGMEM = "October";                              
const char month11[] PROGMEM = "November";                             
const char month12[] PROGMEM = "December";                             
                                                                       
const char * const  monthStrs[ 12 ] PROGMEM = {                        
   month01, month02, month03, month04, month05, month06,               
   month07, month08, month09, month10, month11, month12 };
   
    

.. in main()...

      char * myPtr, showBuffer[11];
      
      myPtr = (char *) pgm_read_word (&monthStrs [month-1]);                   
      strcpy_P (showBuffer, myPtr);
      Serial.print (showBuffer);

 

Main() reads the pointer to the beginning of the month name from the array of pointers.  Then it loads the string from flash memory to the SRAM buffer called "showBuffer"
      
      

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you all of you guys just because of you i have learned a lot. I have now understood that my month array works well only when the months value is upto 9 as bcd and binary are same at that level but now as i want o display all the 12 months i have to change the bcd value of the months after the 9th month into its decimal equivalent and then display it. I have used kartman's function on the reply #13 and ya it works well but now after all this the only thing that i want to know is how do i make the function input value equal to my months array so that the function will do the work for me.. Also please hint this thing in my code i will test this out by myself.(So that i can learnsmiley).Thank you all

#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "I2C_Master_H_file.h"
#include "LCD16x2_4Bit.h"


#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */



int second,minute,hour,day,date,month,year;






void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	second = I2C_Read_Ack();						/* Read second */
	minute = I2C_Read_Ack();						/* Read minute */
	hour = I2C_Read_Nack();							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(Device_Write_address);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(Device_Read_address);

	day = I2C_Read_Ack();							/* Read day */
	date = I2C_Read_Ack();							/* Read date */
	month = I2C_Read_Ack();							/* Read month */
	year = I2C_Read_Nack();							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

int main(void)
{

	
	char buffer[20];
	//char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};

	I2C_Init();										/* Initialize I2C */
	lcdinit();										/* Initialize LCD16x2 */

	while(1)
	{
		
		
		 
		RTC_Read_Clock(0);							/* Read the clock with second address i.e location is 0 */
		
		sprintf(buffer, "%02x:%02x:%02x  ", hour, minute, second);
		lcd_print_xy(0,0,buffer);

		RTC_Read_Calendar(3);						/* Read the calender with day address i.e location is 3 */
		sprintf(buffer, "%02x/ %02x /%02x ", date, months[month - 1], year);
		lcd_print_xy(1,0,buffer);
		
		
		 
		
	}
}

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hint.  

%02X shows hex value.  works for valid BCD too

%d shows decimal value

%s shows character string

 

But most importantly.   month is a BCD value.    you must convert it to regular value.  e.g. with bcd2bin() if you index the months[idx] array.

 

David.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:
how do i make the function input value equal to my months array so that the function will do the work for me

I'm not quite sure what you mean by that?

 

But passing an array as a parameter to a function is a basic, everyday 'C' thing - nothing specific to AVR - so you should be able to look it up in your 'C' textbook or any 'C' tutorial.

 

eg,  https://www.tutorialspoint.com/cprogramming/c_passing_arrays_to_functions.htm

 

Or is that not what you're asking?

 

http://c-faq.com/aryptr/

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
But most importantly.   month is a BCD value.    you must convert it to regular value.  e.g. with bcd2bin()

 

Sorry i forgot to post that code here is the fucntion i have created please check for errors and remember i want to show the months names on the lcd please see.

#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include "I2C_Master_H_file.h"
#include "LCD16x2_4Bit.h"


#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */



int second,minute,hour,day,date,month,year;
uint8_t dec;


static inline int bcd_decimal(uint8_t month)
{
	uint8_t assert = (((month & 0xF0) >> 4) < 10);  
	 assert = ((month & 0x0F) < 10);         
	int dec = ((month & 0xF0) >> 4) * 10 + (month & 0x0F);
	return dec;
}

 





void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	second = I2C_Read_Ack();						/* Read second */
	minute = I2C_Read_Ack();						/* Read minute */
	hour = I2C_Read_Nack();							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(Device_Write_address);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(Device_Read_address);

	day = I2C_Read_Ack();							/* Read day */
	date = I2C_Read_Ack();							/* Read date */
	month = I2C_Read_Ack();							/* Read month */
	year = I2C_Read_Nack();							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

int main(void)
{

	
	char buffer[20];
	//char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
		

	I2C_Init();										/* Initialize I2C */
	lcdinit();										/* Initialize LCD16x2 */

	while(1)
	{
		
		
		 
		RTC_Read_Clock(0);							/* Read the clock with second address i.e location is 0 */
		
		sprintf(buffer, "%02x:%02x:%02x  ", hour, minute, second);
		lcd_print_xy(0,0,buffer);

		RTC_Read_Calendar(3);						/* Read the calender with day address i.e location is 3 */
		sprintf(buffer, "%02x/ %0d  /%02x ", date, dec, year);
		lcd_print_xy(1,0,buffer);
		
		
		 
		
	}
}

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:
please check for errors

Have you checked for errors ?

 

Have you stepped through it with pencil & paper ?

 

It your code - you need to do the basic checks.

 

If you've done the checking & stepping and found something you don't understand, then:

  1. Explain what you did;
  2. Explain what you were expecting (and why)
  3. Explain what you actually got
  4. Explain what you've done to find the problem & resolve the issue.
  5.  

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes indeed there is still something that i am unable to understand and that is i have got a runtime error my code works nodoubt without a compile error but i am still getting a zero in place of the months name is there something that i have left. I think i may have used wrong value in the sprintf to display the months name please tell what i am doing wrong.

Attachment(s): 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you've been pointed to Tip #1 several times already - did you not notice that it also tells you how to post images?

 

 

So you're using some sort of a simulator - not real hardware?

 

I think i may have used wrong value in the sprintf to display the months name please tell what i am doing wrong.

Again, what have you done to find what's wrong?

 

Look at your printf() call - which of those parameters is a name ... ?

 

As you're running in a simulator, you must be able to step through the code, examine variables, etc ...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Oct 21, 2019 - 04:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry i will follow the rules from now. Yes i am using proteus software for my hit and trial methods although i do have the hardware but most of the times the simulation software gives pretty accurate results.Here is the thing according to you (which is kind of neat and clean)

 

1. I have induced a bcd_to_decimal variable in my code(I have not tested this code i took it from a website who claims it to be working).

2. I was expecting that now my bcd_values from the rtc will be converted into decimal from so that i can print them directly using %d format specifier used in sprintf.

3. Instead of displaying anything the code just throws a zero on the screen which is the same as when i have tried to print months name after 0x09.

4. I have tried changing the format specifier but in vain and now i am currently changing the bcd_to_decimal function by first writing it according to code given by kartman in #13 and then i will use it in my code.

 

One more thing that i would like to state here is that after the conversion of bcd value to decimal how it will help me to show the months names on the lcd because i am at present displaying the converted integer value what should i do after the conversion please state that too.smiley

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Go on.  Just look at the sprintf() line in your code:

 

sprintf(buffer, "%02x/ %0d  /%02x ", date, dec, year);

 

On a piece of paper, write down the values of each of the variables you are passing into sprintf().

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am so happy by the combined help of kartman(#13), awneil(#14) and david.prentice(#15). I have written this and this code actually works this converts the BCD value to decimal and then displays the hexadecimal value now i know i am just a step away from adding my months names array so that i can display months names instead of the hexadecimal values. Thank you guys your persistance answers made this possible and yes paper and pencil does wonderslaugh

#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include "I2C_Master_H_file.h"
#include "LCD16x2_4Bit.h"


#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */



int second,minute,hour,day,date,year,month ;

uint8_t bcd_to_decimal(uint8_t);

uint8_t bcd_to_decimal(uint8_t val)
{
 uint8_t bcd_value = 0x11;
  val = ((bcd_value & 0xf0)>> 4);
 val *= 10;
 val += bcd_value & 0x0f;
 return val;
 }




void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	second = I2C_Read_Ack();						/* Read second */
	minute = I2C_Read_Ack();						/* Read minute */
	hour = I2C_Read_Nack();							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(Device_Write_address);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(Device_Read_address);

	day = I2C_Read_Ack();							/* Read day */
	date = I2C_Read_Ack();							/* Read date */
	month = I2C_Read_Ack();							/* Read month */
	year = I2C_Read_Nack();							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

int main(void)
{

	uint8_t val;
	char buffer[20];
	//char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	//char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
		

	I2C_Init();										/* Initialize I2C */
	lcdinit();										/* Initialize LCD16x2 */

	while(1)
	{
		
		
		 
		RTC_Read_Clock(0);							/* Read the clock with second address i.e location is 0 */
		
		sprintf(buffer, "%02x:%02x:%02x  ", hour, minute, second);
		lcd_print_xy(0,0,buffer);

		RTC_Read_Calendar(3);						/* Read the calender with day address i.e location is 3 */
		sprintf(buffer, "%02x/ %2x  /%02x ", date, bcd_to_decimal(val), year);   //changes the decimal value into hexadecimal
		lcd_print_xy(1,0,buffer);
		
		
		 
		
	}
}

LCD screen showing converted hexadecimal values

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry i posted the wrong picLCD screen showing converted hexadecimal values

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 

The name "bcd_to_decimal" is a bit misleading.

 

It is actually just converting the BCD encoding to a straight numeric value.

 

"decimal" (or hex, or binary, or octal, or Roman numerals) doesn't come into it until you display the value.

 

So I guess "bcd_to_value" could be a better name.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok i will change the name. Now what i have to do next remember i want to display the months names and you have hinted that i should first convert the bcd values to something(decimal or binary)which can be printed easily. I am successful in creating a bcd2dec() function but now i want to display the names with the help of my months[12] array. Here is what i have written but it throws me a error (as i have expected) please tell me the right way to do this. Thanks.subscripted value is neither array nor pointer nor vector

#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include "I2C_Master_H_file.h"
#include "LCD16x2_4Bit.h"


#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */



int second,minute,hour,day,date,year,month ;

char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};

uint8_t bcd_to_value(uint8_t);

uint8_t bcd_to_value(uint8_t val)
{
 uint8_t bcd_value = months[12];
  val = ((bcd_value & 0xf0)>> 4);
 val *= 10;
 val += bcd_value & 0x0f;
 return val;
 }




void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	second = I2C_Read_Ack();						/* Read second */
	minute = I2C_Read_Ack();						/* Read minute */
	hour = I2C_Read_Nack();							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(Device_Write_address);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(Device_Read_address);

	day = I2C_Read_Ack();							/* Read day */
	date = I2C_Read_Ack();							/* Read date */
	month = I2C_Read_Ack();							/* Read month */
	year = I2C_Read_Nack();							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

int main(void)
{

	uint8_t val;
	char buffer[20];
	//char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
		

	I2C_Init();										/* Initialize I2C */
	lcdinit();										/* Initialize LCD16x2 */

	while(1)
	{
		
		
		 
		RTC_Read_Clock(0);							/* Read the clock with second address i.e location is 0 */
		
		sprintf(buffer, "%02x:%02x:%02x  ", hour, minute, second);
		lcd_print_xy(0,0,buffer);

		RTC_Read_Calendar(3);						/* Read the calender with day address i.e location is 3 */
		sprintf(buffer, "%02x/ %2x  /%02x ", date, bcd_to_value(val[month - 1]), year);   //changes the decimal value into hexadecimal
		lcd_print_xy(1,0,buffer);
		
		
		 
		
	}
}

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have spent 9 days on this.

 

Find a printf() tutorial and do some experimenting.  e.g.

char *name = "Ashman";
sprintf(buf, "%d", 123);
sprintf(buf, "%x", 123);
sprintf(buf, "%s", "David");
sprintf(buf, "%s", name); 
sprintf(buf, "%s", months[5]); 
...

The Internet is very useful but at times I wonder whether you would learn more by sitting in a quiet room with pencil and paper.   No computers !!

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To build your code I had to remove the .h and dummy the functions:

I2C_Init();
I2C_Start(uint8_t);
I2C_Write(uint8_t);
I2C_Repeated_Start(uint8_t);
uint8_t I2C_Read_Ack();
uint8_t I2C_Read_Nack();
I2C_Stop();

lcdinit();
lcd_print_xy(int, int, char *);

Having done that it showed me that the line with the fault is:

	uint8_t val;

		sprintf(buffer, "%02x/ %2x  /%02x ", date, bcd_to_value(val[month - 1]), year);   //changes the decimal value into hexadecimal

You are using "val" as if it were an array when it was only defined as a simple uint8_t.

 

As others have said you need to learn C first.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Learning C must be difficult if English is not your native language.

I would assume that standard textbooks must be published in every language.

 

Follow C tutorials.   Do all the exercises.    Experiment for yourself.

It is easy with a PC and Simulator.

 

Make sure that you understand the basics e.g. variables,  arrays, ...,  functions

 

Experiment with the printf() family.    See what happens when you provide the correct format  string   e.g. %d for numbers, %s for strings

 

I don't know how you got on with Maths in school.

My memories:   if you did the exercises you learned how to solve a similar problem.   If you skipped the classwork,   you never understood how a Maths technique worked.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for a late reply, but i got what you all are saying i need to work on the basics of C first before going into embedded programming. Although i am still not able to display names by the methods you all have suggested to me (could be because of the fact that my basics are not clear) but still i wrote this works perfectly...See if there is a room for improvement. And thanks you all for giving me advice.smiley

#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include "I2C_Master_H_file.h"
#include "LCD16x2_4Bit.h"

#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */

int second,minute,hour,day,date,year,month ;

void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	second = I2C_Read_Ack();						/* Read second */
	minute = I2C_Read_Ack();						/* Read minute */
	hour = I2C_Read_Nack();							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(Device_Write_address);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(Device_Read_address);

	day = I2C_Read_Ack();							/* Read day */
	date = I2C_Read_Ack();							/* Read date */
	month = I2C_Read_Ack();							/* Read month */
	year = I2C_Read_Nack();							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

int main(void)
{

	char buffer[20];

	I2C_Init();										/* Initialize I2C */
	lcdinit();										/* Initialize LCD16x2 */

	while(1)
	{

		RTC_Read_Clock(0);							/* Read the clock with second address i.e location is 0 */

		sprintf(buffer, "%02x:%02x:%02x  ", hour, minute, second);
		lcd_print_xy(0,0,buffer);

		RTC_Read_Calendar(3);	

		if(month == 0x01)
		{
		sprintf(buffer, "%02x/ JAN  /%02x ", date, year);
		lcd_print_xy(1,0,buffer);
		}
		if(month == 0x02)
		{
			sprintf(buffer, "%02x/ FEB  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x03)
		{
			sprintf(buffer, "%02x/ MAR  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x04)
		{
			sprintf(buffer, "%02x/ APR  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x05)
		{
			sprintf(buffer, "%02x/ MAY /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x06)
		{
			sprintf(buffer, "%02x/ JUN /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x07)
		{
			sprintf(buffer, "%02x/ JULY  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x08)
		{
			sprintf(buffer, "%02x/ AUG  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x09)
		{
			sprintf(buffer, "%02x/ SEP  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x10)
		{
			sprintf(buffer, "%02x/ OCT  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x11)
		{
			sprintf(buffer, "%02x/ NOV  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}
		if(month == 0x12)
		{
			sprintf(buffer, "%02x/ DEC  /%02x ", date, year);
			lcd_print_xy(1,0,buffer);
		}

	}
}

months name display

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Sledgehammer to crack a nut code? Ya gotta luv it!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Well, we did try. Even to the point of giving the actual solution.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Brute force works, but eventually you start thinking there must be a better way.

 

There is already plenty of code examples provided, here is one more. You are already using a tool like sprintf, so why not go the rest of the way. The string of interest can go into one continuous string as they are fixed lengths (I'm just trying to come up with something that has not already been shown- a little difficult as everything else is taken). The month you get is in bcd, so make a copy and convert to normal hex/binary so you can get an offset into the string- 0,3,6,9,12,...

    ...

    char month_str[]= {"JANFEBMARAPRMAYJUMJULAUGSEPOCTNOVDEC"};

    while(1)
    {
        ...

        RTC_Read_Calendar(3);    
        //month- 0x01-0x09->0-8 (-1), 0x10,0x11,0x12->9,10,11 (-7)
        int month_hex = month >= 0x10 ? month-7 : month-1;
        sprintf(buffer, "%02x/ %.3s /%02x ", date, &month_str[month_hex*3], year);
        lcd_print_xy(1,0,buffer);

    }
 

Another suggestion thrown in for free- do you really need to split up the rtc reading of the very few registers it has. Just read it all in one call, no need to pass arguments for address. One call, you have the all the latest info. When all are read in the same 'frame', you will get all values that are in sync with each other. If you make the date into a separate read, you can have the time and date out of sync (read time, time rolled over to next day, read date- date and time now do not match). You could end up thinking its (almost) a day  ahead of what it actually is (briefly anyway), could be important.

Last Edited: Tue. Oct 29, 2019 - 09:56 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include "I2C_Master_H_file.h"
#include "LCD16x2_4Bit.h"

#define Device_Write_address	0xD0				/* Define RTC DS1307 slave address for write operation */
#define Device_Read_address		0xD1				/* Make LSB bit high of slave address for read operation */

int second,minute,hour,day,date,year,month ;

uint8_t bcdtobin(uint8_t val)
{
 uint8_t binval;
 binval = ((val & 0xf0)>> 4);
 binval *= 10;
 binval += val & 0x0f;
 return binval;
 }

void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(Device_Write_address);				/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);					/* Write address to read */
	I2C_Repeated_Start(Device_Read_address);		/* Repeated start with device read address */

	second = bcdtobin(I2C_Read_Ack());						/* Read second */
	minute = bcdtobin(I2C_Read_Ack());						/* Read minute */
	hour = bcdtobin(I2C_Read_Nack());							/* Read hour with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(Device_Write_address);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(Device_Read_address);

	day = bcdtobin(I2C_Read_Ack());							/* Read day */
	date = bcdtobin(I2C_Read_Ack());							/* Read date */
	month = bcdtobin(I2C_Read_Ack());							/* Read month */
	year = bcdtobin(I2C_Read_Nack());							/* Read the year with Nack */
	I2C_Stop();										/* Stop i2C communication */
}

int main(void)
{

	uint8_t val;
	char buffer[20];
	//char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	char* months[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};

	I2C_Init();										/* Initialize I2C */
	lcdinit();										/* Initialize LCD16x2 */

	while(1)
	{

		RTC_Read_Clock(0);							/* Read the clock with second address i.e location is 0 */

		sprintf(buffer, "%02d:%02d:%02d  ", hour, minute, second);
		lcd_print_xy(0,0,buffer);

		RTC_Read_Calendar(3);						/* Read the calender with day address i.e location is 3 */
		sprintf(buffer, "%02d/ %s  /%02d ", date, months[month] , year);
		lcd_print_xy(1,0,buffer);

	}
}

 

Now that I'm on a real computer (as opposed to a mobile device) - let's work through the steps that were missed.

 

1. Google bcd to bin. Common problems have common solutions. bcdtobin() is a common name for a function that does what you wanted. You ignored this.

2. If you had googled, you probably would've found references for various RTC chips. You problem has been solved many times before. You chose to re-invent the wheel.

 

When you need to tackle a new project:

1. do your research. It is unlikely you are doing something new and very likely it has been done before.

2. abstraction - the RTC uses BCD. As you've found, that creates problems when you want to do math on it. Asbtract it to something that is more convenient - ie bcdtobin().

If you needed to carry water, you can't simply pick it up. You put it in a bottle. Now you have a bottle of water you can easily carry. Programming is much the same.

 

3. do your research - C is a fairly simple language. With the advent of the internet there is a zillion tutorials and documents. It would've taken you a few hours to do some reading. Whilst this would not have made you an expert in C, you probably would pick up enough so you could make better decisions. As well, you could re-read specific sections to reinforce your knowlege.

 

4. learn how to learn. learn how to solve problems. These are invaluable lessons.

 

 

[edit] fix up dodgy bcdtobin function.

 

 

Last Edited: Wed. Oct 30, 2019 - 05:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>Now that I'm on a real computer (as opposed to a mobile device)

 

It appears your mobile device is the real computer, and your real computer may be broken. If I had to use a mobile to do anything useful, I would be in trouble.

Although the code posted is like code that falls in the forest (the ones that need to hear it are not listening), your bcd routine needs work. There is also the thing about day/date/month being 1 based from the rtc.

 

If your computer is broken, you can play with code online-

https://godbolt.org/z/U-XGXU

https://godbolt.org/z/BW9bND

 

 

:)

Last Edited: Wed. Oct 30, 2019 - 12:55 AM

Pages