-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlcd_digital_clock.c
341 lines (283 loc) · 8.24 KB
/
lcd_digital_clock.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/*******************************************************************************
* File : lcd_digital_clock.c
* Brief : Application to read time and date information from the Tiny RTC
* Module (DS1307) and display it on the 16x2 Character LCD (HD4478U)
* Author ; Kyungjae Lee
* Date : Jul 17, 2023
* ****************************************************************************/
#include "lcd_hd44780u.h"
#include "rtc_ds1307.h"
#include <string.h> /* strlen() */
#include <stdio.h> /* printf() */
#include "stm32f407xx.h"
#define SYSTICK_TIM_CLK 16000000UL
/* SysTick timer registers */
#define SYST_CSR (*(uint32_t volatile *)0xE000E010)
#define SYST_RVR (*(uint32_t volatile *)0xE000E014)
/* SysTick Control and Status Register (SYST_CSR) bit fields */
#define SYST_CSR_ENABLE (1 << 0U) /* Counter enabled */
#define SYST_CSR_TICKINT (1 << 1U)
#define SYST_CSR_CLKSOURCE (1 << 2U) /* Processor clock */
#define PRINT_ON_LCD /* Comment this out if LCD is not installed */
/* Function prototypes */
void DisplayPrologue(void);
char* TimeToString(RTC_Time_TypeDef *rtcTime);
char* DateToString(RTC_Date_TypeDef *rtcDate);
char* GetDay(uint8_t dayCode);
void NumToString(uint8_t num, char *buf);
void SysTickTimer_Init(uint32_t tickHz);
void DelayMs(uint32_t delayInMs);
int main(int argc, char *argv[])
{
RTC_Time_TypeDef currTime;
RTC_Date_TypeDef currDate;
char *amPm;
printf("Application running with LCD...\n");
#ifndef PRINT_ON_LCD
printf("Application running without LCD...\n");
#else
/* Initialize LCD module */
LCD_Init();
/* Display the project title and the name of the author */
DisplayPrologue();
#endif
/* Initialize Tiny RTC module */
if (DS1307_Init())
{
/* RTC initialization was unsuccessful */
printf("RTC init failed\n");
while (1);
}
/* Initialize the SysTick Timer so it generates 1 interrupt per second */
SysTickTimer_Init(1);
/* Configure initial date and time to set */
currDate.day = FRIDAY;
currDate.date = 14;
currDate.month = 7;
currDate.year = 23; /* Only the last two digits of the year */
currTime.hours = 11;
currTime.minutes = 59;
currTime.seconds = 50;
currTime.timeFormat = TIME_FORMAT_12HRS_PM;
/* Set initial time and date */
DS1307_SetCurrentDate(&currDate);
DS1307_SetCurrentTime(&currTime);
/* Get initial time and date */
DS1307_GetCurrentDate(&currDate);
DS1307_GetCurrentTime(&currTime);
/* Print current time ----------------------------------------------------*/
if (currTime.timeFormat != TIME_FORMAT_24HRS)
{
/* 12HRS format (e.g., 08:33:45 PM) */
amPm = (currTime.timeFormat) ? "PM" : "AM";
#ifndef PRINT_ON_LCD
printf("Current time = %s %s\n", TimeToString(&currTime), amPm);
#else
LCD_SetCursor(2, 1);
LCD_PrintString(TimeToString(&currTime));
LCD_PrintString(" ");
LCD_PrintString(amPm);
#endif
}
else
{
/* 24HRS format (e.g., 20:33:45) */
#ifndef PRINT_ON_LCD
printf("Current time = %s\n", TimeToString(&currTime));
#else
LCD_PrintString(TimeToString(&currTime));
#endif
}
/* Print current date in 'MM/DD/YY Day' format ---------------------------*/
#ifndef PRINT_ON_LCD
printf("Current date = %s %s\n", DateToString(&currDate), GetDay(currDate.day));
#else
LCD_SetCursor(1, 1);
LCD_PrintString(DateToString(&currDate));
LCD_PrintString(" ");
LCD_PrintString(GetDay(currDate.day));
#endif
while (1);
return 0;
} /* End of main */
/**
* DisplayPrologue()
* Desc. : Displays the project title and the author's name
* Param. : None
* Returns : None
* Note : N/A
*/
void DisplayPrologue(void)
{
/* Display the project title */
LCD_PrintString("Real-time clock");
LCD_SetCursor(2, 1);
LCD_PrintString("on 16x2 LCD");
/* Introduce inter-frame delay */
DelayMs(3000);
/* Clear display */
LCD_ClearDisplay();
LCD_ReturnHome();
/* Display the author's name */
LCD_PrintString("by");
LCD_SetCursor(2, 1);
LCD_PrintString("Kyungjae Lee");
DelayMs(3000);
/* Clear display */
LCD_ClearDisplay();
LCD_ReturnHome();
} /* End of DisplayPrologue */
/**
* TimeToString()
* Desc. : Converts the time represented by @rtcTime to a string
* Param. : @rtcTime - pointer to RTC Time structure
* Return : Time in string format (e.g., HH:MM:SS PM)
* Note : N/A
*/
char* TimeToString(RTC_Time_TypeDef *rtcTime)
{
static char buf[9]; /* Make it static not to return a dangling ptr */
buf[2] = ':';
buf[5] = ':';
NumToString(rtcTime->hours, buf);
NumToString(rtcTime->minutes, &buf[3]);
NumToString(rtcTime->seconds, &buf[6]);
buf[8] = '\0';
return buf;
} /* End of TimeToString */
/**
* DateToString()
* Desc. : Converts the date represented by @rtcDate to a string
* Param. : @rtcDate - pointer to RTC Date structure
* Return : Date in string format (e.g., MM/DD/YY <Day>)
* Note : N/A
*/
char* DateToString(RTC_Date_TypeDef *rtcDate)
{
static char buf[9]; /* Make it static not to return a dangling ptr */
buf[2] = '/';
buf[5] = '/';
NumToString(rtcDate->month, buf);
NumToString(rtcDate->date, &buf[3]);
NumToString(rtcDate->year, &buf[6]);
buf[8] = '\0';
return buf;
} /* End of DateToString */
/**
* GetDay()
* Desc. : Gets the day represented by @dayCode in string format
* Param. : @dayCode - day macro
* Return : Day in string format (e.g., Sunday)
* Note : N/A
*/
char* GetDay(uint8_t dayCode)
{
char *days[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
return days[dayCode];
} /* End of GetDay */
/**
* NumToString()
* Desc. : Converts the passed uint8_t number @num and store it into @buf
* Param. : @num - a number to be converted into a string
* @buf - pointer to a string buffer
* Return : None
* Note : N/A
*/
void NumToString(uint8_t num, char *buf)
{
if (num < 10)
{
buf[0] = '0';
buf[1] = num + '0';
//buf[1] = num + 48;
}
else if (10 <= num && num < 99)
{
buf[0] = num / 10 + '0';
buf[1] = num % 10 + '0';
//buf[0] = num / 10 + 48;
//buf[1] = num % 10 + 48;
}
} /* End of NumToString */
/**
* SysTickTimer_Init()
* Desc. : Initializes the SysTick Timer
* Param. : @tickHz - number of interrupts to be triggered per second
* Return : None
* Note : Counting down to zero asserts the SysTick exception request.
*/
void SysTickTimer_Init(uint32_t tickHz)
{
/* Calculate reload value */
uint32_t reloadVal = (SYSTICK_TIM_CLK / tickHz) - 1;
/* Clear the least significant 24 bits in the SYST_RVR */
SYST_RVR &= ~0x00FFFFFF;
/* Load the counter start value into SYST_RVR */
SYST_RVR |= reloadVal;
/* Configure SYST_CSR */
SYST_CSR |= (SYST_CSR_TICKINT | SYST_CSR_CLKSOURCE | SYST_CSR_ENABLE);
/* TICKINT : Enable SysTick exception request */
/* CLKSOURCE: Specify clock source; processor clock source */
/* ENABLE : Enable counter */
} /* End of SysTickTimer_Init */
/**
* SysTick_Handler()
* Desc. : Handles the SysTick exception
* Param. : None
* Return : None
* Note : N/A
*/
void SysTick_Handler(void)
{
RTC_Time_TypeDef currTime;
RTC_Date_TypeDef currDate;
char *amPm;
/* Print current time ----------------------------------------------------*/
DS1307_GetCurrentTime(&currTime);
if (currTime.timeFormat != TIME_FORMAT_24HRS)
{
/* 12HRS format (e.g., 08:33:45 PM) */
amPm = (currTime.timeFormat) ? "PM" : "AM";
#ifndef PRINT_ON_LCD
printf("Current time = %s %s\n", TimeToString(&currTime), amPm);
#else
LCD_SetCursor(2, 1);
LCD_PrintString(TimeToString(&currTime));
LCD_PrintString(" ");
LCD_PrintString(amPm);
#endif
}
else
{
/* 24HRS format (e.g., 20:33:45) */
#ifndef PRINT_ON_LCD
printf("Current time = %s\n", TimeToString(&currTime));
#else
LCD_SetCursor(2, 1);
LCD_PrintString(TimeToString(&currTime));
#endif
}
/* Print current date in 'MM/DD/YY Day' format ---------------------------*/
DS1307_GetCurrentDate(&currDate);
#ifndef PRINT_ON_LCD
printf("Current date = %s <%s>\n", DateToString(&currDate), GetDay(currDate.day));
#else
LCD_SetCursor(1, 1);
LCD_PrintString(DateToString(&currDate));
LCD_PrintString(" ");
//LCD_PrintChar('<');
LCD_PrintString(GetDay(currDate.day));
//LCD_PrintChar('>');
#endif
} /* End of SysTick_Handler */
/**
* DelayMs()
* Desc. : Spinlock delays for @delayInMs milliseconds
* Param. : @delayInMs - time to delay in milliseconds
* Returns : None
* Note : N/A
*/
void DelayMs(uint32_t delayInMs)
{
for (uint32_t i = 0; i < delayInMs * 1000; i++);
} /* End of DelayMs */