Здравейте !
Все още не разучил изцяло контролера на Zilog, по стечение на обстоятелствата се наложи да си взема платката, която е в заглавието На мен ми се струва доста сложничка, но поне има много хубави примери (повечето неща от source-а са неразбираеми за мен, поне на този етап...), които аз трябва да използвам и модифицирам леко. Всъщност имам цял проект да правя с нея, но това е друг въпрос 
По-долу прилагам сорса (не съм го писал аз, а фирмата производител), който аз модифицирах леко...да показва само дигитален часовник, без аналогов ( поне това успях ). Да отбележа само, че тук не се занимаваме с регистри и т.н., всичко е направено във функции (май driver-и му се казва), което е доста по-удобно, но пък това не значи, че всичко разбирам...като например, тепърва се запознавах с "timer.h", инициализиране на дисплей и т.н, които са ми леко мътнички 
Сега програмата работи по следният начин: Инициализира се дигиталния часовник и с бутон "0" се увеличават секундите. Въпросът ми е, как да създам меню...при което да ползвам бутон "1" за селектиране на секунди, минути и часове, а пък с бутон "0" да ги увеличавам съответно И евентуално - запазване на промяната / отказ от промяната...
Аз пробвах какви ли не щуротии, създавах нови променливи от тип "time_t", if-else, switch и нищо и нищо не става... Имам чувство, че това е нещо елементарно и със съвсем леки промени в сорса би трябвало да тръгне без проблеми. Мисля си, че ако аз бях писал програмата от началото, там с регистрите и всичко, някак си ще ми бъде по-лесно, но просто на този етап нямам тази възможност. Разбира се, трябва да уточня, че и език С ми е 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); } }
|  |  |  |  |
Благодаря !
|