Здравейте,
Нямам време за цяла 'статия', просто лек увод за тия, които 'не знаят'. За другите, нека допълват ...
Паралелният порт е много удобен за леки проекти, в който нямаме време и средства да инвестираме много.
Писането в паралелният порт може да стане без да пишем драйвер за ядрото, а като го заобиколим – просто искаме от ядрото 'привилегии' ( c примерно ioperm(0x378,2,1)) и използваме входно изходни оператори:
// запис на '1' в порта
#include <sys/io.h>
#include <unistd.h>
...........................
ioperm(0x378,2,1)
.outb(1,0x378);
............................
ioperm(адрес например 0x378, брой следващи адреси за които искаме привилегия – 4, статус активен - 1);
outb(1,0x378); // запис на '1' в порта
http://linux.die.net/man/2/iopermhttp://www.doc.ic.ac.uk/~ih/doc/par/По много начини можем да видим действителните адреси на нашият паралелен порт, например в
/sys/class/ppdev/parport0/device/resources:
state = active
io 0x378-0x37f
irq 7
0x378 е адреса в който можем да четем/ записваме данни, (регистър данни), 0x379 е статус регистъра, а 0x37А ще е контролният регистър. Ако не става записването на изходни данни, вероятната причина е че не сте разрешили изхода ( с бит 5, С5 на 0x37A ) .
***ВНИМАНИЕ!!!
Макар че не ми се е случвало да изгоря паралелен порт досега, вижда се, че това е много вероятно при неправилно свързване ( програмиране).
Може да приемем, че товароспособността на шините е 5 мили ампера.
(макар и на 20ма държи). Също, тя е различна в зависимост от включването - дали '0' или '1' е на изхода/товара.
Конфликт се получава, когато например имаме на изхода '0' (0 волта), а от товара се получава '1' (5 волта.). Или ако използваме 5 Волта напрежение ( то е максималното!!! ) , то 1 кило ом съпротивление м/у порта и товара би ни предпазило от всяка конфликтна ситуация. ( 5 волта делено на 1000 ома е 0.005 ампера).
Ако за товар ползвате светодиоди например, 100-200 ома е ОК.(макар че ги връзвам директно при мен...).
Порт Дата( 2 – 9 )<-----> резистор<------->товар.
Порт маса (25,24,23,...)<---------------------> маса.
Сега, нека минем на софтуера:
Ще използвам Убунту 9.04, Kdevelop, QT 4 Designer
Старт, Разработка->KDevelop-> KDevelop Multilanguage IDE.
Project-> New Project -> C++->QMake project -> Empty Qmake Template ( в нова празна директория).
File-> New-> ( *.cpp)-> main
Значи направихме файл main.cpp,
File-> New-> (QT4 Widget *.ui)-> form
Форма, (която ще си 'нарисуваме' с QT 4 Designer ) .
Щракаме на формата (form.ui в kdevelop), отваря се Designer-а
Слагаме един pushButton и един lcdNumber ( може от property editor
да сложим mode -> hex).
Записваме формата и затваряме 'дизайнера'.
Имаме грубият материал, сега го навързваме:
Разликата между QT3 и QT4 е много голяма, специално в случая, затова и я ползвам за пример. Който е ползвал версия 3, знае че всичко може да си направи с дизайнера, друго му не трябва. Тук обаче не.
С дизайнера (верс. 4) направихме клас 'ui_form' , но ние ще използваме класа form, а липсващото ще си добавим в два файла – my.cpp и my.h . правим ги. В 'main.cpp' пишем:
// файл main.cpp
#include <QApplication>
#include "my.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Form f;
f.show();
return app.exec();
}
-----------------------------------------------------------
Проектият файл за qmake – то трябва да изглежда така:
SOURCES += main.cpp \
my.cpp
FORMS += form.ui
HEADERS += my.h
--------------------------------------------------------
Заглавният файл (my.h):
#ifndef FORM_H
#define FORM_H
#include "ui_form.h" // <= ще си го направи qmake (uic,..)
class Form : public QWidget, private Ui::Form
{
Q_OBJECT
public:
Form(QWidget *parent = 0);
private slots:
private:
};
#endif
------------------------------------------------------
#include <QtGui>
#include "my.h"
Form::Form(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
}
void Form::read_pp(){
}
---------------------------------------
Сега трябва да сме готови, Build->Build project -> Execute Main Program
Имаме програмата, ама не работи както искаме. Само показва формата.
Имаме мегдан за творчество, (като и досега) какво и как ще напишем е просто лично решение, но например решаваме една част да сложим във формата, друга няма начин, ще пишем.
Начи щракане на бутона е събитие, което ни е дефинирано предварително. То води до излъчване на сигнали (emit .....), clicked() е този, който ни трябва. И трябва да го прихванем, затова с дизайнера добавяме слот ( Change signals/slots.... -> slots '+' ) read_pp().
После от signal/slot editor добавяме ('+'):
Sender: pushButton
Signal: clicked()
Receiver: Form
Slot: read_pp()
Сега вече, можем да го ползваме, добавяме го в my.cpp:
void Form::read_pp(){} // най-отдолу
и в my.h:
private slots:
void read_pp(); <- това, обявяваме слот , който ще се изпълни при щракане на бутона.
Единственото, което ни остава е да попълним тази функция с код, който да прочете порта и да ги изобрази на lcdNumber widget-a.
my.cpp
#include <QtGui>
#include "my.h"
// Добавяме :
#include <sys/io.h>
#include <unistd.h>
// за да използваме ioperm(...), iob(..)
...................
void Form::read_pp(){
ioperm(0x378,4,1);
char y=inb(0x378);
lcdNumber->display(y); // lcdNumber->display(inb(0x378));
}
Начи ние наследихме класа на формата чрез класа form, и промените ги правим в него (my.h, my.cpp), а от формата ( с дизайнера) ползваме слотове,сигнали ( от class ui_form) и т.н.
Реално би било добре записа и четенето в порта да си е отделна команда и да се извиква с параметри, но това тук е пример и би бил полезен за някой, който иска бързо да си свърши работа, без да задълбава много.