我有一台带有Linux 2.6的mini2440主板,我必须对其进行编程以控制已安装的太阳能电池板。提供了算法,我需要为ARM板编写代码。 GUI在Qt中完成,我需要编写实际控件的代码。我看到了从用户空间访问GPIO的方法,这很乏味。我质疑PWM的准确度。
我可以使用哪些其他方法为GPIO编程开/关和PWM应用程序?
一些朋友建议将控制代码编程为内核模块,但我不太确定我是否希望进入该模块。
答案 0 :(得分:4)
一些朋友建议将控制代码编程为内核模块,但我不太确定我是否希望进入该模块。
我几乎可以肯定,如果它与硬件没有密切关系,它将在Linux内核中被拒绝。用户空间系统调用和sysfs访问的目的是将您的自定义逻辑放在硬件抽象(OSI模型)之上的Linux中。
您需要做的是首先检查Linux内核是否为您的设备提供所有硬件支持。然后,您可以使用我的中间件类以C ++方式控制GPIO。最后,您可以编写一个小的主应用程序来测试内核和C ++类。该应用程序只会像实例化GPIO类,导出GPIO,然后写入值一样简单。
(这与你的PWM问题有什么关系尚不清楚,但你似乎混淆了两个不同的内核驱动程序区域)
根据sysfs,您可以通过Linux kernel gpio documentation执行以下代码。您当然需要确保Linux内核支持您的硬件gpio。
#ifndef FOOBAR_GENERALPURPOSEIO_H
#define FOOBAR_GENERALPURPOSEIO_H
namespace Foobar
{
class FOOBAR_EXPORT GeneralPurposeIO
{
public:
enum Direction {
Input,
Output
};
explicit GeneralPurposeIO(quint32 gpioNumber = 0);
~GeneralPurposeIO();
int gpioExport();
int gpioUnexport();
bool isGpioExported();
quint32 gpioNumber() const;
void setGpioNumber(quint32 gpioNumber);
Direction direction() const;
int setDirection(Direction direction);
qint32 value() const;
int setValue(qint32 value);
private:
class Private;
Private *const d;
};
}
#endif // FOOBAR_GENERALPURPOSEIO_H
#include "generalpurposeio.h"
#include <QtCore/QDebug>
#include <QtCore/QFile>
using namespace Foobar;
class GeneralPurposeIO::Private
{
public:
Private()
{
}
~Private()
{
}
static const QString gpioExportFilePath;
static const QString gpioUnexportFilePath;
static const QString gpioDirectionFilePath;
static const QString gpioValueFilePath;
static const QString gpioFilePath;
quint32 gpioNumber;
};
const QString GeneralPurposeIO::Private::gpioExportFilePath = "/sys/class/gpio/export";
const QString GeneralPurposeIO::Private::gpioUnexportFilePath = "/sys/class/gpio/unexport";
const QString GeneralPurposeIO::Private::gpioDirectionFilePath = "/sys/class/gpio/gpio%1/direction";
const QString GeneralPurposeIO::Private::gpioValueFilePath = "/sys/class/gpio/gpio%1/value";
const QString GeneralPurposeIO::Private::gpioFilePath = "/sys/class/gpio/gpio%1";
GeneralPurposeIO::GeneralPurposeIO(quint32 gpioNumber)
: d(new Private)
{
d->gpioNumber = gpioNumber;
}
GeneralPurposeIO::~GeneralPurposeIO()
{
}
/*
* Exports the desired gpio number.
*
* Note: Unfortunately, it is not possible to just call this method "export"
* since that is a reserved keyword in C++. Systematically the unexport method
* cannot be called "unexport" either for consistency.
*/
int GeneralPurposeIO::gpioExport()
{
if (isGpioExported()) {
// TODO: Proper error mutator mechanism for storing different error
// enumeration values internally that can be requested by the API user
qDebug() << "Cannot export the gpio pin since it is already exported:" << d->gpioNumber;
return -1;
}
QFile gpioExportFile(d->gpioExportFilePath);
if (!gpioExportFile.open(QIODevice::Append)) {
qDebug() << "Cannot open the gpio export file:" << d->gpioExportFilePath;
return -1;
}
/*
* Seek to begining of the file
*/
gpioExportFile.seek(0);
/*
* Write our value of "gpioPinNumber" to the file
*/
if (gpioExportFile.write(QByteArray::number(d->gpioNumber)) == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioExportFilePath;
gpioExportFile.close();
return -1;
}
gpioExportFile.close();
return 0;
}
int GeneralPurposeIO::gpioUnexport()
{
if (!isGpioExported()) {
// TODO: Proper error mutator mechanism for storing different error
// enumeration values internally that can be requested by the API user
qDebug() << "Cannot unexport the gpio pin since it is not exported yet:" << d->gpioNumber;
return -1;
}
QFile gpioUnexportFile(d->gpioUnexportFilePath);
if (!gpioUnexportFile.open(QIODevice::Append)) {
qDebug() << "Cannot open the gpio export file:" << d->gpioUnexportFilePath;
return -1;
}
/*
* Seek to begining of the file
*/
gpioUnexportFile.seek(0);
/*
* Write our value of "gpioPinNumber" to the file
*/
if (gpioUnexportFile.write(QByteArray::number(d->gpioNumber)) == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioUnexportFilePath;
gpioUnexportFile.close();
return -1;
}
gpioUnexportFile.close();
return 0;
}
bool GeneralPurposeIO::isGpioExported()
{
if (!QFile(d->gpioFilePath.arg(d->gpioNumber)).exists()) {
return false;
}
return true;
}
quint32 GeneralPurposeIO::gpioNumber() const
{
return d->gpioNumber;
}
void GeneralPurposeIO::setGpioNumber(quint32 gpioNumber)
{
d->gpioNumber = gpioNumber;
}
GeneralPurposeIO::Direction GeneralPurposeIO::direction() const
{
// TODO: Implement me
return GeneralPurposeIO::Output;
}
int GeneralPurposeIO::setDirection(Direction direction)
{
if (!isGpioExported()) {
if (gpioExport() == -1) {
return -1;
}
}
/*
* Set the direction
*/
QFile gpioDirectionFile(d->gpioDirectionFilePath.arg(d->gpioNumber));
if (!gpioDirectionFile.open(QIODevice::ReadWrite)) {
qDebug() << "Cannot open the relevant gpio direction file:" << d->gpioDirectionFilePath;
return -1;
}
int retval = 0;
/*
* Seek to begining of the file
*/
gpioDirectionFile.seek(0);
switch (direction) {
case Output:
if (gpioDirectionFile.write("high") == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioDirectionFilePath;
retval = -1;
}
break;
case Input:
if (gpioDirectionFile.write("low") == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioDirectionFilePath;
retval = -1;
}
break;
default:
break;
}
gpioDirectionFile.close();
return retval;
}
qint32 GeneralPurposeIO::value() const
{
// TODO: Implement me
return 0;
}
int GeneralPurposeIO::setValue(qint32 value)
{
if (direction() != GeneralPurposeIO::Output) {
qDebug() << "Cannot set the value for an input gpio pin:" << d->gpioNumber;
return -1;
}
/*
* Set the value
*/
QFile gpioValueFile(d->gpioValueFilePath.arg(d->gpioNumber));
if (!gpioValueFile.open(QIODevice::ReadWrite)) {
qDebug() << "Cannot open the relevant gpio value file:" << d->gpioValueFilePath.arg(d->gpioNumber);
gpioValueFile.close();
return -1;
}
/*
* Seek to begining of the file
*/
gpioValueFile.seek(0);
if (gpioValueFile.write(QByteArray::number(value)) == -1) {
qDebug() << Q_FUNC_INFO << "Error while writing the file:" << d->gpioValueFilePath.arg(d->gpioNumber);
gpioValueFile.close();
return -1;
}
gpioValueFile.close();
return 0;
}