Управление через COM порт внешним устройством. Продолжаем работать с COM портом. В этой статье мы поговорим о том, как можно снаружи управлять этим портом, т.е. записывать в него данные снаружи (через внешнее устройство) и анализировать состояние порта в программе. Обращаю внимание, что пока мы работаем без USART`а (см. ранее) и будем управлять только линиями взаимодействия.
Как все это будет выглядеть? В качестве "внешнего устройства" пока выберем обычный ключ, с помощью котрого будем устанавливать снаружи (для порта) высокий или низкий уровень напряжения на соответствующих линиях. В программе будем считывать состояния этих линиий и отображать их. Этими линиями будут:
* CTS - Готовность к передаче. Линия взаимодействия, с помощью которой внешнее устройство сообщает компьютеру, что оно готово к передаче данных.
* DSR - Готовность внешнего устройства. Линия взаимодействия, с помощью которой внешнее устройство сообщает компьютеру, что оно включено и готово к связи.
А вот ее практическая реализация. Как видно, у меня ключ выполнен в виде простой перемычки. Когда перемычка соединена с землей, на соответствующей линии устанавливается низкий уровень напряжения, когда разъединена - высокий.
Теперь напишем программу, которая будет считывать состояние этих линий и отображать какой уровень напряжения сейчас на них установлен. Для этого создаем новый проект MFC и указываем ему имя, например, TestCOM. Далее выбираем вариант построения на основе диалога.
Придайте внешний вид окну диалога нашей программы, как на рис. ниже. Для этого добавьте два Edit-окна для отображения состояния линии и кнопку, по нажатию на которую будет проведен анализ состояния линий.
Теперь надо создать переменные для Edit-окошек. Для этого выбирайте в главном меню пункт View - > ClassWizard. В открывшемся окне перейдите на вкладку Member Variables. Если в списке Class Name установлен не CTestCOMDlg то выбирите его. В списке просмотра Control IDs выделите идентификатор первого Edit-окна IDC_EDIT (если Вы не изменяли это имя). Нажимайте книпку Add Variable. В открывшемся окне в поле Member Variable Name введите m_CTS (например, такое имя для окна, показывающее состояние линии CTS), в списке Category - Value, а в списке Variable Type тип int. Нажмите Ok.
Аналогично проделываем ту же операцию для окошка, связанного с линией DSR, только назовите переменную как m_DSR.
Далее, в файле TestCOMDlg.h в описание класса диалога добавьте строчку: HANDLE hFile;.
class CTestCOMDlg : public CDialog
{
// Construction
public:
CTestCOMDlg(CWnd* pParent = NULL); // standard constructor
HANDLE hFile;
Абсолютно аналогично с предыдущей статьей этого раздела, добавляем код который открывает порт при загрузке программы. В итоге, функция CTestCOMDlg::OnInitDialog(), расположенная в файле TestCOMDlg.cpp, класса нашего диалога должна принять вид:
BOOL CTestCOMDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
..................
// TODO: Add extra initialization here
hFile = CreateFile("COM2", GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
MessageBox("Не удалось открыть порт!", "Ошибка", MB_ICONERROR);
}
else
{
MessageBox("Порт успешно открыт", "Ok", MB_OK);
}
return TRUE; // return TRUE unless you set the focus to a control
}
Еще раз обращаю внимание на номер открываемого порта. Побробнее об этом написано в предыдущей статье.
А теперь займемся самым интересным - функцией, которая анализирует состояния линий. Для этого создайте функцию-обработчик на кнопку Read (так ее обозвал я) двойным щелчком на нее, и назовите ее, например, OnRead. Добавьте в нее следующий код:
void CTestCOMDlg::OnRead()
{
// TODO: Add your control notification handler code here
ULONG ul=0;
if(GetCommModemStatus(hFile, &ul)!=0)
{
if(ul == 0x10)
{
m_CTS = 1;
m_DSR = 0;
}
if(ul == 0x20)
{
m_CTS = 0;
m_DSR = 1;
}
if(ul == 0x30)
{
m_CTS = 1;
m_DSR = 1;
}
if(ul == 0x00)
{
m_CTS = 0;
m_DSR = 0;
}
UpdateData(false);
}
}
С помощью стандартной Win API функции GetCommModemStatus() проводится считывание состояний линий управления COM порта. Ей передается два параметра - первый, это HANDLE на открытый порт, второй - адрес на переменную, в которую будет помещено числовое значение, характерезующее состояние линий. Далее, если вызов функции был удачным, проводится анализ этой переменной с назначением в переменные Edit-окошек нуля или еденицы в соответствие с тем, какой уровень напряжения был на линии. В конце с помощью функции UpdateData() проводится рбновление информации в Edit-окнах.
Все, комилируем, запускаем. Если все хорошо, должны увидеть сообщение об успешном открытии порта. Далее, замыкая/размыкая ключи на линях, нажимайте кнопку Read. При этом, если на линии ключ разомкнут - в Edit-окне будет еденица, иначе - ноль. Если порт открылся, но манипуляции с ключом не дают результата, убедитесь, что Ваше устройство подключено к тому же порту, который Вы открываете в функции CreateFile().
Иванов Д. В.
16 декабря 2006 года
www.pcports.ru