Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

EFM 32 - Happy Gecko (Digital Clock)
http://mcu-bg.com/mcu_site/viewtopic.php?f=7&t=16332
Страница 1 от 1

Автор:  Metyyy [ Съб Яну 26, 2019 7:27 pm ]
Заглавие:  EFM 32 - Happy Gecko (Digital Clock)

Здравейте !

Все още не разучил изцяло контролера на Zilog, по стечение на обстоятелствата се наложи да си взема платката, която е в заглавието :) На мен ми се струва доста сложничка, но поне има много хубави примери (повечето неща от source-а са неразбираеми за мен, поне на този етап...), които аз трябва да използвам и модифицирам леко. Всъщност имам цял проект да правя с нея, но това е друг въпрос :)

По-долу прилагам сорса (не съм го писал аз, а фирмата производител), който аз модифицирах леко...да показва само дигитален часовник, без аналогов ( поне това успях :) ). Да отбележа само, че тук не се занимаваме с регистри и т.н., всичко е направено във функции (май driver-и му се казва), което е доста по-удобно, но пък това не значи, че всичко разбирам...като например, тепърва се запознавах с "timer.h", инициализиране на дисплей и т.н, които са ми леко мътнички :)

Сега програмата работи по следният начин: Инициализира се дигиталния часовник и с бутон "0" се увеличават секундите. Въпросът ми е, как да създам меню...при което да ползвам бутон "1" за селектиране на секунди, минути и часове, а пък с бутон "0" да ги увеличавам съответно :) И евентуално - запазване на промяната / отказ от промяната...

Аз пробвах какви ли не щуротии, създавах нови променливи от тип "time_t", if-else, switch и нищо и нищо не става... :rolleyes:
Имам чувство, че това е нещо елементарно и със съвсем леки промени в сорса би трябвало да тръгне без проблеми. Мисля си, че ако аз бях писал програмата от началото, там с регистрите и всичко, някак си ще ми бъде по-лесно, но просто на този етап нямам тази възможност. Разбира се, трябва да уточня, че и език С ми е basic ниво, но всичко с времето си :)))

Код:

#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_gpio.h"
#include "em_pcnt.h"
#include "em_prs.h"
#include "display.h"
#include "glib.h"
#include "bspconfig.h"

/* Frequency of RTC (COMP0) pulses on PRS channel 2
* = frequency of LCD polarity inversion. */
#define RTC_PULSE_FREQUENCY    (64)

/* Clock mode */
typedef enum {
  CLOCK_MODE_ANALOG,
  CLOCK_MODE_DIGITAL
} ClockMode_t;
volatile ClockMode_t clockMode = CLOCK_MODE_DIGITAL;

/* The current time reference. Number of seconds since midnight
* January 1, 1970.  */
static volatile time_t curTime = 0;

/* PCNT interrupt counter */
static volatile int pcntIrqCount = 0;

/* Flag to check when we should redraw a frame */
static volatile bool updateDisplay = true;

/* Global glib context */
GLIB_Context_t gc;

/***************************************************************************//**
* @brief Setup GPIO interrupt for pushbuttons.
******************************************************************************/
static void gpioSetup(void)
{
  /* Enable GPIO clock */
  CMU_ClockEnable(cmuClock_GPIO, true);

  /* Configure PB0 as input and enable interrupt  */
  GPIO_PinModeSet(BSP_GPIO_PB0_PORT, BSP_GPIO_PB0_PIN, gpioModeInputPull, 1);
  GPIO_IntConfig(BSP_GPIO_PB0_PORT, BSP_GPIO_PB0_PIN, false, true, true);

  /* Configure PB1 as input and enable interrupt */
  GPIO_PinModeSet(BSP_GPIO_PB1_PORT, BSP_GPIO_PB1_PIN, gpioModeInputPull, 1);
  GPIO_IntConfig(BSP_GPIO_PB1_PORT, BSP_GPIO_PB1_PIN, false, true, true);

  NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
  NVIC_EnableIRQ(GPIO_EVEN_IRQn);

  NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
  NVIC_EnableIRQ(GPIO_ODD_IRQn);
}

/***************************************************************************//**
* @brief Unified GPIO Interrupt handler (pushbuttons)
*
*PB1 Increments the time by one minute
*******************************************************************************/
void GPIO_Unified_IRQ(void)
{
  /* Get and clear all pending GPIO interrupts */
  uint32_t interruptMask = GPIO_IntGet();
  GPIO_IntClear(interruptMask);

  if (interruptMask & (1 << BSP_GPIO_PB0_PIN)) {
    /* Increase time by 1 second. */
    curTime++;

    updateDisplay = true;
  }
}

/***************************************************************************//**
* @brief GPIO Interrupt handler for even pins
******************************************************************************/
void GPIO_EVEN_IRQHandler(void)
{
  GPIO_Unified_IRQ();
}

/***************************************************************************//**
* @brief GPIO Interrupt handler for odd pins
******************************************************************************/
void GPIO_ODD_IRQHandler(void)
{
  GPIO_Unified_IRQ();
}

/***************************************************************************//**
* @brief   Set up PCNT to generate an interrupt every second.
*
******************************************************************************/
void pcntInit(void)
{
  PCNT_Init_TypeDef pcntInit = PCNT_INIT_DEFAULT;

  /* Enable PCNT clock */
  CMU_ClockEnable(cmuClock_PCNT0, true);
  /* Set up the PCNT to count RTC_PULSE_FREQUENCY pulses -> one second */
  pcntInit.mode = pcntModeOvsSingle;
  pcntInit.top = RTC_PULSE_FREQUENCY;
  pcntInit.s1CntDir = false;
  /* The PRS channel used depends on the configuration and which pin the
     LCD inversion toggle is connected to. So use the generic define here. */
  pcntInit.s0PRS = (PCNT_PRSSel_TypeDef)LCD_AUTO_TOGGLE_PRS_CH;

  PCNT_Init(PCNT0, &pcntInit);

  /* Select PRS as the input for the PCNT */
  PCNT_PRSInputEnable(PCNT0, pcntPRSInputS0, true);

  /* Enable PCNT interrupt every second */
  NVIC_EnableIRQ(PCNT0_IRQn);
  PCNT_IntEnable(PCNT0, PCNT_IF_OF);
}

/***************************************************************************//**
* @brief   This interrupt is triggered at every second by the PCNT
*
******************************************************************************/
void PCNT0_IRQHandler(void)
{
  PCNT_IntClear(PCNT0, PCNT_IF_OF);

  pcntIrqCount++;

  /* Notify main loop to redraw clock on display. */
  updateDisplay = true;
}

/***************************************************************************//**
* @brief  Updates the digital clock.
*
******************************************************************************/
void digitalClockUpdate(struct tm *time, bool redraw)
{
  char clockString[16];

  if (redraw) {
    GLIB_setFont(&gc, (GLIB_Font_t *)&GLIB_FontNumber16x20);
    gc.backgroundColor = White;
    gc.foregroundColor = Black;
    GLIB_clear(&gc);
  }

  sprintf(clockString, "%02d:%02d:%02d", time->tm_hour, time->tm_min, time->tm_sec);
  GLIB_drawString(&gc, clockString, strlen(clockString), 1, 52, true);

  /* Update display */
  DMD_updateDisplay();
}

/***************************************************************************//**
* @brief  Shows an digital clock on the display.
*
******************************************************************************/
void digitalClockShow(bool redraw)
{
  /* Convert time format */
  struct tm *time = gmtime((time_t const *) &curTime);

  if (updateDisplay) {
    digitalClockUpdate(time, redraw);
    updateDisplay = false;
  }
}

/***************************************************************************//**
* @brief  Main function of clock example.
*
******************************************************************************/
int main(void)
{
  EMSTATUS status;
  bool redraw;
  ClockMode_t prevClockMode = CLOCK_MODE_ANALOG;

  /* Chip errata */
  CHIP_Init();

  /* Use the 21 MHz band in order to decrease time spent awake.
     Note that 21 MHz is the highest HFRCO band on ZG. */
  CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO);
  CMU_HFRCOBandSet(cmuHFRCOBand_21MHz);

  /* Setup GPIO for pushbuttons. */
  gpioSetup();

  /* Initialize display module */
  status = DISPLAY_Init();
  if (DISPLAY_EMSTATUS_OK != status) {
    while (true)
      ;
  }

  /* Initialize the DMD module for the DISPLAY device driver. */
  status = DMD_init(0);
  if (DMD_OK != status) {
    while (true)
      ;
  }

  status = GLIB_contextInit(&gc);
  if (GLIB_OK != status) {
    while (true)
      ;
  }

  /* Set PCNT to generate interrupt every second */
  pcntInit();

  /* Enter infinite loop that switches between analog and digitcal clock
   * modes, toggled by pressing the button PB0. */
  while (true) {
    redraw = (prevClockMode != clockMode);
    if (CLOCK_MODE_DIGITAL == clockMode)
    {
       digitalClockShow(redraw);
    }
    /* Sleep between each frame update */
    EMU_EnterEM2(false);
  }
}



Благодаря !

Автор:  stefan63 [ Нед Яну 27, 2019 2:12 pm ]
Заглавие:  Re: EFM 32 - Happy Gecko (Digital Clock)

Какво е меню? Набор от съобщения и реакции на бутончета.
Освен това е едно от състоянията на системата- например -нормално изобразяване на часовника, настройка на часовника, настройка на алармата,сигнализация за аларма.


Погледни си часовника на смартфона и виж - първо се задейства бутон за влизане в промяна.
После вероятно се появява съобщение , подканящо към задаване на ново време.

Часовникът на колата ми има 2 бутончета, с едното увеличавам минутите, с другото -часовете.
Няма влизане, излизане и подканящи надписи. Това струва 2 бутончета.
В система с много функции и малко бутони - се използват менюта .

Автор:  Metyyy [ Пон Яну 28, 2019 9:37 pm ]
Заглавие:  Re: EFM 32 - Happy Gecko (Digital Clock)

Благодаря ти, но това не ми помага много...много. Прав си, че в моя случай от меню няма нужда, макар че за проекта ми, ще трябва, тъй като ще имам - нормално изобразяване на часовника, настройка на часовника, настройка на алармата,сигнализация за аларма.

Колкото наивно и глуповато да прозвучи, не знам как да опиша задействането на промяна и подканването към задаване на ново време. Уж пробвах с разни if-ве, switch-ве и нз си още какво, обаче...нищо. Все ми се струва, че не трябва да правя промени в таймера, интеръпти и т.н., защото това е нещо простичко ама най-вероятно бъркам. Знам ли... :?

Автор:  itso.t [ Вто Яну 29, 2019 2:01 am ]
Заглавие:  Re: EFM 32 - Happy Gecko (Digital Clock)

Пробвай да опишеш на лист алгоритъма с ромбчета, квадрати и т.н. Пример: https://en.wikipedia.org/wiki/Algorithm
Ако не работи в тоя вариант, няма да бачка и като код.
На пръв поглед подобна дейност изглежда като загуба на време, но за неща различни от blink.c, е полезна.

Страница 1 от 1 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/