©
Dale, 02.01.2012 — 02.01.2012.
Начало:
часть 1,
часть 2.
В статье
«Hello World!» в embedded-исполнении мы уже применяли метод моделирования приложения на инструментальной системе. Это дает возможность убедиться в работоспособности будущей системы, не дожидаясь готовности ее аппаратной части. Поступим так же и в этот раз.
На этот раз, помимо таймера и источника света, которые были у нас в упомянутой статье, в новой системе появился также датчик освещенности, который также не мешало бы симулировать. Я решил использовать для управления его состояниями клавиатуру, а для отображения текущего состояния — консольный вывод, как и ранее.
Поскольку консольная строка отображает теперь состояние двух независимых устройств (а в перспективе, как мы увидим, их будет больше), имеет смысл сосредоточить средства симуляции в отдельном модуле.
Датчик освещенности будет симулироваться следующим образом: нажатие клавиши D (в любом регистре) будет переключать текущее состояние датчика в «день» (Day), а нажатие клавиши N (также в любом регистре) — в «ночь» (Night). Между нажатиями клавиш датчик будет сохранять свое состояние.
Для отображения состояния системы будет использоваться строка консоли. Первая литера строки будет отображать текущее состояние датчика освещенности (D/N — «день/ночь» соответственно). Вторая литера будет отображать состояние красного прожектора — R, если он включен, и пробел, если выключен.
Интерфейс симулятора выглядит следующим образом:
#ifndef _SIMULATION_H
#define _SIMULATION_H
/** @file
* @brief Симуляция устройства.
*
* Симулируются следующие периферийные устройства:
* \li датчик освещенности;
* \li красный прожектор.
*
* На консоль выводится строка следующего вида:
* \li первая литера - состояние датчика освещенности: D(Day)/N(Night);
* \li вторая литера - R (если красный прожектор включен) либо пробел.
*
* Смена состояния датчика освещенности симулируется нажатиями клавиш D и N на любом регистре.
*/
/**
* @brief Симуляция состояния датчика освещенности.
*
* Симулирует текущее состояние датчика освещенности. Переключение состояния производится нажатием клавиш D (DFay) и N (Night) на консоли.
*
* @return Состояние датчика освещенности.
* @retval 0 Ночь.
* @retval 1 День.
*/
_Bool Simulation_getDayLightSensor_isDay(void);
/**
* @brief Симуляция состояния красного прожектора.
*
* Симулирует текущее состояние красного прожектора.
* @param val 0 - выключен, 1 - включен.
*/
void Simulation_setRedLightSwitch(_Bool val);
/**
* @brief Итерация симуляции.
*/
void Simulation_run(void);
#endif // _SIMULATION_H
Реализация:
#include "Simulation.h"
#include <conio.h>
#include <ctype.h>
#include <stdio.h>
static _Bool isDayFlag = 0;
_Bool Simulation_getDayLightSensor_isDay(void)
{
char c;
if (_kbhit())
{
c = toupper(_getch());
if (c == 'D')
isDayFlag = 1;
else if (c == 'N')
isDayFlag = 0;
}
return isDayFlag;
}
static _Bool redLightSwitchState = 0;
void Simulation_setRedLightSwitch(_Bool val)
{
redLightSwitchState = val;
}
static char showDayFlag(void)
{
return isDayFlag ? 'D' : 'N';
}
static char showRedLightSwitchState(void)
{
return redLightSwitchState ? 'R' : ' ';
}
void Simulation_run(void)
{
printf("%c%c\r", showDayFlag(), showRedLightSwitchState());
}
#include "RedLightSwitch.h"
#include "Simulation.h"
void RedLightSwitch_init(void)
{
Simulation_setRedLightSwitch(0);
}
void RedLightSwitch_off(void)
{
Simulation_setRedLightSwitch(0);
}
void RedLightSwitch_on(void)
{
Simulation_setRedLightSwitch(1);
}
#include "DayLightSensor.h"
#include "Simulation.h"
void DayLightSensor_init(void)
{
}
_Bool DayLightSensor_isDay(void)
{
return Simulation_getDayLightSensor_isDay();
}
Симуляция таймера несколько отличается от
предыдущей версии. На этот раз мы не можем позволить себе зациклить управление до тех пор, пока будет выдержана необходимая пауза. Вместо этого мы вычислим конечную метку времени, а затем будем проверять, достигнута она или еще нет.
#include "IntervalTimer.h"
#include <time.h>
static clock_t finishMark; // конечная временная метка интервала
void IntervalTimer_init(void)
{
finishMark = 0;
}
void IntervalTimer_start(uint16_t interval)
{
finishMark = clock() + (interval * CLOCKS_PER_SEC / 1000);
}
_Bool IntervalTimer_isElapsed(void)
{
return (clock() >= finishMark);
}
Для целей симуляции нам придется слегка модифицировать реализацию модуля Application:
#include "Application.h"
#include "RedChannelAuto.h"
#include "Simulation.h"
void Application_init(void)
{
RedChannelAuto_init();
}
void Application_run(void)
{
RedChannelAuto_run();
Simulation_run();
}
По сравнению с базовой версией в функцию Application_run() добавлен вызов Simulation_run(), посредством которого производится отображение выходной информации для симуляции устройства на инструментальной системе.
Увидеть результат симуляции можно, загрузив и запустив соответствующее
приложение. Напоминаю, что в процессе симуляции можно использовать клавиши
D и
N для имитации дневного и ночного режимов датчика освещенности.
Архив с текущим состоянием проекта находится во
вложении.
Продолжение.