Перейти к содержанию

STM8L RTC и 7-сегментник


Рекомендуемые сообщения

 

Приветствую!

Разбираюсь с STM8L, посмотрел особенности, видеоуроки, почитал о семействе STM. Имеется немного опыта работы с PIC и AVR.

Нашел 2 индикатора АЛС320, решил первым проектом сделать часы (пока только секунды) с использованием встроенного RTC. Почитал документацию по RTC, посмотрел примеры как людей, так и с библиотеки stdPeriph lib для IAR, подключил индикаторы (по типу схемы под спойлером, только без транзисторов). Сделал простенькую библиотеку для работы с 7-сегментником. Несколько функций для начальной установки времени.

Но вот с выводом времени (секунд) возникли проблемы. В частности, установлен RTC wake-up каждых 500ms, и экран "мерцает" с этой частотой.

Функцию вывода времени запускать через прерывание RTC wake-up или в главной петле в функции main?

И в драйвере 7-сегментника решил сделать функцию для смены яркости путем смены частоты мерцания, но при конфигурации тактирования и делителя, функции delay с refreshDisplay устанавливают намного большую задержку (TimingDelay_Decrement прописан в прерываниях).

Подскажите что я делаю не так.

Спасибо!

timing_delay.c

Spoiler

/**
  ******************************************************************************
  * @file    timing_delay.c
  * @author  MCD Application Team
  * @version V2.1.2
  * @date    19-May-2011
  * @brief   This file contains a set of functions needed to generate 1ms time 
  *          base delay using TIM2 update interrupt.
  *          TimingDelay_Init() function, should be called in the main.c file to
  *          ensure TIM2 initialization and configuration.
  *          The timing accuracy is based on the use of the external low speed
  *          clock source(LSE).
  *          Delay() function should be called in main.c file to specify the 
  *          duration of the desired delay in ms.   
  *          Counter decrementation is performed in TIM2 Update interrupt Handler
  *          by the mean of TimingDelay_Decrement() function. 
  *          This function should be called in the stm8l15x_it.c file in the 
  *          TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler handler.
  *            
  *          @note TimingDelay_Init() function should be tailored in case user 
  *                wants to use a different clock source.
  *           
  *          For more details on timing_delay driver use, you can refer to 
  *          CLK_SYSCLKSwitch example in the STM8L15x_StdPeriph_Lib package.         
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "timing_delay.h"

/** @addtogroup Utilities
  * @{
  */

/** @addtogroup Misc
  * @{
  */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define TIM2_PERIOD  (uint8_t) 7

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static __IO uint32_t TimingDelay;

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @addtogroup TIMING_DELAY_Functions
  * @{
  */

/**
  * @brief  timing delay init:to generate 1 ms time base using TIM2 update interrupt
  * @note   The external low speed clock (LSE) is used to ensure timing accuracy.
  *         This function should be updated in case of use of other clock source.      
  * @param  None
  * @retval None
  */
void TimingDelay_Init(void)
{
  /* Enable TIM2 clock */
  CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);

  /* Remap TIM2 ETR to LSE: TIM2 external trigger becomes controlled by LSE clock */
  SYSCFG_REMAPPinConfig(REMAP_Pin_TIM2TRIGLSE, ENABLE);

  /* Enable LSE clock */
  CLK_LSEConfig(CLK_LSE_ON);
  /* Wait for LSERDY flag to be reset */
  while (CLK_GetFlagStatus(CLK_FLAG_LSERDY) == RESET);

  /* TIM2 configuration:
     - TIM2 ETR is mapped to LSE
     - TIM2 counter is clocked by LSE div 4
      so the TIM2 counter clock used is LSE / 4 = 32.768 / 4 = 8.192 KHz
     TIM2 Channel1 output frequency = TIM2CLK / (TIM2 Prescaler * (TIM2_PERIOD + 1))
                                    = 8192 / (1 * 8) = 1024 Hz                */
                                    
  /* Time Base configuration */
  TIM2_TimeBaseInit(TIM2_Prescaler_1, TIM2_CounterMode_Up, TIM2_PERIOD);
  TIM2_ETRClockMode2Config(TIM2_ExtTRGPSC_DIV4, TIM2_ExtTRGPolarity_NonInverted, 0);

  TIM2_UpdateRequestConfig(TIM2_UpdateSource_Global);

  /* Clear TIM2 update flag */
  TIM2_ClearFlag(TIM2_FLAG_Update);

  /* Enable update interrupt */
  TIM2_ITConfig(TIM2_IT_Update, ENABLE);

  TIM2_Cmd(ENABLE);
}

/**
  * @brief  Inserts a delay time.
  * @param  nTime: specifies the delay time length, in milliseconds.
  * @retval None
  */
void Delay(__IO uint32_t nTime)
{
  TimingDelay = nTime;
  while (TimingDelay != 0);
}

/**
  * @brief  Decrements the TimingDelay variable.
  * @note   This function should be called in the
  *         TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler in the stm8l15x_it.c file.
  *
  *       // INTERRUPT_HANDLER(TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler, 19)
  *       // {
  *           // TimingDelay_Decrement(); 
  *           // TIM2_ClearITPendingBit(TIM2_IT_Update);
  *             
  *       // }  
  * @param  None
  * @retval None
  */
void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00)
  {
    TimingDelay--;
  }
}

/**
  * @}
  */

/**
  * @}
  */
  
/**
  * @}
  */

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

 

segment_driver.cpp

Spoiler

#include "segment_driver.h"

/**
 * Numbers chars
 */
extern const char numbers[10] = {
/*0*/ (1 << SEGMENT_B) | (1 << SEGMENT_C) | (1 << SEGMENT_D) | (1 << SEGMENT_E) | (1 << SEGMENT_F) | (1 << SEGMENT_G),
/*1*/ (1 << SEGMENT_D) | (1 << SEGMENT_G),
/*2*/ (1 << SEGMENT_A) | (1 << SEGMENT_C) | (1 << SEGMENT_D) | (1 << SEGMENT_E) | (1 << SEGMENT_F),
/*3*/ (1 << SEGMENT_A) | (1 << SEGMENT_C) | (1 << SEGMENT_D) | (1 << SEGMENT_G) | (1 << SEGMENT_F),
/*4*/ (1 << SEGMENT_A) | (1 << SEGMENT_B) | (1 << SEGMENT_D) | (1 << SEGMENT_G),
/*5*/ (1 << SEGMENT_A) | (1 << SEGMENT_B) | (1 << SEGMENT_C) | (1 << SEGMENT_F) | (1 << SEGMENT_G),
/*6*/ (1 << SEGMENT_A) | (1 << SEGMENT_B) | (1 << SEGMENT_C) | (1 << SEGMENT_E) | (1 << SEGMENT_F) | (1 << SEGMENT_G),
/*7*/ (1 << SEGMENT_C) | (1 << SEGMENT_D) | (1 << SEGMENT_G),
/*8*/ (1 << SEGMENT_A) | (1 << SEGMENT_B) | (1 << SEGMENT_C) | (1 << SEGMENT_D) | (1 << SEGMENT_E) | (1 << SEGMENT_F) | (1 << SEGMENT_G),
/*9*/ (1 << SEGMENT_A) | (1 << SEGMENT_B) | (1 << SEGMENT_C) | (1 << SEGMENT_D) | (1 << SEGMENT_F) | (1 << SEGMENT_G)
};

// Brightness level
int brightnessLevel = 2; // 2 ms

// Display buffer
char data[INDICATORS_COUNT];

// Store indicators pins
char indicators[INDICATORS_COUNT] = {INDICATOR_1, INDICATOR_2};

/**
 * Initializes display
 */
void initDisplay()
{
  // Init port B to Output push-pull, high level, 10MHz
  GPIO_Init(GPIOB, GPIO_Pin_All, GPIO_Mode_Out_PP_High_Fast);
  
  // Init open drain
  // Indicator 1
  GPIO_Init(GPIOD, GPIO_Pin_4, GPIO_Mode_Out_OD_Low_Fast);
  // Indicator 2
  GPIO_Init(GPIOD, GPIO_Pin_5, GPIO_Mode_Out_OD_Low_Fast);
  // Turn off indication
  GPIOB->ODR = 0;
  
  // Fill display buffer
}

/**
 * Writes into buffer
 */
void write(int num, int indicator)
{
  if (indicator > INDICATORS_COUNT || indicator < INDICATORS_COUNT)
    indicator = 1;
  
  data[indicator - 1] = num;
}

void refreshDisplay()
{
  for (int digitNum = 0 ; digitNum < INDICATORS_COUNT ; digitNum++) {

    // Illuminate the required segments for this digit
    GPIO_Init(GPIOD, indicators[digitNum], GPIO_Mode_Out_OD_Low_Fast);
    GPIO_Write(GPIOB, numbers[data[digitNum]]); // Pickup data from indicator arrays

    // Wait with lights on (to increase brightness)
    //delay_ms(brightnessLevel);
    //Delay(brightnessLevel);
    
    // Turn all lights off
    GPIOB->ODR = 0;
    // Turn port "off" (to push-pull)
    GPIO_Init(GPIOD, indicators[digitNum], GPIO_Mode_Out_PP_High_Fast);
  }
}

/*
 * Clears a display
 */
void clearDisplay()
{
  int i;
  for (i=0;i<INDICATORS_COUNT;i++) {
    data[i] = 0;
  }
}

void setNum(int num)
{
  
}

void setChars(char str[])
{
  int i, indicator = 0;
  
  int len = strlen(str);
  
  if (len > INDICATORS_COUNT || len < 0)
    len = INDICATORS_COUNT;
  
  for (i=0;i<len;i++) {
    data[indicator] = numbers[str[i]];
    indicator++;
  }
}

// TODO: DONE! NOT WORKING!
void setBrightness(int level)
{
  if (level > 100 || level < 0)
    level = 100;
  brightnessLevel = map(level, 0, 100, 1, 2000);
}

// Helper
int map(int x, int in_min, int in_max, int out_min, int out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

 

main.cpp

Spoiler

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Peripheral InitStructure define */
RTC_InitTypeDef   RTC_InitStr;
RTC_TimeTypeDef   RTC_TimeStr;

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main( void )
{ 
  /* Configure and enable RTC */
  RTC_Config();
 
  /* Init display */
  initDisplay();

  /* Initialize time application */
  Calendar_Init();
  
  /* Enable general Interrupt*/
  enableInterrupts();
  
  /* Display current time */
  LCD_ShowTimeCalendar();

  /* Time setting */
  Time_Regulate();
  
  /* RTC wake-up event every 500 ms (timer_step x (1023 + 1) )*/
  RTC_SetWakeUpCounter(1023);
  RTC_WakeUpCmd(ENABLE);
  
  while (1)
  {
    LCD_ShowTimeCalendar();
    //halt();
    
    // Run refresh display
    refreshDisplay();
  }
}

// Global only for debug purposes!
char tmp;

/**
  * @brief  Prints the Time Calender on the GLASS LCD.
  * @param  None
  * @retval None
  */
void LCD_ShowTimeCalendar(void)
{
  /* Wait for RTC registers synchronisation */
  RTC_WaitForSynchro();

  /* Get the current Time*/
  RTC_GetTime(RTC_Format_BCD, &RTC_TimeStr);

  //tmp = (char)(((uint8_t)(RTC_TimeStr.RTC_Hours & 0xF0) >> 4) + 48);
  //LCD_GLASS_WriteChar(&tmp, POINT_OFF, SEPARATOR_OFF, 0);

  //tmp = (char)(((uint8_t)(RTC_TimeStr.RTC_Hours & 0x0F)) + 48);
  //LCD_GLASS_WriteChar(&tmp, POINT_OFF, SEPARATOR_OFF, 1);

  //tmp = (char)(((uint8_t)(RTC_TimeStr.RTC_Minutes & 0xF0) >> 4) + 48);
  //LCD_GLASS_WriteChar(&tmp, POINT_OFF, SEPARATOR_ON, 2);

  //tmp = (char)(((uint8_t)(RTC_TimeStr.RTC_Minutes & 0x0F)) + (uint8_t)48);
  //LCD_GLASS_WriteChar(&tmp, POINT_OFF, SEPARATOR_OFF, 3);

  //tmp = (char)(((uint8_t)(RTC_TimeStr.RTC_Seconds & 0xF0) >> 4) + 48);
  //LCD_GLASS_WriteChar(&tmp, POINT_OFF, SEPARATOR_ON, 4);

  tmp = (char)(((uint8_t)(RTC_TimeStr.RTC_Seconds & 0x0F) >> 4) + 48);
  //LCD_GLASS_WriteChar(&tmp, POINT_OFF, SEPARATOR_OFF, 5);
  
  //tmp = (char)(uint8_t)(RTC_TimeStr.RTC_Seconds);
  setChars(&tmp);
  //write(5,1);
  //write(tmp,2);
  //refreshDisplay();
}

/**
  * @brief  Initializes calendar application.
  * @param  None
  * @retval None
  */
void Calendar_Init(void)
{
  RTC_InitStr.RTC_HourFormat = RTC_HourFormat_24;
  RTC_InitStr.RTC_AsynchPrediv = 0x7C;
  RTC_InitStr.RTC_SynchPrediv = 0x07CF;
  RTC_Init(&RTC_InitStr);

  RTC_TimeStr.RTC_H12     = RTC_H12_AM;
  RTC_TimeStr.RTC_Hours   = 00;
  RTC_TimeStr.RTC_Minutes = 00;
  RTC_TimeStr.RTC_Seconds = 00;
  RTC_SetTime(RTC_Format_BIN, &RTC_TimeStr);
}

/**
  * @brief  Configure RTC peripheral 
  * @param  None
  * @retval None
  */
static void RTC_Config(void)
{
  /* Enable RTC clock */
  CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);
  /* Wait for LSE clock to be ready */
  while (CLK_GetFlagStatus(CLK_FLAG_LSERDY) == RESET);
  /* wait for 1 second for the LSE Stabilisation */
  LSE_StabTime();
  CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);

  /* Configures the RTC wakeup timer_step = RTCCLK/16 = LSE/16 = 488.28125 us */
  RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);

  /* Enable wake up unit Interrupt */
  RTC_ITConfig(RTC_IT_WUT, ENABLE);
}

/**
  * @brief  Wait 1 sec for LSE stabilisation .
  * @param  None.
  * @retval None.
  * Note : TIM4 is configured for a system clock = 2MHz
  */
void LSE_StabTime(void)
{
  CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);

  /* Configure TIM4 to generate an update event each 1 s */
  TIM4_TimeBaseInit(TIM4_Prescaler_16384, 123);
  /* Clear update flag */
  TIM4_ClearFlag(TIM4_FLAG_Update);

  /* Enable TIM4 */
  TIM4_Cmd(ENABLE);

  /* Wait 1 sec */
  while ( TIM4_GetFlagStatus(TIM4_FLAG_Update) == RESET );

  TIM4_ClearFlag(TIM4_FLAG_Update);

  /* Disable TIM4 */
  TIM4_Cmd(DISABLE);

  CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, DISABLE);
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {}
}
#endif

 

Схема подключения (по примеру, но без транзисторов)

Spoiler

00-to-99-Display-in-Quad-7-Segment-Displ

Изменено пользователем Tuxie
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Что-то не то.

Я бы сделал по-другому. Настроил бы прерывание таймера с частотой 400Гц, например. В этом прерывании дела л бы элементарную вещь - гасил разряды, устанавливал сегменты согласно следующему разряду и зажигал бы следующий разряд. Алгоритм прост как пробка. Теперь, изменяешь в основной программе лишь две ячейки памяти а "оно само" на автомате отрисовывает. А теперь изменение яркости - тот же таймер настраиваешь прерывание на сравнение, и в обработчике этого прерывания... просто отключаешь все разряды.

Теперь смотри какая фишка - меняешь регистр сравнения таймера, меняется время через которое разряды погасятся(при переполнении таймера возникает первое прерывание в котором мы зажигаем очередной разряд) и соответственно меняется яркость. Только надо учесть что максимальное значение может отработать некорректно - будет выставлен одновременный запрос на оба прерывания и какое из них первее отработает... того и тапки. и минимальне значение тоже - пока не отработает первое прерывание вызывать второе нет смысла - оно отработает сразу после первого и яркость будет вероятно на нуле. будет какой-то нижний порог, ниже которого будет минимальная яркость.

 

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

10 hours ago, Alexeyslav said:

Что-то не то.

Я бы сделал по-другому. Настроил бы прерывание таймера с частотой 400Гц, например. В этом прерывании дела л бы элементарную вещь - гасил разряды, устанавливал сегменты согласно следующему разряду и зажигал бы следующий разряд. Алгоритм прост как пробка. Теперь, изменяешь в основной программе лишь две ячейки памяти а "оно само" на автомате отрисовывает. А теперь изменение яркости - тот же таймер настраиваешь прерывание на сравнение, и в обработчике этого прерывания... просто отключаешь все разряды.

Теперь смотри какая фишка - меняешь регистр сравнения таймера, меняется время через которое разряды погасятся(при переполнении таймера возникает первое прерывание в котором мы зажигаем очередной разряд) и соответственно меняется яркость. Только надо учесть что максимальное значение может отработать некорректно - будет выставлен одновременный запрос на оба прерывания и какое из них первее отработает... того и тапки. и минимальне значение тоже - пока не отработает первое прерывание вызывать второе нет смысла - оно отработает сразу после первого и яркость будет вероятно на нуле. будет какой-то нижний порог, ниже которого будет минимальная яркость.

 

Спасибо за идейку

Какой лучше таймер использовать? TIM4?

Установку prescaler и period для таймера устанавливать в зависимости от конфигурации CLK_RTCClockConfig?

Каким образом все таки лучше выводить числа на экран? А то у меня функция setChars не лучшим образом реализована

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Я не знаю что там в STM с таймерами, это же не принципиально - лишь бы в нём были доступны те самые вещи. Ну и само собой 8-битного хватит, в 16-битном режиме надо будет ставить слишком высокую частоту тактирования чтобы получить 500Гц переполнения - это просто нерационально. Часто даже в 16-битных таймерах больше одного регистра сравнения, просто второй поставить на 256 и сброс таймера по сравнению.

Ну а setChars - что в ней не так? выполняет же то для чего предназначена?

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

23 hours ago, Alexeyslav said:

Я не знаю что там в STM с таймерами, это же не принципиально - лишь бы в нём были доступны те самые вещи. Ну и само собой 8-битного хватит, в 16-битном режиме надо будет ставить слишком высокую частоту тактирования чтобы получить 500Гц переполнения - это просто нерационально. Часто даже в 16-битных таймерах больше одного регистра сравнения, просто второй поставить на 256 и сброс таймера по сравнению.

Ну а setChars - что в ней не так? выполняет же то для чего предназначена?

setChars некорректно работает, то нормально числа подбирает, то нет. Нужно переделывать и искать "нормальное" решение.

 

Сделал так:

TIM4 (8 битный таймер) поставил на прерывание с использованием внешнего кварца (LSE). С курса STM8 мне ясно что частота выдачи update interrupt равна SYSCLK / PRESCALLER / ARR.

SYSCLK = 32768 hz, prescaler = 32768 / 1 / 81 = ~404hz.  Задал настройки, запустил таймер, прерывание выполняется, но экран (первый индикатор, второй вообще ничего) оооооочень тускло мерцает, отображая "кусочки цифры".

Не совсем понял как это все реализовать. Буду признателен за примеры. Спасибо!

  // Enable TIM4 CLK
  CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);
  
  // LSE 32.768 kHz
  // Time base configuration
  TIM4_TimeBaseInit(TIM4_Prescaler_1, 81);
  // Clear TIM4 update flag
  TIM4_ClearFlag(TIM4_FLAG_Update);
  // Enable update interrupt
  TIM4_ITConfig(TIM4_IT_Update, ENABLE);

  // Enable TIM4
  TIM4_Cmd(ENABLE);

Interrupt handler

INTERRUPT_HANDLER(TIM4_UPD_OVF_TRG_IRQHandler,25)
{
  LCD_ShowTimeCalendar();
  refreshDisplay();
  TIM4_ClearITPendingBit(TIM4_IT_Update);
}

 

Ссылка на комментарий
Поделиться на другие сайты

Цитата

setChars некорректно работает, то нормально числа подбирает, то нет.

А зачем ему подбирать числа? Он их тупо передавать в буфер должен, не более. У вас программа-гадалка?

18 часов назад, Tuxie сказал:

Не совсем понял как это все реализовать. Буду признателен за примеры.

Увы, с STM-ками так плотно не знаком. Поэтому как настроить таймер - это вопрос к документации. И соответственно примеры...

В остальном же алгоритм прост - каждое прерывание берём с буфера очередную цифру, засвечиваем на индикаторе... а не каждое прерывание выводим все цифры и закономерно получаем фигню.

 

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Появилось время, попробовал реализовать сценарий с таймерами. Реализовал с помощью двух. Не нашел наглядных примеров по работе с одним таймером для этих задач.

Были еще проблемы с рассчетом значений таймеров и предделителей RTC, но тем не менее все получилось.

Осталось разобратся с яркостью подсветки и "подправить" энергосбережение.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • Да схема самая обычная, без всяких пиэфси . Вот примерная.  Но блочок все равно не заработал, при превышении нагрузки 50 ватт происходит перекос плечей и выброс
    • @1960sae "Собирал когда то такой конструктор, запустился сразу....". блин. не могу управится с ним. все проверил. нашел пробитый конденсатор, поменял. питание от адаптера сделал 7,3в. регулятор четко 5,05 в держит. на ногах пика питание есть, на всех ногах тоже какая то напруга есть. ниче не греется, транзы холодные. но не работает и все. когда щупами проверял по выводам пика моргнули индикаторы один раз и все. осцилла нет. ума не приложу, интернет рою. пока нифига не смог победить. что смущает: по схеме (я выше здесь выложил) 8 резисторов (на индикаторы идут) по 220 ом, а в наборе они по 1 кОм (я их впаял).  может по прошивке другая частота запуска прописана, может с кварцем что не так. опыта не хватает, конечно, сообразить, куда рыть. буду перебором
    • Кто сказал? Откуда такие знания? Опишите механизм появления искаженного звука. Точно не надо.
    • Здравствуйте. Чтобы не открывать новую тему по примитивному вопросу. На фото выше справа вверху стоит ионистор. На этой плате никаких элементов памяти я не вижу, поэтому скорее всего питание с ионистора подается вверх - на плату с МК.   Правильно ли я понимаю, что ионистор нужен для хранения текущего времени, а рабочая программа хранится в eeprom или flash на плате с МК (или в кишках самого МК)? Вопрос связан с тем, что прежде чем чинить эту LOGO, надо знать, сохранилась ли в нем программа. А чтобы узнать, сохранилась ли в нем программа, надо иметь соответствующую приблуду. Приблуду можно сотворить и самому, но если программа все-таки хранится в sram с питанием от ионистора, то никакого смысла делать приблуду нет, как и чинить LOGO. Просьба просветить, кто в курсе месте хранения рабочей программы в siemens logo. LOGO само собой старый: 6ED1052-1MD00-OBA5  
    • Против разумной, никаких. Кашкаровшина к ней не относится.
    • Так и делаю правильно, из за 50 гигов диск не попру никуда.
×
×
  • Создать...