Полная версия этой страницы:
Часы на STM32
ЛеонидК
Nov 20 2010, 09:58
Нужно добавить часы в проект на STM32.
Использую библиотеки ST и пример RTCCalendar.
При инициализации на RTC_WaitForLastTask() программа виснет.
В пошаговом режиме чаще проходит.
Может кто подскажет в чем может быть проблема.
shreck
Nov 20 2010, 10:47
Делал часы реального времени на основе примеров от ST. Все четко работает. Так что код в студию.
ЛеонидК
Nov 20 2010, 11:03
CODE
void RTC_Config(void) {
u16 WaitForOscSource;
if (BKP_ReadBackupRegister(BKP_DR1) != CONF_DONE)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
DateVar.Month = DEFAULT_MOUNT;
DateVar.Day = DEFAULT_DAY;
DateVar.Year = DEFAULT_YEAR;
TimeVar.Sec = DEFAULT_SEC;
TimeVar.Min = DEFAULT_MIN;
TimeVar.Hour = DEFAULT_HOUR;
SummerTimeCorrect =OCTOBER_FLAG_SET;
BKP_WriteBackupRegister(BKP_DR1,CONF_DONE);
RTC_DataWrite();
}
else
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
}
}
AHTOXA
Nov 20 2010, 17:21
А кварц часовой имеется?
ЛеонидК
Nov 20 2010, 17:31
И питание тоже включал.
Правда конденсаторы 9,1 пФ.
Проверьте часовой кварц. Резонит?
ЛеонидК
Nov 20 2010, 18:20
Да
Цитата(ЛеонидК @ Nov 20 2010, 21:20)

Да
Тогда может Вам стоит проверить конкретно биты в регистрах, почему не устанавливаються флаги?
zksystem
Nov 21 2010, 08:29
Цитата(ЛеонидК @ Nov 20 2010, 12:58)

Использую библиотеки ST и пример RTCCalendar.
При инициализации на RTC_WaitForLastTask() программа виснет.
В пошаговом режиме чаще проходит.
Может кто подскажет в чем может быть проблема.
Генератор часов раскачивается полминуты в моем случае, потом, после первой инициализации все нормально, пока батарейку не выдернешь. Советую посмотреть, правильные ли нагрузочные емкости к Вашему кварцу?
shreck
Nov 22 2010, 03:10
Цитата(ЛеонидК @ Nov 20 2010, 18:03)

void RTC_Config(void) {...}
Что-то здесь не так с последовательностью инициализации (хотя вдумчиво не смотрел). Посмотрите как у меня сделано.
CODE
//******************************************************************************
// RTC_DRV_CPP
// DESCRIPTION:
// Драйвер аппаратного RTC.
// При совпадении текущего времени с заданными временами,
// вызывается пользовательский обработчик (из прерывания).
//
//******************************************************************************
#include "rtc_drv.h"
#include "platform_config.h"
#include "stm32f10x.h"
#include "helper.h"
//------------------------------------------------------------------------------
// T Y P E S and D E F I N I T I O N S
//------------------------------------------------------------------------------
namespace
{
const Time zero_time = {0,0,0};
const uint32_t sec_per_day = 0x00015180; // = 24*60*60
enum {nch = 2}; // Кол-во каналов для сравнения.
const uint16_t key = 0xA5A5;
} // ns
//------------------------------------------------------------------------------
// G L O B A L V A R I A B L E S
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// L O C A L S
//------------------------------------------------------------------------------
namespace
{
// Prototypes.
void enable_bkp();
bool rtc_config();
void set_time(const Time& tm);
uint32_t time2int(Time tm);
Time int2time(uint32_t u);
// Variables.
rtc_drv::Cmp_callback callback;
uint32_t cmp_time[nch];
} // ns
//==============================================================================
// I M P L E M E N T A T I O N
//==============================================================================
namespace rtc_drv
{
//------------------------------------------------------------------------------
// Инициализация и запуск "железа".
// Возврат 0 - ошибок нет; 1 - кварц не запустился; 2 - восстановление по
// умолчанию (следствие разряда батареи).
uint8_t init()
{
uint8_t res = 0;
NVIC_InitTypeDef NVIC_InitStructure;
// Enable the RTC Interrupt.
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = RTC_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = RTC_SUBPRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
enable_bkp();
// Наличие правильной настройки определяется по ключевому значению в
// регистре в BKP domain.
if (key != BKP_ReadBackupRegister(BKP_DR1))
{
// Backup data register value is not correct or not yet programmed (when
// the first time the program is executed).
if (!rtc_config())
{
return 1;
}
set_time(zero_time);
BKP_WriteBackupRegister(BKP_DR1, key);
res = 2;
}
else
{
// Без основного питания может пройти не один день. Счетчик необходимо
// привести в надлежащее состояние.
// Wait for RTC registers synchronization.
RTC_WaitForSynchro();
uint32_t ticks = RTC_GetCounter();
ticks = ticks % sec_per_day;
set_time(int2time(ticks));
}
// Enable the RTC Second interrupt.
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
// RTC clock output.
// Disable the Tamper Pin.
// To output RTCCLK/64 on Tamper pin,
// the tamper functionality must be disabled.
BKP_TamperPinCmd(DISABLE);
// Enable RTC Clock Output on Tamper Pin.
BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
return res;
}
//------------------------------------------------------------------------------
// Возврат текущего времени.
Time time()
{
return int2time(RTC_GetCounter());
}
//------------------------------------------------------------------------------
// Установка текущего времени.
void time(const Time& tm)
{
set_time( tm );
}
//------------------------------------------------------------------------------
// Устанавливает значение делителя для получения секундного интервала.
void set_divider(uint32_t div)
{
if (div)
{
// Wait until last write operation on RTC registers has finished.
RTC_WaitForLastTask();
// Enable the RTC Second interrupt.
// Set RTC prescaler: set RTC period to 1sec.
RTC_SetPrescaler(div-1); // RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(div+1)
// Wait until last write operation on RTC registers has finished.
RTC_WaitForLastTask();
}
}
//------------------------------------------------------------------------------
// Устанавливает обработчик.
// При вызове обработчика, ему передается номер канала, в котором было совпадение.
void set_callback(Cmp_callback cb)
{
callback = cb;
}
//------------------------------------------------------------------------------
// Устанавливает время для сравнения.
// ch =[0,1] - канал совпадения.
void set_cmp_time(uint8_t ch, const Time& tm)
{
if (ch < nch)
cmp_time[ch] = time2int( tm );
}
} // namespace rtc_drv
//------------------------------------------------------------------------------
// Обработчик секундного прерывания.
extern "C"
void RTC_IRQHandler()
{
if (RESET != RTC_GetITStatus(RTC_IT_SEC))
{
RTC_ClearITPendingBit(RTC_IT_SEC);
RTC_WaitForLastTask();
// Reset RTC Counter when Time is 23:59:59.
uint32_t curr = RTC_GetCounter();
if (sec_per_day == curr)
{
curr = 0;
RTC_SetCounter(0);
RTC_WaitForLastTask();
}
// Проверка на совпадение.
for (uint_fast8_t i=0; i<nch; ++i)
{
if (curr == cmp_time[i] && callback)
callback(i);
}
}
}
//==============================================================================
// Local functions.
namespace
{
//------------------------------------------------------------------------------
// Открывает доступ к регистрам из bkp domain.
void enable_bkp()
{
// Enable PWR and BKP clocks.
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
// Allow access to BKP Domain.
PWR_BackupAccessCmd(ENABLE);
}
//------------------------------------------------------------------------------
// Настраивает и запускает аппаратный rtc.
// Возврат true, если ошибок нет.
bool rtc_config()
{
BKP_DeInit();
// Enable LSE.
RCC_LSEConfig(RCC_LSE_ON);
// Wait till LSE is ready (но не более 3 секунд).
uint32_t i=0;
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && i<3000)
{
delay_us(1000);
++i;
}
if (i >= 3000) return false;
// Select LSE as RTC Clock Source.
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
// Enable RTC Clock.
RCC_RTCCLKCmd(ENABLE);
// Wait for RTC registers synchronization.
RTC_WaitForSynchro();
rtc_drv::set_divider(rtc_drv::divider_def);
return true;
}
//------------------------------------------------------------------------------
// Устанавливает новое значение времени.
void set_time(const Time& tm)
{
// Wait until last write operation on RTC registers has finished.
RTC_WaitForLastTask();
// Change the current time.
RTC_SetCounter(time2int);
// Wait until last write operation on RTC registers has finished.
RTC_WaitForLastTask();
}
//------------------------------------------------------------------------------
// Преобразование времени в число и обратно.
uint32_t time2int(Time tm)
{
return (tm.hour*3600 + tm.min*60 + tm.sec);
}
Time int2time(uint32_t u)
{
Time tm = {u/3600, (u%3600)/60, (u%3600)%60};
return tm;
}
} // ns
ЛеонидК
Nov 22 2010, 15:16
Так то оно так, только RTC_WaitForLastTask() не проходит.
И прерываний у меня нет. Я хочу смотреть часы, когда хочу, а не во время измерения.
ЛеонидК
Nov 22 2010, 18:32
Вопрос снимается.
Удалил лишнее RTC_WaitForLastTask().
Правда четкого понимания нет.
BlackHead
Oct 13 2011, 13:52
Вероятно, произошло вот что:
Привожу выдержку из мануала RM0008 стр 464:
To enable access to the Backup registers and the RTC, proceed as follows:
● enable the power and backup interface clocks by setting the PWREN and BKPEN bits
in the RCC_APB1ENR register
● set the DBP bit the Power Control Register (PWR_CR) to enable access to the Backup
registers and RTC.
Похоже, второй пункт у Вас не выполнен!
rexton
Feb 15 2012, 17:49
Еще вопрос по часам.
Плата stm32discovery не могу запустить часы от внешнего кварца. Смотрел осцилом - нет генерации на кварце. На OSC32_OUT просто 3 вольта. На OSC32_IN что то около нуля. Самое странное на плате не было резистора R15 который как раз идет с OSC32_OUT на кварц. Впаял перемычку вместо него, ничего не изменилось.
Вот код инициализации часов:
CODE
unsigned char RtcInit (void)
{
//разрешить тактирование модулей управления питанием и управлением резервной областью
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
//разрешить доступ к области резервных данных
PWR->CR |= PWR_CR_DBP;
//если часы выключены - инициализировать их
if ((RCC->BDCR & RCC_BDCR_RTCEN) != RCC_BDCR_RTCEN)
{
//выполнить сброс области резервных данных
RCC->BDCR |= RCC_BDCR_BDRST;
RCC->BDCR &= ~RCC_BDCR_BDRST;
//выбрать источником тактовых импульсов внешний кварц 32768 и подать тактирование
RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_LSE;
RTC->CRL |= RTC_CRL_CNF;
RTC->PRLL = 0x7FFF; //регистр деления на 32768
RTC->CRL &= ~RTC_CRL_CNF;
//установить бит разрешения работы и дождаться установки бита готовности
RCC->BDCR |= RCC_BDCR_LSEON;
while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY);
RTC->CRL &= (uint16_t)~RTC_CRL_RSF;
while((RTC->CRL & RTC_CRL_RSF) != RTC_CRL_RSF){}
return 1;
}
return 0;
}
Что может быть?
rexton
Feb 16 2012, 13:15
Пришлось поменять микроконтроллер и все заработало....
ISK2010
Feb 20 2012, 19:12
Может не в тему, но я не могу понять, зачем использовать такие вещи, как пример RTCCalendar. Зачем сохранять в бэйкап регистры {сек,мин,час, день, мес, год}. А если устройсво долго было выключено, то в примере в цикле начинается посуточный пересчет даты (!). Я понимаю, что в ините может быть что угодно, но это уже перебор. Ведь единственным базисом времени в реальной жизни является относительное время в секундах, например, относительно 00:00:00 01.01.2000. И 32 битного счетчика вам хватит до ~2120 года (батарейки хватит

? ). Т.е. кроме самого счетчика RTC вам ничего не нужно. И арифметика пересчета "секунды века" в человеческие "часы минуты дни месяцы годы" получается проще, чем в примере.
IgorKossak
Feb 20 2012, 20:06
Цитата(ISK2010 @ Feb 20 2012, 21:12)

... например, относительно 00:00:00 01.01.2000.
Тогда уж лучше с
начала века (и тысячелетия), а именно 00:00:00 01.01.2001, к тому же - понедельник.
batson
Nov 10 2012, 10:02
Интересно узнать про точность часов и кто как калибрует.
У меня на платке Discovery, с родным кварцем 6pf, часы без калибровки безбожно врали, на несколько минут в день. В своем проекте я решил попробовать кварц 12.5pf(кварц обычный DT-26, 32768, 12.5pf, другой информации нет. ) и конденсаторы 12pf, знаю что так делать плохо, но ведь работает. Часы стали отставать примерно на 40 сек в сутки, т.е. частота как бы 32752Гц, думаю поменять делитель и не париться, мне достаточно погрешности в несолько минут в год.
KnightIgor
Nov 10 2012, 12:19
Цитата(IgorKossak @ Feb 20 2012, 22:06)

Тогда уж лучше с
начала века (и тысячелетия), а именно 00:00:00 01.01.2001, к тому же - понедельник.
А правильнее, шеф, - с 01-01-1970 00:00:00, т.к. С-шная библиотека с ее функциями даты и времени из этого исходит.
Sidoroff
Dec 23 2013, 07:28
Подниму тему по часам STM32 (или не совсем по часам?).
В общем такое дело. Микроконтроллер STM32F407. Подключаю батарейку CR2032 к VBAT.
Потребление от батарейки 0. Включаю устройство от штатного питания и выключаю.
Потребление от батарейки становится 3 мА, а на шине штатного питания остается
и держится небольшое напряжение примерно на уровне 0.6 вольт.
Батарейка, разумеется, садится через 3 суток, как и положено (220 мА/ч).
Выхода из такого состояния два: или отключить и подключить опять батарейку,
или закоротить и отпустить шину штатного питания (те самые 0.6 вольта).
Наличие или отсутствие программы в МК (можно его полностью стереть) не влияет.
В чем может быть дело? Надо менять МК?
Или что-то надо настроить в регистрах как можно быстрее при запуске прошивки?
Михась
Jan 22 2014, 03:59
STM32F051, сегодня увидел, как на отладочной платке дискавери с внешней 2032, после отключения питания от отладчика (шнур USB от ноута)остался светится светодиод "PWR". После снятия и установки перемычки JP2 (в цепи питания основного процессора)
все угомонилось. Пару раз удалось повторить эффект. Почему батарейка запитывает шину? Все шины питания в одной куче и вроде с этим не должно быть проблем?
mantech
Jan 22 2014, 04:53
Цитата(Sidoroff @ Dec 23 2013, 11:28)

Подниму тему по часам STM32 (или не совсем по часам?).
Потребление от батарейки 0. Включаю устройство от штатного питания и выключаю.
Потребление от батарейки становится 3 мА, а на шине штатного питания остается
и держится небольшое напряжение примерно на уровне 0.6 вольт.
Ну незнаю, делал все, как по даташиту, при выключении питания - 2мкА, так что все в пределах нормы...
VadimNic_nt
Apr 22 2014, 04:14
Пример работы с таймером. может пригодится кому-то.
CODE
/*------------------------------------------------------------------------------
File Name : rtc.h
Author :
Version : 1.1
Date : 17/12/2013
Description : contens functions for work rtc timer stm32f103xx
--------------------------------------------------------------------------------*/
#include "stm32F10x.h"
#include "stm32f10x_rtc.h"
#include "misc.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "time.h"
#include "glb_def.h"
#include "ublox530m_gps.h"
#include "rtc.h"
/*------------------------------------------------------------------------------
| RTC |
------------------------------------------------------------------------------*/
/* Extern variables ----------------------------------------------------------*/
extern FlagEvent_t flag_event;
/* Private variables ---------------------------------------------------------*/
static uint32_t cnt_wait;
static struct tm caltime; /* from time.h*/
__IO static time_t counter;
/* Private function declaration ----------------------------------------------*/
static void Rtc_counter_to_struct(struct tm *caltime);
static time_t Rtc_struct_to_counter(struct tm *caltime);
/**---------------------------------------------------------------------------
* @brief RTC_IRQHandler
* @param none
* @retval none
*---------------------------------------------------------------------------
*/
void RTC_IRQHandler (void) {
uint32_t current_cnt;
if (RTC_GetITStatus(RTC_IT_SEC) == SET) {
RTC_ClearITPendingBit(RTC_IT_SEC);
/*Waits until last write operation
on RTC registers has finished */
RTC_WaitForLastTask();
current_cnt = RTC_GetCounter();
if (current_cnt > cnt_wait) {
/*Waits until last write operation
on RTC registers has finished */
RTC_WaitForLastTask();
/* disable interrupt*/
RTC_ITConfig(RTC_IT_SEC, DISABLE);
/* wait elapsed */
flag_event.WaitElapsed = 1;
}
}
}
/**---------------------------------------------------------------------------
* @brief Init rtc timer stm32f103xx for work
* @param none
* @retval none
*---------------------------------------------------------------------------
*/
void Rtc_Init (void)
{
NVIC_InitTypeDef NVIC_InitStruct;
//enable clock power supply module and buckup domain
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
//enable common access
PWR->CR |= PWR_CR_DBP;
RCC->BDCR |= RCC_BDCR_BDRST;
RCC->BDCR &= ~RCC_BDCR_BDRST;
RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_LSE;
//Enters the RTC configuration mode
RTC->CRL |= RTC_CRL_CNF;
//clock from external quartz
RTC->PRLL = 0x7FFF;
//Exits from the RTC configuration mode
RTC->CRL &= ~RTC_CRL_CNF;
//setup bit enable work LSE and wait ready LSE
RCC->BDCR |= RCC_BDCR_LSEON;
while ((RCC->BDCR & RCC_BDCR_LSEON) != RCC_BDCR_LSEON){}
RTC_WaitForSynchro();
//Setup NVIC for RTC
NVIC_InitStruct.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x0F;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
/**---------------------------------------------------------------------------
* @brief Start wait mode
* @param
* @output
* @retval none
*---------------------------------------------------------------------------
*/
void Rtc_StartWait (DataTimeCmd_t *SETime)
{
struct tm t1, t2;
uint32_t dt;
t1.tm_hour = SETime->StartWaitTime.hour;
t1.tm_isdst = 0;
t1.tm_mday = SETime->StartWaitTime.mday;
t1.tm_min = SETime->StartWaitTime.min;
t1.tm_mon = SETime->StartWaitTime.month-1;
t1.tm_sec = SETime->StartWaitTime.sec;
t1.tm_year = SETime->StartWaitTime.year - 1900;
counter = Rtc_struct_to_counter(&t1);
/*Waits until last write operation
on RTC registers has finished */
RTC_WaitForLastTask();
Rtc_SetCounter(counter);
/**/
t2.tm_hour = SETime->EndWaitTime.hour;
t2.tm_isdst = 0;
t2.tm_mday = SETime->EndWaitTime.mday;
t2.tm_min = SETime->EndWaitTime.min;
t2.tm_mon = SETime->EndWaitTime.month-1;
t2.tm_sec = SETime->EndWaitTime.sec;
t2.tm_year = SETime->EndWaitTime.year - 1900;
/**/
dt = mktime(&t2) - mktime(&t1);
/*Waits until last write operation
on RTC registers has finished */
RTC_WaitForLastTask();
cnt_wait = RTC_GetCounter() + dt;//wmin*60;
//Enable second interrupt
RTC_ITConfig(RTC_IT_SEC, ENABLE);
}
/**---------------------------------------------------------------------------
* @brief populates time-struct based on counter-value
* @param caltime - pointer to time-struct tm (from time.h)
* @output time-struct tm fills
* @retval none
*---------------------------------------------------------------------------
*/
static void Rtc_counter_to_struct (struct tm *caltime)
{
struct tm *ct;
counter = RTC_GetCounter();
ct = localtime((const time_t*)&counter);
memcpy((void*)caltime, (void*)ct, sizeof(struct tm));
}
/**---------------------------------------------------------------------------
* @brief calculates second-counter from populated time-struct tm
* @param caltime - pointer to time-struct tm (from time.h)
* @output none
* @retval counter-value (unit seconds) time_t type
*---------------------------------------------------------------------------
*/
static time_t Rtc_struct_to_counter (struct tm *caltime)
{
counter = mktime(caltime);
return counter;
}
/**---------------------------------------------------------------------------
* @brief populates time-struct RTC_t type from struct tm type
* @param rtc - pointer to RTC_t struct
* @output time-struct gets modified
* @retval none
*---------------------------------------------------------------------------
*/
void Rtc_Gettime (DataTime_t *rtc)
{
Rtc_counter_to_struct(&caltime);
rtc->hour = caltime.tm_hour;
rtc->mday = caltime.tm_mday;
rtc->min = caltime.tm_min;
rtc->month = caltime.tm_mon+1;
rtc->sec = caltime.tm_sec;
rtc->wday = caltime.tm_wday;
rtc->year = caltime.tm_year + 1900;
}
/**---------------------------------------------------------------------------
* @brief sets the hardware-counter
* @param new counter-value
* @output none
* @retval none
*---------------------------------------------------------------------------
*/
void Rtc_SetCounter (uint32_t cnt)
{
/* Change the current time */
RTC->CRL |= RTC_CRL_CNF;
RTC->CNTH = cnt>>16;
RTC->CNTL = cnt;
RTC->CRL &= ~RTC_CRL_CNF;
}
/**---------------------------------------------------------------------------
* @brief populates time-struct tm type from time-struct RTC_t type
* @param none
* @output caltime - global time-struct tm type
* counter - global sec counter
* sets the hardware-counter
* @retval none
*---------------------------------------------------------------------------
*/
void Rtc_Settime (DataTime_t *rtc)
{
caltime.tm_hour = rtc->hour;
caltime.tm_isdst = 0;
caltime.tm_mday = rtc->mday;
caltime.tm_min = rtc->min;
caltime.tm_mon = rtc->month-1;
caltime.tm_sec = rtc->sec;
caltime.tm_year = rtc->year - 1900;
/*Waits until last write operation
on RTC registers has finished */
RTC_WaitForLastTask();
counter = Rtc_struct_to_counter(&caltime);
Rtc_SetCounter(counter);
}
/**---------------------------------------------------------------------------
* @brief Get UTC data and time
* @param data - pointer on struct GPSDATA_t: 'dd,mm,yyyy'
* time - pointer on struct GPSTIME_t: 'hhmmss.ddd'
* @output populates time-struct GPSDATA_t and GPSTIME_t
* @retval none
*---------------------------------------------------------------------------
*/
void Rtc_GetUtcDateTime (GPSDATA_t *data, GPSTIME_t *time) {
DataTime_t rtc;
Rtc_Gettime(&rtc);
data->date_str[0] = rtc.mday/10 + 0x30;
data->date_str[1] = rtc.mday%10 + 0x30;
data->date_str[2] = ',';
data->date_str[3] = rtc.month/10 + 0x30;
data->date_str[4] = rtc.month%10 + 0x30;
data->date_str[5] = ',';
data->date_str[6] = rtc.year/1000 + 0x30;
data->date_str[7] = (rtc.year%1000)/100 + 0x30;
data->date_str[8] = (rtc.year%100)/10 + 0x30;
data->date_str[9] = rtc.year%10 + 0x30;
//
time->time_str[0] = rtc.hour/10 + 0x30;
time->time_str[1] = rtc.hour%10 + 0x30;
time->time_str[2] = rtc.min/10 + 0x30;
time->time_str[3] = rtc.min%10 + 0x30;
time->time_str[4] = rtc.sec/10 + 0x30;
time->time_str[5] = rtc.sec%10 + 0x30;
time->time_str[6] = '.';
time->time_str[7] = '0';
time->time_str[8] = '0';
time->time_str[9] = '0';
}
/**---------------------------------------------------------------------------
* @brief Get UTC data and time
* @param rtc - pointer on struct RTC_t
* ttime_str - pointer on struct RtcDataTime_t: 'dd,mm,yyyyhhmmss.ddd'
* @output populates time-struct RtcDataTime_t
* @retval none
*---------------------------------------------------------------------------
*/
void Rtc_ConvertToStr(DataTime_t *rtc, StrDataTime_t *time_str)
{
time_str->Data.date_str[0] = rtc->mday/10 + 0x30;
time_str->Data.date_str[1] = rtc->mday%10 + 0x30;
time_str->Data.date_str[2] = ',';
time_str->Data.date_str[3] = rtc->month/10 + 0x30;
time_str->Data.date_str[4] = rtc->month%10 + 0x30;
time_str->Data.date_str[5] = ',';
time_str->Data.date_str[6] = rtc->year/1000 + 0x30;
time_str->Data.date_str[7] = (rtc->year%1000)/100 + 0x30;
time_str->Data.date_str[8] = (rtc->year%100)/10 + 0x30;
time_str->Data.date_str[9] = rtc->year%10 + 0x30;
//
time_str->Time.time_str[0] = rtc->hour/10 + 0x30;
time_str->Time.time_str[1] = rtc->hour%10 + 0x30;
time_str->Time.time_str[2] = rtc->min/10 + 0x30;
time_str->Time.time_str[3] = rtc->min%10 + 0x30;
time_str->Time.time_str[4] = rtc->sec/10 + 0x30;
time_str->Time.time_str[5] = rtc->sec%10 + 0x30;
time_str->Time.time_str[6] = '.';
time_str->Time.time_str[7] = '0';
time_str->Time.time_str[8] = '0';
time_str->Time.time_str[9] = '0';
}
/*----------------------------END OF FILE-------------------------------------*/
Цитата(Sidoroff @ Dec 23 2013, 10:28)

Подниму тему по часам STM32 (или не совсем по часам?).
В общем такое дело. Микроконтроллер STM32F407. Подключаю батарейку CR2032 к VBAT.
Потребление от батарейки 0. Включаю устройство от штатного питания и выключаю.
Потребление от батарейки становится 3 мА, а на шине штатного питания остается
и держится небольшое напряжение примерно на уровне 0.6 вольт.
Батарейка, разумеется, садится через 3 суток, как и положено (220 мА/ч).
Выхода из такого состояния два: или отключить и подключить опять батарейку,
или закоротить и отпустить шину штатного питания (те самые 0.6 вольта).
Наличие или отсутствие программы в МК (можно его полностью стереть) не влияет.
В чем может быть дело? Надо менять МК?
Или что-то надо настроить в регистрах как можно быстрее при запуске прошивки?
Столкнулся с такой же проблемой на STM32F051. Началось с того что хотел откалибровать внутренние часы и вывел на PC13 частоту чтобы измерить период. Оставил на пару дней чтобы определить на сколько уйдут часы и батарейка оказалась разряжена. В ходе разбирательства выяснилось что в режиме вывода частоты этот вывод push-pull, а не open drain. И при выключенном питании контроллера все так же пытается выдать единичку и тянет ток из батарейки. Как только отключил выдачу частоты, стразу стало все нормально.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.