Отговори на тема  [ 4 мнения ] 
EFM 32 - Happy Gecko (Digital Clock) 
Автор Съобщение
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение 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);
  }
}



Благодаря !


Съб Яну 26, 2019 6:27 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: EFM 32 - Happy Gecko (Digital Clock)
Какво е меню? Набор от съобщения и реакции на бутончета.
Освен това е едно от състоянията на системата- например -нормално изобразяване на часовника, настройка на часовника, настройка на алармата,сигнализация за аларма.


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

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


Нед Яну 27, 2019 1:12 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Ное 22, 2014 6:23 pm
Мнения: 48
Мнение Re: EFM 32 - Happy Gecko (Digital Clock)
Благодаря ти, но това не ми помага много...много. Прав си, че в моя случай от меню няма нужда, макар че за проекта ми, ще трябва, тъй като ще имам - нормално изобразяване на часовника, настройка на часовника, настройка на алармата,сигнализация за аларма.

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


Пон Яну 28, 2019 8:37 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 03, 2005 1:21 am
Мнения: 10574
Местоположение: София
Мнение Re: EFM 32 - Happy Gecko (Digital Clock)
Пробвай да опишеш на лист алгоритъма с ромбчета, квадрати и т.н. Пример: https://en.wikipedia.org/wiki/Algorithm
Ако не работи в тоя вариант, няма да бачка и като код.
На пръв поглед подобна дейност изглежда като загуба на време, но за неща различни от blink.c, е полезна.


Вто Яну 29, 2019 1:01 am
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 4 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни