oktava-studio.ru

Работа с часами M41T94 в LPC2000



Часы 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







Copyright © 2016- Программирование Native API и расширенные возможности NTFS
По вопросам сотрудничества и другим вопросам по работе сайта пишите на cleogroup[собака]yandex.ru