§ 8. Применение таймеров для работы с портами
|
Дмитрий Иванов, 15 Января 2007
|
Статья доработана и обновлена 22 Января 2012
|
|
Новерное, как только у Вас получилось "зажигать" и "тушить" светодиоды в LPT порту, сразу же появились мысли: "а нельзя ли записывать или считывать данные из порта с определенным временным интервалом, да к тому же желательно чтоб он был минимальным".
|
Желание вполне логичное, и сразу Вас обрадую, вполне реализуемое. Для начала, в качестве примера, я хотел бы рассказать как сделать простенькую программу, позволяющую с определенной частотой мигать светодиодами, подключенными к LPT порту.
Итак, запускаем Microsoft Visual C++ 6.0 и создаем новый MFC проект с именем, например, LPTTimer.
![](img/PS008/1.gif)
Программа будет основываться на диалоге, по этому выбираем соответствующий пункт. После этого сразу нажимаем Finish, т.к. дальнейшие настройки проекта нас не интересуют.
![](img/PS008/2.gif)
Придайте окну диалога вид, показанный на рис. ниже. Уберите от туда созданные по умолчанию текстовую строчку "TODO: ..." и кнопку Cancel. Кнопку "Ok" переименуюйте, например, в "Exit". Добавьте еще две кнопки и дайте им названия Start Timer и Stop Timer.
![](img/PS008/3.gif)
Содадим обработчик на нажатие кнопки Start Timer. Для этого два раза щщелкните на нее. Появится окно с возможностью изменить имя функции. Задайте имя OnStartTimer. Проделайте аналогичную операцию и для второй кнопки. В качестве имени задайте OnStopTimer.
![](img/PS008/4.gif)
Далее добавьте к проекту все необходимые файлы для работы с библиотекой inpout32.dll. Если забыли как это сделать или первый раз про нее слышите, посмотрите предыдущие статьи этого раздела - там все хорошо расписано.
Теперь допишем тело функуии OnStartTimer(). Как видно из кода, сначала мы записываем в регистр DATA LPT порта число 0, т.е. тушим все светодиоды, подключенные к нему (предполагается, что у Вас к порту подключено какое-нибудь устройство для визуального наблюдения за его состоянием). А вот далее идет вызов не знакомой нам Windows функции SetTimer(). Что она делает? Происходит следующее: вызвав ее с такими параметрами как здесь мы говорим Windows - пожалуйста, каждые 500 мс (миллисекунд) передавай управление на спецализированный обработчик в нашей программе. Первый параметр - это идентификатор таймера (может потребоваться, если мы с своей программе создадим несколько таймеров). Представляет из себя просто целое положительное число, большее нуля. Воторой параметр - это период срабатывания таймера в миллисекундах. Третий - адрес на нашу собственную функцию обработчик, куда Windows передаст управление при срабатывании таймера. Мы здесь будем использовать стандартный Windows обработчик, поэтому передаем NULL.
void CLPTTimerDlg::OnStartTimer()
{
// TODO: Add your control notification handler code here
Out32(0x378, 0);
SetTimer(1, 500, NULL);
}
Давайте определим этот самый обработчик таймера. Для этого заходим в пункт меню View->ClassWizard. Выбираем в разделе "Message Maps" в списке "Object IDs" пункт CLPTTimerDlg. В списке "Messages" выбираем пункт WM_TIMER и нажимаем кнопку Add Function затем Edit Code.
![](img/PS008/5.gif)
Нас перенесет к заготовке функции OnTimer(). Именно на нее будет переходить управление при каждом срабатывании таймера. В качестве параметра ей передается переменная nIDEvent, которая содержит идентификатор таймера. В нашем случае она будет равна 1 (т.к. других таймеров мы не создавали). Что мы будем делать при срабатывании таймера? Сначала прочтем содержимое регистра DATA а потом запишем его же, но проинвертировав. В результате, если в порту все биты были 0 то станут 1 и наоборот. В итоге, светодиоды начнут мигать с частотой 2 Гц.
void CLPTTimerDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
BYTE c=Inp32(0x378);
Out32(0x378, ~c);
CDialog::OnTimer(nIDEvent);
}
Теперь немного допишем код функции OnStopTimer(). Единственное что мы сделаем, так это вызовем функциию KillTimer(). Я думаю, ее функциональное назначение вполне очевидно - она удалит таймер с идентификатором 1. При этом, соответственно, светодиоды мигать перестанут.
void CLPTTimerDlg::OnStopTimer()
{
// TODO: Add your control notification handler code here
KillTimer(1);
}
© Дмитрий Иванов
15 Января 2007
http://www.kernelchip.ru