Часы M41T94 и микроконтроллеры серии LPC2000
Микросхема M41T94 это часы реального времени (RTC), работающие по последовательному протоколу SPI. Здесь будет рассмотрена работа этих часов совместно с микроконтроллерами серии LPC2000 (ядро ARM7TDMI-S). Используемые в коде функции spi_get_byte и spi_put_byte, служащие для обмена по протоколу SPI, описаны на странице «Протокол SPI и микроконтроллеры серии LPC2000».
Сначала описываем некоторые значения, которые используются при работе с микросхемой, а также структуру SRPD_DATE, в которой будет храниться получаемая или передаваемая в микросхему информация о дате и времени.
#define M41T94_REG_SECONDS 0x01
#define M41T94_REG_MINUTES 0x02
#define M41T94_REG_HOURS 0x03
#define M41T94_REG_WDAY 0x04
#define M41T94_REG_DAY 0x05
#define M41T94_REG_MONTH 0x06
#define M41T94_REG_YEAR 0x07
#define M41T94_REG_HT 0x0c
#define M41T94_BIT_HALT 0x40
#define M41T94_BIT_STOP 0x80
#define M41T94_BIT_CB 0x40
#define M41T94_BIT_CEB 0x80
#define M41T94_WRITE 0x80
typedef struct _SRPD_DATE
{
u8 year;
u8 month;
u8 day;
u8 wday; // день недели
u8 hour;
u8 min;
u8 sec;
} SRPD_DATE, *PSRPD_DATE;
bool m41t94_get_time(const struct m41t94_dev * dev, PSRPD_DATE tm);
bool m41t94_set_time(const struct m41t94_dev * dev, PSRPD_DATE tm);
void m41t94_init(const struct m41t94_dev * dev);
void m41t94_print_time(PSRPD_DATE tm);
Две функции преобразования из двоичного кода (BIN) в двоично-десятичный (BCD) и обратно.
static unsigned int bcd2bin(unsigned char val)
{
return (val & 0x0F) + (val >> 4) * 10;
}
static unsigned char bin2bcd(unsigned int val)
{
return ((val / 10)
Дальше две функции, предназначенные для обмена по SPI с микросхемой.
Первая функция m41t94_w8r8, называется так потому, что одновременно и передаёт по SPI,
и получает 8 бит. DEV_OFF_PORT_1 имеет отношение к выбору микросхемы SPI, см. здесь.
Суть в том, что эта функция сначала передаёт команду val, потом сразу читает ответ.
Функция m41t94_write занимается только передачей.
// 0 ok
static short m41t94_write(const struct m41t94_dev * dev, unsigned char *buf, size_t size)
{
short i;
if (NULL == buf)
return 0;
DEV_ON_PORT_1;
for (i = 0; i
Следующие функции занимаются непосредственно установкой даты и её получением с микросхемы.
Тут особо комментариев не будет, и так всё понятно.
void m41t94_init(const struct m41t94_dev * dev)
{
io_dir_out(1, dev->pin_cs);
DEV_OFF_PORT_1;
}
bool m41t94_set_time(const struct m41t94_dev * dev, PSRPD_DATE tm)
{
unsigned char buf[8]; /* write cmd + 7 registers */
if (NULL == dev || NULL == tm)
return false;
buf[0] = M41T94_WRITE | M41T94_REG_SECONDS; /* write time + date */
buf[M41T94_REG_SECONDS] = bin2bcd(tm->sec);
buf[M41T94_REG_MINUTES] = bin2bcd(tm->min);
buf[M41T94_REG_HOURS] = bin2bcd(tm->hour);
buf[M41T94_REG_WDAY] = bin2bcd(tm->wday + 1);
buf[M41T94_REG_DAY] = bin2bcd(tm->day);
buf[M41T94_REG_MONTH] = bin2bcd(tm->month + 1);
buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB;
if (tm->year >= 100)
buf[M41T94_REG_HOURS] |= M41T94_BIT_CB;
buf[M41T94_REG_YEAR] = bin2bcd(tm->year % 100);
return (m41t94_write(dev, buf, 8) > 0);
}
bool m41t94_get_time(const struct m41t94_dev * dev, PSRPD_DATE tm)
{
short ret, hour;
unsigned char buf[2];
if (NULL == dev || NULL == tm)
return false;
ret = m41t94_w8r8(dev, M41T94_REG_HT);
if (ret sec = bcd2bin(ret);
ret = m41t94_w8r8(dev, M41T94_REG_MINUTES);
tm->min = bcd2bin(ret);
hour = m41t94_w8r8(dev, M41T94_REG_HOURS);
tm->hour = bcd2bin(hour & 0x3F);
ret = m41t94_w8r8(dev, M41T94_REG_WDAY);
tm->wday = bcd2bin(ret) - 1;
ret = m41t94_w8r8(dev, M41T94_REG_DAY);
tm->day = bcd2bin(ret);
ret = m41t94_w8r8(dev, M41T94_REG_MONTH);
tm->month = bcd2bin(ret) - 1;
ret = m41t94_w8r8(dev, M41T94_REG_YEAR);
tm->year = bcd2bin(ret);
if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB))
tm->year += 100;
return true;
}
А так можно вывести дату и время для проверки:
void m41t94_print_time(PSRPD_DATE tm)
{
if (NULL == tm)
return;
xprintf("%02d.%02d.%02d %02d:%02d:%02d" CRLF,
tm->day, tm->month, tm->year, tm->hour, tm->min, tm->sec
);
}
Список микроконтроллеров, для которых применим данный код:
LPC2101,
LPC2102,
LPC2103,
LPC2104,
LPC2106,
LPC2109,
LPC2114,
LPC2119,
LPC2124,
LPC2129,
LPC2131,
LPC2132,
LPC2134,
LPC2136,
LPC2138,
LPC2141,
LPC2142,
LPC2144,
LPC2146,
LPC2148,
LPC2194,
LPC2210,
LPC2212,
LPC2214,
LPC2220,
LPC2290,
LPC2292,
LPC2294,
LPC2361,
LPC2362,
LPC2364,
LPC2365,
LPC2366,
LPC2367,
LPC2368,
LPC2377,
LPC2378,
LPC2387,
LPC2420,
LPC2458,
LPC2460,
LPC2468,
LPC2470,
LPC2478.
Автор: амдф
Дата: 10.03.2013
Избранное
Остальное
По вопросам сотрудничества и другим вопросам по работе сайта пишите на cleogroup[собака]yandex.ru