嵌入式程序设计

嵌入式程序设计

前言

思维导图

用 Qt 编写嵌入式 GUI 程序——加减乘除四则运算器设计

头文件

calculator.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#ifndef CALCULATOR_H
#define CALCULATOR_H //对 calculator.h 头文件的声明
#include <QWidget> //包含主窗体类
#include <QPushButton> //包含按键类
#include <QVBoxLayout> //包含垂直布局器类
#include <QHBoxLayout> //包含水平布局器类
#include <QLineEdit> //包含显示框类
#include <QStack>
class Calculator : public QWidget //计算器继承自主窗体类
{
Q_OBJECT //必须加上这句,如果要调用信号,槽函数的操作的话
public:
Calculator(); //计算器类的构造函数
~Calculator(); //计算器类的析构函数
public slots: //定义各个按键按下后对应操作处理的槽函数
void zeroButtonPress();
void oneButtonPress();
void twoButtonPress();
void threeButtonPress();
void fourButtonPress();
void fiveButtonPress();
void sixButtonPress();
void sevenButtonPress();
void eightButtonPress();
void nineButtonPress();
void addButtonPress();
void subButtonPress();
void mulButtonPress();
void divButtonPress();
void clearButtonPress();
void equButtonPress();
private:
QLineEdit *operateEdit;//声明显示框
QPushButton *zeroButton;//声明数字按键¹
QPushButton *oneButton;
QPushButton *twoButton;
QPushButton *threeButton;
QPushButton *fourButton;
QPushButton *fiveButton;
QPushButton *sixButton;
QPushButton *sevenButton;
QPushButton *eightButton;
QPushButton *nineButton;
QPushButton *clearButton;//声明运算符按键
QPushButton *addButton;
QPushButton *subButton;
QPushButton *divButton;
QPushButton *mulButton;
QPushButton *equButton;
QHBoxLayout *firstLayout;//声明水平布局器,该布局器主要对 16 个按键进行布局
QHBoxLayout *secondLayout;
QHBoxLayout *thirdLayout;
QHBoxLayout *fourthLayout;
QVBoxLayout *mainLayout;//声明垂直布局器,该布局器主要对主窗体上面的空间进行排布
QString expression;
int precedence(QChar op);
float calculator(float a,float b,QChar op);
};
#endif // CALCULATOR_H

源文件

calculator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
#include"calculator.h"
Calculator::Calculator()
{
operateEdit = new QLineEdit(this);//初始化显示框
operateEdit->setReadOnly(true); //设置显示框为只读
operateEdit->setText(tr("0"));//初始化显示框显示数据为0
zeroButton = new QPushButton;//初始化按键
zeroButton->setText(tr("0"));//设置按键上显示的标签,以下对按键相关的操作类似
oneButton = new QPushButton;
oneButton->setText(tr("1"));
twoButton = new QPushButton;
twoButton->setText(tr("2"));
threeButton = new QPushButton;
threeButton->setText(tr("3"));
fourButton = new QPushButton;
fourButton->setText(tr("4"));
fiveButton = new QPushButton;
fiveButton->setText(tr("5"));
sixButton = new QPushButton;
sixButton->setText(tr("6"));
sevenButton = new QPushButton;
sevenButton->setText(tr("7"));
eightButton = new QPushButton;
eightButton->setText(tr("8"));
nineButton = new QPushButton;
nineButton->setText(tr("9"));
clearButton = new QPushButton;
clearButton->setText(tr("Clear"));
addButton = new QPushButton;
addButton->setText(tr("+"));
subButton = new QPushButton;
subButton->setText(tr("-"));
mulButton = new QPushButton;
mulButton->setText(tr("*"));
divButton = new QPushButton;
divButton->setText(tr("/"));
equButton = new QPushButton;
equButton->setText(tr("="));
firstLayout = new QHBoxLayout;//初始化水平布局器 firstLayout
firstLayout->addWidget(zeroButton); //把按键 zeroButton 添加到 firstLayout
firstLayout->addWidget(oneButton); //把按键 oneButton 添加到 firstLayout
firstLayout->addWidget(twoButton); //把按键 twoButton 添加到 firstLayout
firstLayout->addWidget(addButton); //把按键 threeButton 添加到 firstLayout,以下对水平布局器的操作类似
secondLayout = new QHBoxLayout;
secondLayout->addWidget(threeButton);
secondLayout->addWidget(fourButton);
secondLayout->addWidget(fiveButton);
secondLayout->addWidget(subButton);
thirdLayout = new QHBoxLayout;
thirdLayout->addWidget(sixButton);
thirdLayout->addWidget(sevenButton);
thirdLayout->addWidget(eightButton);
thirdLayout->addWidget(mulButton);
fourthLayout = new QHBoxLayout;
fourthLayout->addWidget(nineButton);
fourthLayout->addWidget(clearButton);
fourthLayout->addWidget(equButton);
fourthLayout->addWidget(divButton);
mainLayout = new QVBoxLayout(this);//初始化垂直布局器 mainLayout
mainLayout->addWidget(operateEdit); //把显示数据框 operateEdit 加到 mainLayout
mainLayout->addLayout(firstLayout); //把水平布局器 firstLayout 添加到 mainLayout
mainLayout->addLayout(secondLayout); //把水平布局器 secondLayout 添加到mainLayout
mainLayout->addLayout(thirdLayout); //把水平布局器 thirdLayout 添加到 mainLayout
mainLayout->addLayout(fourthLayout); //把水平布局器 fourthLayout 添加到 mainLayout
connect(zeroButton,SIGNAL(clicked()),this,SLOT(zeroButtonPress()));
//把按键 zeroButton 的按下事件同 zeroButtonPress()绑定到一起,以下操作类似
connect(oneButton,SIGNAL(clicked()),this,SLOT(oneButtonPress()));
connect(twoButton,SIGNAL(clicked()),this,SLOT(twoButtonPress()));
connect(threeButton,SIGNAL(clicked()),this,SLOT(threeButtonPress()));
connect(fourButton,SIGNAL(clicked()),this,SLOT(fourButtonPress()));
connect(fiveButton,SIGNAL(clicked()),this,SLOT(fiveButtonPress()));
connect(sixButton,SIGNAL(clicked()),this,SLOT(sixButtonPress()));
connect(sevenButton,SIGNAL(clicked()),this,SLOT(sevenButtonPress()));
connect(eightButton,SIGNAL(clicked()),this,SLOT(eightButtonPress()));
connect(nineButton,SIGNAL(clicked()),this,SLOT(nineButtonPress()));
connect(addButton,SIGNAL(clicked()),this,SLOT(addButtonPress()));
connect(subButton,SIGNAL(clicked()),this,SLOT(subButtonPress()));
connect(mulButton,SIGNAL(clicked()),this,SLOT(mulButtonPress()));
connect(divButton,SIGNAL(clicked()),this,SLOT(divButtonPress()));
connect(equButton,SIGNAL(clicked()),this,SLOT(equButtonPress()));
connect(clearButton,SIGNAL(clicked()),this,SLOT(clearButtonPress()));
this->setWindowTitle(tr("Calculator"));//设置窗体标题为 Calculator
expression="";
}

Calculator::~Calculator()
{
if (operateEdit != NULL)
{
delete operateEdit;
operateEdit = NULL;
}

if (zeroButton != NULL)
{
delete zeroButton;
zeroButton = NULL;
}

if (oneButton != NULL)
{
delete oneButton;
oneButton = NULL;
}

if (twoButton != NULL)
{
delete twoButton;
twoButton = NULL;
}

if (threeButton != NULL)
{
delete threeButton;
threeButton = NULL;
}

if (fourButton != NULL)
{
delete fourButton;
fourButton = NULL;
}

if (fiveButton != NULL)
{
delete fiveButton;
fiveButton = NULL;
}

if (sixButton != NULL)
{
delete sixButton;
sixButton = NULL;
}

if (sevenButton != NULL)
{
delete sevenButton;
sevenButton = NULL;
}

if (eightButton != NULL)
{
delete eightButton;
eightButton = NULL;
}

if (nineButton != NULL)
{
delete nineButton;
nineButton = NULL;
}

if (clearButton != NULL)
{
delete clearButton;
clearButton = NULL;
}

if (addButton != NULL)
{
delete addButton;
addButton = NULL;
}

if (subButton != NULL)
{
delete subButton;
subButton = NULL;
}

if (mulButton != NULL)
{
delete mulButton;
mulButton = NULL;
}

if (divButton != NULL)
{
delete divButton;
divButton = NULL;
}

if (equButton != NULL)
{
delete equButton;
equButton = NULL;
}

if (firstLayout != NULL)
{
delete firstLayout;
firstLayout = NULL;
}

if (secondLayout != NULL)
{
delete secondLayout;
secondLayout = NULL;
}

if (thirdLayout != NULL)
{
delete thirdLayout;
thirdLayout = NULL;
}

if (fourthLayout != NULL)
{
delete fourthLayout;
fourthLayout = NULL;
}

if (mainLayout != NULL)
{
delete mainLayout;
mainLayout = NULL;
}
}



void Calculator::zeroButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression += "0";
} else {
expression.append("0");
}
operateEdit->setText(expression);
}

void Calculator::oneButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "1";
} else {
expression.append("1");
}
operateEdit->setText(expression);
}

void Calculator::twoButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "2";
} else {
expression.append("2");
}
operateEdit->setText(expression);
}

void Calculator::threeButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "3";
} else {
expression.append("3");
}
operateEdit->setText(expression);
}

void Calculator::fourButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "4";
} else {
expression.append("4");
}
operateEdit->setText(expression);
}

void Calculator::fiveButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "5";
} else {
expression.append("5");
}
operateEdit->setText(expression);
}

void Calculator::sixButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "6";
} else {
expression.append("6");
}
operateEdit->setText(expression);
}

void Calculator::sevenButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "7";
} else {
expression.append("7");
}
operateEdit->setText(expression);
}

void Calculator::eightButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "8";
} else {
expression.append("8");
}
operateEdit->setText(expression);
}

void Calculator::nineButtonPress()
{
if(expression.isEmpty() || expression.endsWith('0')) {
expression = "9";
} else {
expression.append("9");
}
operateEdit->setText(expression);
}

void Calculator::addButtonPress()
{
if(!expression.isEmpty() && !expression.endsWith('+') && !expression.endsWith('-') && !expression.endsWith('*') && !expression.endsWith('/')) {
expression.append("+");
}
operateEdit->setText(expression);
}

void Calculator::subButtonPress()
{
if(!expression.isEmpty() && !expression.endsWith('+') && !expression.endsWith('-') && !expression.endsWith('*') && !expression.endsWith('/')) {
expression.append("-");
}
operateEdit->setText(expression);
}

void Calculator::mulButtonPress()
{
if(!expression.isEmpty() && !expression.endsWith('+') && !expression.endsWith('-') && !expression.endsWith('*') && !expression.endsWith('/')) {
expression.append("*");
}
operateEdit->setText(expression);
}

void Calculator::divButtonPress()
{
if(!expression.isEmpty() && !expression.endsWith('+') && !expression.endsWith('-') && !expression.endsWith('*') && !expression.endsWith('/')) {
expression.append("/");
}
operateEdit->setText(expression);
}

void Calculator::clearButtonPress()
{
expression.clear();
operateEdit->setText("0");
}
//等号操作响应函数
void Calculator::equButtonPress()
{
if(expression.isEmpty()) {
return;
}

QStack<float> numbers;
QStack<QChar> operators;
QString number;
for(int i = 0; i < expression.size(); ++i) {
QChar c = expression.at(i);
if(c.isDigit() || c == '.') {
number.append(c);
} else {
if(!number.isEmpty()) {
numbers.push(number.toFloat());
number.clear();
}
while(!operators.isEmpty() && precedence(operators.top()) >= precedence(c)) {
float second = numbers.pop();
float first = numbers.pop();
QChar op = operators.pop();
numbers.push(calculator(first, second, op));
}
operators.push(c);
}
}
if(!number.isEmpty()) {
numbers.push(number.toFloat());
}
while(!operators.isEmpty()) {
float second = numbers.pop();
float first = numbers.pop();
QChar op = operators.pop();
numbers.push(calculator(first, second, op));
}
float result = numbers.pop();
expression = QString::number(result, 'f', 7);
operateEdit->setText(expression);
}

int Calculator::precedence(QChar op)
{
if(op == '+' || op == '-') {
return 1;
} else if(op == '*' || op == '/') {
return 2;
}
return 0;
}

float Calculator::calculator(float a, float b, QChar op)
{
switch(op.toLatin1()) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
}
return 0;
}

主函数

main.cpp
1
2
3
4
5
6
7
8
9
#include <QApplication>//包含应用程序类
#include "calculator.h"//包含计算器类
int main(int argc, char *argv[])//main 函数的标准写法
{
QApplication app(argc, argv); //创建一个 QApplication 对象,管理应用程序的资源
Calculator mainwindow; //产生一个计算器对象
mainwindow.showMaximized();//显示计算器窗体(默认以最大化的形式显示)
return app.exec();//让程序进入消息循环,等待可能的菜单、工具条、鼠标等的输入,
}

编写嵌入式 Linux 设备驱动程序——LED驱动程序

Notes

  • insmod led_driver.ko 加载 LED 驱动模块
  • lsmod 查看目标机中已经加载的所有模块
  • cat /proc/devices 查看目标机中已经加载的所有设备,包括字符设备、块设备
  • rmmod led_driver.ko 卸载 LED 驱动模块
  • mknod /dev/XXX c #### x 创建 LED 设备文件节点
    • XXX 表示设备名,Linux 根据设备名创建设备目录;本实验中表示 led_light2 即指 LED 设备的第二个驱动程序,默认驱动程序为 led_light;
    • c 表示字符设备
    • #### 表示主设备号
    • x 表示次设备号
  • ls /dev 查看创建的所有设备
  • rmmod led_driver.ko 卸载 LED 驱动模块

Codes Modification

实验手册中给定的模块删除代码为:

1
2
3
4
5
6
7
8
9
10
/*模块的退出*/
static void __exit s5pv210_led_exit(void)
{
/* -------------------------------- */
device_destroy(led_dev_class,DEVICE_NODE);
/* ---------------------------------- */
class_destroy(led_dev_class);
cdev_del(cdev_p);
unregister_chrdev_region(num_dev,1);
}

根据设备文件节点是无法移除设备的,Linux 通过分配的设备号(主设备号、次设备号)来注册设备的,因此需要删除设备对应的设备号 num_dev,修改后的代码为:

1
2
3
4
5
6
7
8
9
10
/*模块的退出*/
static void __exit s5pv210_led_exit(void)
{
/* -------------------------------- */
device_destroy(led_dev_class,num_dev);
/* ---------------------------------- */
class_destroy(led_dev_class);
cdev_del(cdev_p);
unregister_chrdev_region(num_dev,1);
}

模块驱动程序

led_driver.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include<linux/init.h>
#include<linux/module.h>
#include<linux/sched.h>
#include<linux/kernel.h>
#include <asm/uaccess.h>
#include <plat/gpio-cfg.h>
#include <linux/gpio.h>

#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
/*定义设备目录*/
#define DEVICE_LIST "led_test2"
/*定义设备文件节点*/
#define DEVICE_NODE "led_light2"
#define LED1 0x01
#define LED2 0x02
#define LED3 0x04
#define LED4 0x08
/*定义申请设备号(主设备号+次设备号)的变量*/
static dev_t num_dev;
/*字符设备的变量定义*/
static struct cdev *cdev_p;

/*定义一个 class 类*/
static struct class *led_dev_class;
/*定义一个全局变量,表示 LED 灯的状态*/
static unsigned char led_status = 0;
/*设置 LED 灯的状态*/
static void set_led_status(unsigned char status)
{
/*表示 LED 灯的状态是否发生变化*/
unsigned char led_status_changed;
led_status_changed= led_status^(status & 0xF);
/*数据变化检测*/
led_status=(status & 0xF);
/*如果 4 个 LED 灯的状态发生了变化*/

if(led_status_changed!=0x00)
{
/*判断是否改变 LED1 灯的状态*/
if(led_status_changed&LED1)
{

if(led_status&LED1)
gpio_direction_output(S5PV210_GPH0(0),0);
else
gpio_direction_output(S5PV210_GPH0(0),1);
}
/*判断是否改变 LED2 灯的状态*/
if(led_status_changed&LED2)
{
if(led_status&LED2)
gpio_direction_output(S5PV210_GPH0(1),0);
else
gpio_direction_output(S5PV210_GPH0(1),1);
}

/*判断是否改变 LED3 灯的状态*/
if(led_status_changed&LED3)
{
if(led_status&LED3)
gpio_direction_output(S5PV210_GPH0(2),0);
else
gpio_direction_output(S5PV210_GPH0(2),1);
}
/*判断是否改变 LED4 灯的状态*/
if(led_status_changed&LED4)
{
if(led_status&LED4)
gpio_direction_output(S5PV210_GPH0(3),0);
else
gpio_direction_output(S5PV210_GPH0(3),1);
} } }

/*读取 LED 灯的状态*/
static ssize_t s5pv210_led_read(struct file * file,char * buf,size_t count,loff_t * f_ops)
{
/*从用户空间读取数据,获取 LED 灯的状态*/
copy_to_user(buf, (char *)&led_status, sizeof(unsigned char));
return sizeof(unsigned char);
}

/*定义实现 LED 灯的写操作*/
static ssize_t s5pv210_led_write (struct file * file,const char * buf, size_t count,loff_t * f_ops)
{
unsigned char status;
if(count==1)
{
/*向用户空间写数据,如果写失败,则返回错误*/
if(copy_from_user(&status, buf,sizeof(unsigned char)))
return -EFAULT;
set_led_status(status);
return sizeof(unsigned char);
}else
return -EFAULT;
}

/*打开 LED 设备*/
static ssize_t s5pv210_led_open(struct inode * inode,struct file * file)
{ /*增加管理此设备的 owner 模块的使用计数*/
try_module_get(THIS_MODULE);
return 0;
}
/*释放 LED 设备*/
static ssize_t s5pv210_led_release(struct inode * inode, struct file * file)
{
/*减少管理此设备的 owner 模块的使用计数*/
module_put(THIS_MODULE);
return 0;
}

/*定义具体的文件操作*/
static const struct file_operations s5pv210_led_ctrl_ops={
.owner = THIS_MODULE,
.open = s5pv210_led_open,
.read = s5pv210_led_read,
.write = s5pv210_led_write,
.release = s5pv210_led_release,
};
/*LED 灯的初始化和 LED 设备驱动的加载*/
static int s5pv210_led_ctrl_init(void)
{
int err;

struct device* temp=NULL;
unsigned int gpio;
/*GPIO 口的初始化 LED1,LED2,LED3,LED4,设置为输出*/
for(gpio=S5PV210_GPH0(0);gpio<S5PV210_GPH0(4);gpio++)
{
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));
}
/*动态注册 led_test 设备,num_dev 为动态分配出来的设备号(主设备号+次设备号)*/
err=alloc_chrdev_region(&num_dev,0,1,DEVICE_LIST);
if (err < 0) {
printk(KERN_ERR "LED: unable to get device name %d/n", err);
return err;
}
/*动态分配 cdev 内存空间*/
cdev_p = cdev_alloc();
cdev_p->ops = &s5pv210_led_ctrl_ops;

/*加载设备驱动*/
err=cdev_add(cdev_p,num_dev,1);
if(err){
printk(KERN_ERR "LED: unable to add the device %d/n", err);
return err;
}
/*在/sys/class 下创建 led_test 目录*/
led_dev_class=class_create(THIS_MODULE,DEVICE_LIST);
if(IS_ERR(led_dev_class))
{
err=PTR_ERR(led_dev_class);
goto unregister_cdev;
}

/*基于/sys/class/led_test 和/dev 下面创建 led_light 设备文件*/
temp=device_create(led_dev_class, NULL,num_dev, NULL, DEVICE_NODE);
if(IS_ERR(temp))
{
err=PTR_ERR(temp);
goto unregister_class;
}
return 0;

unregister_class:
class_destroy(led_dev_class);
unregister_cdev:
cdev_del(cdev_p);
return err;
}
/*模块的初始化*/
static int __init s5pv210_led_init(void)
{
int ret;
ret = s5pv210_led_ctrl_init();
if(ret)
{
printk(KERN_ERR "Apply: S5PV210_LED_init--Fail !!!/n");
return ret;
}
return 0;
}

/*模块的退出*/
static void __exit s5pv210_led_exit(void)
{
device_destroy(led_dev_class,num_dev);
class_destroy(led_dev_class);
cdev_del(cdev_p);
unregister_chrdev_region(num_dev,1);
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LED driver test");
module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);

Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
INSTALLDIR= /opt/tftp
ifneq ($(KERNELRELEASE),)
obj-m:=led_driver.o
else
KERNELDIR:=/opt/cross-compiler/kernel-embv210
PWD:=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *.order .*.cmd *.ko *.mod.c *.symvers
endif
install: led_driver.ko
mkdir -p $(INSTALLDIR)
cp --target-dir=$(INSTALLDIR) led_driver.ko

测试文件

led_test.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// LED test programme
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define DEVICE_NODE "/dev/led_light2"
int main(int argc,char **argv)
{
int fd,i,j;
unsigned char status;
unsigned char t;
/*打开设备节点*/
fd = open(DEVICE_NODE,O_RDWR);
if(fd == -1)
{
printf("open device %s error \n",DEVICE_NODE);
return -1;
}
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
//依次点亮 LED1..LED4
t=(unsigned char)((1<<j)&0x0F);
write(fd,&t,sizeof(t));
if(read(fd,&status,1)!=0)
{
printf("led status:%0x\n",status);
}
sleep(1);
} }
close(fd);
return 0;
}

Contributors

Zhihao Li, Computer Science and Technology, Xidian University

https://zhihaoli.top

References

付少峰. 2024年春, 嵌入式程序设计, 西安电子科技大学.

https://mooc1.chaoxing.com/mooc-ans/course/240785528.html

Author

Zhihao Li

Posted on

2024-06-12

Updated on

2024-12-24

Licensed under


Comments