基于S3C2440的Linux-3.6.6移植——按键驱动

基于S3C2440的Linux-3.6.6移植——按键驱动
基于S3C2440的Linux-3.6.6移植——按键驱动

基于S3C2440的Linux-3.6.6移植——按键驱动

分类:arm-linux驱动2013-04-13 20:54 2784人阅读评论(2) 收藏举报

对于s3c2440开发板上的几个按键功能,linux系统提供了很好的支持,只要把按键对应的IO端口配置好,按键就可以工作了。

针对我的开发板,为了配置按键的IO端口,需要修改arch/arm/mach-s3c24xx目录下的mach-zhaocj2440.c文件中的zhaocj2440_buttons结构为:

static struct gpio_keys_button zhaocj2440_buttons[] = {

{

.gpio = S3C2410_GPF(0), /* K4 */

.code = KEY_F1,

.desc = "Button 4",

.active_low = 1,

},

{

.gpio = S3C2410_GPF(1), /* K1 */

.code = KEY_F2,

.desc = "Button 1",

.active_low = 1,

},

{

.gpio = S3C2410_GPF(2), /* K3 */

.code = KEY_F3,

.desc = "Button 3",

.active_low = 1,

},

{

.gpio = S3C2410_GPF(4), /* K2*/

.code = KEY_POWER,

.desc = "Button 2",

.active_low = 1,

},

};

修改好后使用默认的menuconfig直接编译即可。把编译好的系统下载到开发板上,系统运行后,在dev目录有一个event0文件,这个就是按键设备。也可以通过下列命令查看一下设备信息:

[root@zhaocj /]#ls -l /proc/bus/input

-r--r--r-- 1 0 0 0 Jan 1 00:05 devices

-r--r--r-- 1 0 0 0 Jan 1 00:05 handlers

[root@zhaocj /]#cat /proc/bus/input/devices

I: Bus=0019 Vendor=0001 Product=0001Version=0100

N: Name="gpio-keys"

P: Phys=gpio-keys/input0

S:Sysfs=/devices/platform/gpio-keys/input/input0

U: Uniq=

H: Handlers=kbd event0

B: PROP=0

B: EV=3

B: KEY=100000 0 38000000 0

下面我们就来具体测试一下按键功能:

[root@zhaocj/]#hexdump /dev/event0

0000000 44e4 386d 3190000f 0001 003d 0001 0000

0000010 44e4 386d 31c0000f 0000 0000 0000 0000

0000020 44e5 386d 3b9a0003 0001 003d 0000 0000

0000030 44e5 386d 3bbd0003 0000 0000 0000 0000

0000040 44ea 386d a2750008 0001 003c 0001 0000

0000050 44ea 386d a2a30008 0000 0000 0000 0000

0000060 44ea 386d e426000b 0001 003c 0000 0000

0000070 44ea 386d e449000b 0000 0000 0000 0000

0000080 4525 386d 91190004 0001 0074 0001 0000

0000090 4525 386d 91490004 0000 0000 0000 0000

00000a0 4525 386d a78b0007 0001 0074 0000 0000

00000b0 4525 386d a7ad0007 0000 0000 0000 0000

00000c0 452a 386d f4af0005 0001 003b 0001 0000

00000d0 452a 386d f4df0005 0000 0000 0000 0000

00000e0 452a 386d ea3d0008 0001 003b 0000 0000

00000f0 452a 386d ea5e0008 0000 0000 0000 0000

上面是依次按下4个按键所得到的结果,每按一个键,会出现4行数据,这是因为每按一次键包括键的按下和键的抬起两个动作,而每个动作结束后还会有一个同步事件发生,因此会出现4行数据。其中每行的后几个数据的含义是基于input_event数据结构的:

struct input_event {

struct timeval time;

__u16 type;

__u16 code;

__s32 value;

};

即数据表示的是按键的类型、按键的代码和按键的值。

我们也可以编写一段应用程序来测试按键功能:

#include

#include

#include

int main(void)

{

intfd;

struct input_event ev_key;

fd= open("/dev/event0", 666);

if(fd < 0)

{

perror("open device buttons");

exit(1);

}

for(;;)

{

read(fd,&ev_key,sizeof(struct input_event));

printf("type:%d,code:%d,value:%d\n",ev_key.type,ev_key.code,ev_key.value);

}

close(fd);

return 0;

}

运行该程序,并依此按下4个键,得到的结果为:

type:1,code:61,value:1

type:0,code:0,value:0

type:1,code:61,value:0

type:0,code:0,value:0

type:1,code:60,value:1

type:0,code:0,value:0

type:1,code:60,value:0

type:0,code:0,value:0

type:1,code:116,value:1

type:0,code:0,value:0

type:1,code:116,value:0

type:0,code:0,value:0

type:1,code:59,value:1

type:0,code:0,value:0

type:1,code:59,value:0

type:0,code:0,value:0

下面就介绍一下linux是如何实现按键功能的。这里主要涉及到两方面的内容:linux的中断处理和输入子系统。

Linux中断分为两个部分:前半部和后半部。前半部是实际响应中断的函数,需要用request_irq注册;后半部是由前半部调度,并在一个更安全的时间来执行的函数,该函数就是具体负责执行中断的内容。前半部不允许被其他中断干扰,因此它的内容短小,而执行后半部时可以响应其他中断。这种机制的好处是可以迅速的响应中断。

Linux输入子系统包括三个层次:事件处理层(Event Handler)、核心层(Input Core)和驱动层(Input Driver)。

1.事件处理层负责与用户程序打交道,将核心层传来的事件报告给用户程序。

2.核心层是链接其他两个层之间的纽带与桥梁,向下提供驱动层的接口,向上提供事件处理层的接口。

3.驱动层负责操作具体的硬件设备,这层的代码是针对具体的驱动程序的,键盘、鼠标、触摸屏等字符设备驱动功能的实现工作主要就在这层。

输入子系统有三个核心结构体:input_dev,input_handle和input_handler。input_dev表示一个输入设备,包含输入设备的一些相关信息;input_handler表示对输入事件的具体处理,它为输入设备的功能实现了一个接口;input_handle是用来连接输入设备和输入事件。输入子系统主要的任务就是把这三个结构体连接在一起。

下面就按照输入子系统的三个层次,由底层向用户层的方向介绍按键是如何工作的。

在驱动层,Linux提供了一个通用的基于GPIO的按键驱动程序文件——gpio_keys.c(它是在drivers/input/keyboard目录下),我们的按键驱动也是调用该文件的。

首先进行按键的初始化:

static int __init gpio_keys_init(void)

{

//注册驱动

returnplatform_driver_register(&gpio_keys_device_driver);

}

gpio_keys_device_driver的内容为:

static struct platform_drivergpio_keys_device_driver = {

.probe = gpio_keys_probe,

.remove = __devexit_p(gpio_keys_remove),

.driver = {

.name = "gpio-keys", //与设备名一致,即与

Mach-zhaocj2440.c中的平台设备zhaocj2440_button_device中的.name一致

.owner = THIS_MODULE,

.pm = &gpio_keys_pm_ops,

.of_match_table= gpio_keys_of_match,

}

};

主要介绍gpio_keys_probe函数:

static int __devinit gpio_keys_probe(structplatform_device *pdev)

{

conststruct gpio_keys_platform_data *pdata = pdev->dev.platform_data;

structgpio_keys_drvdata *ddata;

structdevice *dev = &pdev->dev;

structgpio_keys_platform_data alt_pdata;

structinput_dev *input;

inti, error;

intwakeup = 0;

if(!pdata) {

//用另一种方法得到平台总线数据

error= gpio_keys_get_devtree_pdata(dev, &alt_pdata);

if(error)

return error;

pdata = &alt_pdata;

}

//为驱动数据ddata开辟一段内存空间,并清零

ddata= kzalloc(sizeof(struct gpio_keys_drvdata) +

pdata->nbuttons* sizeof(struct gpio_button_data),

GFP_KERNEL);

//为输入设备input开辟一段内存空间

input= input_allocate_device();

if(!ddata || !input) {

dev_err(dev,"failed to allocate state\n");

error= -ENOMEM;

gotofail1;

}

//为ddata幅值

ddata->input= input;

ddata->n_buttons= pdata->nbuttons;

ddata->enable= pdata->enable;

ddata->disable= pdata->disable;

mutex_init(&ddata->disable_lock);

//把驱动数据ddata以私有数据形式存放在平台总线设备pdev中,以备日后使用platform_set_drvdata(pdev, ddata);

//把驱动数据ddata以私有数据形式存放在输入设备input中,以备日后使用input_set_drvdata(input,ddata);

//为输入设备input幅值

input->name= pdata->name ? : pdev->name;

input->phys= "gpio-keys/input0";

input->dev.parent= &pdev->dev;

input->open= gpio_keys_open;

input->close= gpio_keys_close;

input->id.bustype= BUS_HOST;

input->id.vendor= 0x0001;

input->id.product= 0x0001;

input->id.version= 0x0100;

/*Enable auto repeat feature of Linux input subsystem */

//为输入设备input赋予自动重复特性,因为按键可以反复地按

if(pdata->rep)

__set_bit(EV_REP,input->evbit);

//为每个按键进行初始化,及设置属性

for (i = 0; i nbuttons; i++) {

conststruct gpio_keys_button *button = &pdata->buttons[i];

struct gpio_button_data *bdata =&ddata->data[i];

// gpio_keys_setup_key为关键函数,在后面进行分析

error = gpio_keys_setup_key(pdev,input, bdata, button);

if (error)

gotofail2;

if(button->wakeup)

wakeup= 1;

}

//在指定目录下生成sys属性文件,即在执行完下面语句后,会在

/sys/devices/platform/gpio-keys/目录下生成四个文件:disabled_keys、disabled_switches、switches、keys,前两个是可读可写的,后两个为只读。

error= sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);

if(error) {

dev_err(dev,"Unable to export keys/switches, error: %d\n",

error);

gotofail2;

}

//注册输入设备input,把输入设备加到输入设备链表中,并寻找合适的handler与input_handler配对

error= input_register_device(input);

if(error) {

dev_err(dev,"Unable to register input device, error: %d\n",

error);

gotofail3;

}

/*get current state of buttons that are connected to GPIOs */

//把当前的按键状态上报给系统,这个是在系统初始化,即上电的时候报告给系统的for (i = 0; i nbuttons; i++) {

struct gpio_button_data *bdata = &ddata->data[i];

if(gpio_is_valid(bdata->button->gpio))

gpio_keys_gpio_report_event(bdata);

}

//用于事件的同步,即告知系统设备已传递完一组完整的数据

input_sync(input);

device_init_wakeup(&pdev->dev,wakeup);

return0;

…………

}

下面介绍gpio_keys_probe函数中的主要函数gpio_keys_setup_key,它的作用是初始化按键:

static int __devinitgpio_keys_setup_key(struct platform_device *pdev,

struct input_dev *input,

struct gpio_button_data *bdata,

const struct gpio_keys_button *button)

{

constchar *desc = button->desc ? button->desc : "gpio_keys";

structdevice *dev = &pdev->dev;

irq_handler_tisr;

unsignedlong irqflags;

intirq, error;

bdata->input= input;

bdata->button= button;

spin_lock_init(&bdata->lock);

//判断按键所对应的gpio是否有效

if(gpio_is_valid(button->gpio)) {

//向系统申请gpio

error= gpio_request(button->gpio, desc);

if(error < 0) {

dev_err(dev,"Failed to request GPIO %d, error %d\n",

button->gpio,error);

returnerror;

}

//设置gpio的方向为输入

error= gpio_direction_input(button->gpio);

if(error < 0) {

dev_err(dev,

"Failedto configure direction for GPIO %d, error %d\n",

button->gpio,error);

gotofail;

}

//设置按键的去抖时间间隔

if(button->debounce_interval) {

error= gpio_set_debounce(button->gpio,

button->debounce_interval* 1000);

/*use timer if gpiolib doesn't provide debounce */

if(error < 0)

bdata->timer_debounce=

button->debounce_interval;

}

//提取gpio所对应的外部中断

irq= gpio_to_irq(button->gpio);

if(irq < 0) {

error= irq;

dev_err(dev,

"Unableto get irq number for GPIO %d, error %d\n",

button->gpio,error);

gotofail;

}

bdata->irq= irq;

//初始化工作队列,因为gpio按钮所使用的中断的后半部是基于工作队列方式的//也就是在bdata->work的工作队列中增加一个任务gpio_keys_gpio_work_func INIT_WORK(&bdata->work,gpio_keys_gpio_work_func);

//设置定时器,因为在按键去抖上用到了定时器

setup_timer(&bdata->timer,

gpio_keys_gpio_timer, (unsignedlong)bdata);

//gpio_keys_gpio_isr为按键中断函数

isr= gpio_keys_gpio_isr;

//设置外部中断上升沿或下降沿触发

irqflags= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;

}else {

if(!button->irq) {

dev_err(dev,"No IRQ specified\n");

return-EINVAL;

}

bdata->irq= button->irq;

if(button->type && button->type != EV_KEY) {

dev_err(dev,"Only EV_KEY allowed for IRQ buttons.\n");

return-EINVAL;

}

bdata->timer_debounce= button->debounce_interval;

setup_timer(&bdata->timer,

gpio_keys_irq_timer, (unsigned long)bdata);

isr= gpio_keys_irq_isr;

irqflags= 0;

}

//标识输入设备对哪些事件感兴趣,因为是按键,所以感兴趣的事件一定是EV_KEY input_set_capability(input,button->type ?: EV_KEY, button->code);

/*

* If platform has specified that the buttoncan be disabled,

* we don't want it to share the interruptline.

*/

if(!button->can_disable)

irqflags|= IRQF_SHARED;

//分配一条中断线,即当按键中断(bdata->irq)发生时,进入中断函数(isr,即gpio_keys_irq_isr函数内)。

error= request_any_context_irq(bdata->irq, isr, irqflags, desc, bdata);

if(error < 0) {

dev_err(dev,"Unable to claim irq %d; error %d\n",

bdata->irq,error);

gotofail;

}

return0;

fail:

if(gpio_is_valid(button->gpio))

gpio_free(button->gpio);

returnerror;

}

下面介绍按键中断函数:

static irqreturn_t gpio_keys_gpio_isr(intirq, void *dev_id)

structgpio_button_data *bdata = dev_id;

BUG_ON(irq!= bdata->irq);

if (bdata->timer_debounce)

mod_timer(&bdata->timer,

jiffies+ msecs_to_jiffies(bdata->timer_debounce));

else

schedule_work(&bdata->work);

returnIRQ_HANDLED;

}

该中断函数即为中断机制的前半部,它主要思想是在按键去抖间隔时间内不执行中断后半部分内容,只有在经过去抖间隔时间达到以后,才执行工作队列中的内容&bdata->work,即执行gpio_keys_gpio_work_func函数。

中断后半部函数gpio_keys_gpio_work_func调用的是gpio_keys_gpio_report_event函数,而gpio_keys_gpio_report_event函数调用的是input_event函数,该函数的功能是把输入事件上报给系统。input_event函数经过一次次传递和封装,最终到达用户空间而被用户所用。

下面介绍输入子系统的核心层文件input.c(它在drivers/input目录下),其中上文提到的input_event函数就在该文件内。

首先从初始化函数input_init开始介绍:

static int __init input_init(void)

{

interr;

//注册input类,这里就是生成了sys/class/input目录,在该目录下会看到本文要用到的链接文件event0。

err= class_register(&input_class);

if(err) {

pr_err("unableto register input_dev class\n");

returnerr;

}

//在proc目录下建立input子系统目录及交互文件,即/proc/bus/input目录下的devices 文件和handlers文件。

err= input_proc_init();

if(err)

gotofail1;

//注册一个主设备号为INPUT_MAJOR(13),次设备号为0~255,文件操作符为input_fops的字符设备。所有主设备号13的字符设备的操作最终都会转入到input_fops中。例如event0的主设备号为13,对其的操作会落在input_fops中

err= register_chrdev(INPUT_MAJOR, "input", &input_fops);

if(err) {

pr_err("unableto register char major %d", INPUT_MAJOR);

gotofail2;

}

return0;

fail2: input_proc_exit();

fail1: class_unregister(&input_class);

returnerr;

}

input_fops很简单,但它里面定义了一个重要input_open_file函数,它负责打开输入设备,我们来看看这个函数:

static int input_open_file(struct inode*inode, struct file *file)

{

structinput_handler *handler;

conststruct file_operations *old_fops, *new_fops = NULL;

interr;

err= mutex_lock_interruptible(&input_mutex);

if(err)

returnerr;

/*No load-on-demand here? */

//通过识别次设备号来获得当前的输入设备的handler

handler= input_table[iminor(inode) >> 5];

//得到该handler的文件操作指针file_operation

if(handler)

new_fops= fops_get(handler->fops);

mutex_unlock(&input_mutex);

/*

* That's _really_ odd. Usually NULL ->openmeans "nothing special",

* not "no device". Oh, well...

*/

if(!new_fops || !new_fops->open) {

fops_put(new_fops);

err= -ENODEV;

gotoout;

}

old_fops= file->f_op;

file->f_op= new_fops;

//用新获得的file_operation中的open来打开设备

err= new_fops->open(inode, file);

if(err) {

fops_put(file->f_op);

file->f_op= fops_get(old_fops);

}

fops_put(old_fops);

out:

returnerr;

}

从input_open_file函数的分析可以看出,input_fops只是输入子系统通用的file_operations,对于不同的输入子系统(如键盘、鼠标、触摸屏等),通过input_open_file函数会调用各自不同的file_operations。对于按键来说,它调用的是drivers/input目录下Evdev.c文件中的evdev_fops。

核心层就介绍这么多,下面介绍事件驱动层的内容。

事件处理层文件主要是用来支持输入设备并与用户空间交互,这部分代码一般不需要我们自己去编写,因为Linux内核已经自带有一些事件处理器,可以支持大部分输入设备,比如Evdev.c、mousedev.c、joydev.c等。对按键来说,用到的是Evdev.c文件(它在drivers/input 目录下)。

首先从Evdev.c文件的初始化函数evdev_init开始介绍:

static int __init evdev_init(void)

{

//注册evdev_handler

returninput_register_handler(&evdev_handler);

}

evdev_handler类型就是前面介绍过的三个重要结构体中的一个——input_handler,它的定义为:

staticstruct input_handler evdev_handler = {

.event = evdev_event,

.connect = evdev_connect,

.disconnect = evdev_disconnect,

.fops = &evdev_fops,

.minor = EVDEV_MINOR_BASE,

.name = "evdev",

.id_table = evdev_ids,

};

其中evdev_connect主要用来连接input_dev和input_handler;evdev_event是把input 事件发给所有的client。另外在该结构体内还定义了一个fops集合,它被赋值为evdev_fops 的指针。evdev_fops就是在介绍核心层input.c文件时,提到的当处理按键输入子系统时,file_operations所对应的就是evdev_fops。在这里,我们只分析该集合中的evdev_open 函数和evdev_read函数

evdev_open函数负责打开一个输入设备:

static int evdev_open(struct inode *inode,struct file *file)

{

structevdev *evdev;

structevdev_client *client;

//得到设备列表中的序号

inti = iminor(inode) - EVDEV_MINOR_BASE;

unsignedint bufsize;

interror;

if(i >= EVDEV_MINORS)

return-ENODEV;

error= mutex_lock_interruptible(&evdev_table_mutex);

if(error)

returnerror;

evdev= evdev_table[i]; //取出设备

if(evdev)

get_device(&evdev->dev); //增加计数

mutex_unlock(&evdev_table_mutex);

if(!evdev)

return-ENODEV;

bufsize= evdev_compute_buffer_size(evdev->handle.dev);

//分配并初始化client结构体

client= kzalloc(sizeof(struct evdev_client) +

bufsize* sizeof(struct input_event),

GFP_KERNEL);

if(!client) {

error= -ENOMEM;

gotoerr_put_evdev;

}

client->bufsize= bufsize;

spin_lock_init(&client->buffer_lock);

//使client与设备相关联,并把它挂接在链表中

client->evdev= evdev;

evdev_attach_client(evdev,client);

//evdev_open_device函数的作用是打开设备,当设备是第一次被打开时,则调用input_open_device函数。

error =evdev_open_device(evdev);

if(error)

gotoerr_free_client;

file->private_data= client;

nonseekable_open(inode,file);

return0;

err_free_client:

evdev_detach_client(evdev,client);

kfree(client);

err_put_evdev:

put_device(&evdev->dev);

returnerror;

}

evdev_read函数负责读取设备:

static ssize_t evdev_read(struct file*file, char __user *buffer,

size_tcount, loff_t *ppos)

{

structevdev_client *client = file->private_data;

structevdev *evdev = client->evdev;

structinput_event event;

size_tread = 0;

interror;

//对读取的数据大小进行判断

if(count != 0 && count < input_event_size())

return-EINVAL;

for(;;) {

//如果设备不存在,则退出

if(!evdev->exist)

return-ENODEV;

//如果缓存中没有数据可读而设备又存在,并且被设置为O_NONBLOCK方式,则退出

if(client->packet_head == client->tail &&

(file->f_flags & O_NONBLOCK))

return-EAGAIN;

/*

* count == 0 is special - no IO is done but wecheck

* for error conditions (see above).

*/

if(count == 0)

break;

while(read + input_event_size() <= count &&

evdev_fetch_next_event(client,&event)) {

//读取数据

if(input_event_to_user(buffer + read, &event))

return-EFAULT;

read+= input_event_size();

}

if(read)

break;

//等待缓存中是否有数据可读,或设备是否被移走

if(!(file->f_flags & O_NONBLOCK)) {

error= wait_event_interruptible(evdev->wait,

client->packet_head!= client->tail ||

!evdev->exist);

if(error)

returnerror;

}

}

至此,基于输入子系统的按键流程就介绍完了。

用单片机编写几种跑马灯

用单片机编写几种跑马灯 任务: 1、在电路板上实现跑马灯,一次1匹 2、在电路板上实现跑马灯,一次2匹 3、在电路板上实现4个二极管的同时闪烁 源程序1: /***********************************信息**************************************** **作者:刘海涛 **版本:初始版V1.0 **描叙:用电路板实现跑马灯。 **日期:2010年7月25日 *******************************************************************************/ /**********************************头文件*************************************** **头文件"reg52.h" *******************************************************************************/ /**********************************函数名*************************************** **函数名:延时函数delay() **输入:无 **输入:无 **宏定义:无 *******************************************************************************/ /**********************************宏定义*************************************** 宏定义:#define XBYTE ((unsigned char *)0x20000L) *******************************************************************************/ #include"reg52.h" delay(unsigned int dat) // 延时函数定义 { unsigned int i,j; for(i=0;i

此程序是用单片机的p1口接八个led灯作跑马灯试验

拆字程序 Org 0000h Mov A , 2000H Add A ,#F0H MOV 2001H ,A MOV A ,2000H ADD A , #0FH MOV 2002H , A MOV A , 2001H ADD A , 2002H END 拆分BCD 码 ? *************************************************************************** ;此程序是用单片机的p1口接八个led灯作跑马灯试验,八个led依次亮了又熄灭,形成漂亮;的跑马灯。本人已经试验成功。 ;单片机教程网https://www.360docs.net/doc/6f3109909.html, 原创

;该8路单片机跑马灯程序代码简单,电路也容易搭建,只需把led接在p1口上就可以了,希望大家能试验成功顺利的完成跑马灯报告 ;*************************************************************************** org 0000h loop0:cjne r0 ,#01h,rel,loop0 ;判断开关打开情况 ajmp start;跳转到程序开始 org 0030h;定义起始汇编地址 start: mov a,#0ffh ; clr c ; mov r2,#08h ;循环八次。 loop: rlc a ;带进位左移。 mov p1,a ;此时led灯开始有反映了。 call delay ;延时 djnz r2,loop ;循环(djnz条件判断) mov r2,#07h ; loop1: rrc a ;带进位右移 mov p1,a ;此时led灯开始有反映了。 call delay ; djnz r2,loop1 ;反复循环 jmp start ;回到程序的开头 delay: mov r3,#20 ;延时子程序 d1: mov r4,#20 d2: mov r5,#248 djnz r5,$ djnz r4,d2 ```````````````````````````````````````````````---------3路单片机跑马灯程序---------------------------------------

跑马灯控制

太原理工大学 单片机原理与应用技术课程实验报告 专业班级 学号 姓名 指导教师

跑马灯控制 一、实验目的 (1)进一步熟悉Keil和Proteus软件的操作,掌握快速复制元器件的操作方法; (2)掌握利用多路LED实现跑马灯控制的原理; (3)掌握循环移位、查表的编程方法。 二、实验硬件和软件 计算机1台,并安装Proteus软件和Kei C51软件。 三、实验任务 实现跑马灯控制效果,八个发光二极管L1-L8分别依次点亮,时间间隔 0.2S,点亮顺序为:L1→L2→…→L8→L7→L6→…→L1亮,重复循环。 四、实验电路及分析 实验电路如图所示,分析可知当P1.0-P1.7端口输出“0”时,发光管点亮;当P1.0-P1.7端口输出“1”时,发光管熄灭。 跑马灯仿真电路图

五、实验程序编写 1.跑马灯控制分析 根据跑马灯的控制要求,P1.7-P1.0输出状态如下表所示,P1口输出值从0XFE开始,循环左移7次后变为0X7F,然后循环右移7次变为0XFE,移位操作之间延时0.2S,循环左移的终止状态是循环右移的初始状态,注意该状态持续时间仍为0.2S,不是0.4S ,以上过程重复循环。 P1口输出状态表 2.C语言程序 #include #include void Delayms(unsigned int n) { unsigned int i, j; for(j=n; j>0;j--) for(i=112; i>0; i--); } int main( ) { unsigned char n;

unsigned char temp; while(1) { temp=0xfe; P1=temp; for(n=7;n>0;n--) { temp=_crol_(temp,1); Delayms(200); P1=temp; } for(n=7;n>0;n--) { temp=_cror_(temp,1); Delayms(200); P1=temp; } } } 3.程序流程图 六、实验步骤 1.利用Proteus软件绘制仿真电路图 (1)打开Proteus软件,File→New Project进入工程创建向导,选择项目文件存放路径,项目文件名为“实验2.pdsprj”。 (2)创建原理图(schematic),默认模板为default,可根据电路规模选择

跑马灯程序

//产生四种亮灯方式的跑马灯 module zmk(mclk,reset,type,ledout); input mclk,reset; input[1:0] type; output [5:0] ledout; reg [5:0] ledout; reg [24:0] count; reg [4:0] state; wire clk; //分频器 always@(posedge mclk) count=count+1; assign clk=count[23]; //当type变化的时候对state进行清零 reg[1:0] type_delay; wire type_change; always @ (posedge clk) type_delay <= type; assign type_change=(type!=type_delay)?1:0; always @ (posedge clk ) begin if(reset==0) //初始化语句begin ledout=6'b000000;state<=0;end else if(type_change)//对state进行清零 state<=4'b1; else if(type==2'b00) begin case(state) 4'b0001:ledout=6'b011111;//第一个灯亮 4'b0010:ledout=6'b101111;//第二个灯亮 4'b0011:ledout=6'b110111;//第三个灯亮 4'b0100:ledout=6'b111011;//第四个灯亮

4'b0101:ledout=6'b111101;//第五个灯亮 4'b0110:ledout=6'b111110;//第六个灯亮 4'b0111:ledout=6'b111101;//第五个灯亮 4'b1000:ledout=6'b111011;//第四个灯亮 4'b1001:ledout=6'b110111;//第三个灯亮 4'b1010:ledout=6'b101111;//第二个灯亮 default :ledout=6'b000000; endcase state=state+1; //计数器产生state的各种状态if(state==4'b1011)state=5'b00001; end else if(type==2'b01) begin case(state) 4'b0001:ledout=6'b101010; 4'b0010:ledout=6'b010101; default :ledout=6'b000000; endcase state=state+1; if(state==4'b0011)state=5'b00001; end else if(type==2'b10) begin case(state) 4'b0001:ledout=6'b110011; 4'b0010:ledout=6'b101101; 4'b0011:ledout=6'b011110; 4'b0100:ledout=6'b101101; default :ledout=6'b000000; endcase state=state+1; if(state==4'b0101)state=5'b00001; end else if(type==2'b11) begin case(state) 5'b00001:ledout=6'b111110;

基于linux的led驱动程序实现

基于linux的led驱动程序实现 一. 博创开发平台硬件LED的实现 博创开发平台设置了3个GPIO控制的LED和一个可直接产生外部硬件中断的按键,LED分别使用了S3C2410的GPC5,GPC6,GPC7三个GPIO,按键接到INT5中断。下面对S3C2410 GPIO的各个寄存器作出说明,用GPIO控制的LED就是通过操作GPIO的各个寄存器进行配置和操作的。S3C2410包含GPA 、GPB 、……、GPH 八个I/O端口。它们的寄存器是相似的:GPxCON 用于设置端口功能(00 表示输入、01表示输出、10 表示特殊功能、11 保留不用),GPxDAT 用于读/写数据,GPxUP 用于决定是否使用内部上拉电阻(某位为0 时,相应引脚无内部上拉;为1时,相应引脚使用内部上拉)。这里要稍微注意一点的地方是PORTA和其他几组端口的使用不太一样,这里不讨论A口,B到H组口的使用完全相同。以下是S3C2410手册上的数据[13]: 图1.1 S3C2410端口 GPC口有16个IO口,查datasheet《S3C2410》所用的地址为: 图1.2 C组GPIO的地址 即GPCCON 地址为0x56000020,GPCDAT地址为0x56000024,各位的设置具体见下图,则对应的GPCCON寄存器的位为:

图1.3 GPCCON寄存器相应的位 这里用到了5,6,7三个口,CON寄存器要完成对对应口的设置工作,将相应的口设置为输出状态,其他的口不用考虑,设置为输出的话就是0x15<<10,这样3个IO口就设置为了输出。下面就可以通过向DATA口写入低电平来点亮LED,GPCDAT的各位分布如下,每一个bit对应一个口。 图1.4 GPCDAT的位分布 GPCDAT有16位,我们这里要用到的就是5,6,7三位即将这3位设置为低电平点亮LED。具体使用情况见驱动的实现。 这三个LED的硬件原理图如下: 图1.5 GPIO控制的LED硬件原理图 二.通过GPIO控制的LED驱动程序 本驱动中没有用到内核提供的write_gpio宏,对硬件地址的操作完全自己实现,可分为以下几部分: ①模块的初始化和退出: int led_init(void)

S3C2440看门狗

看门狗定时器的主要作用是在程序因为干扰而跑飞后,能够使系统复位,不至于使系统永远的死下去。 它的原理与一般的定时器没有多大区别,就是先要设置好一段时间,当超过这段时间后,就从当前运行的程序中跳出进入中断处理程序中。但两者的主要差别是,一般的定时器中断是我们希望它发生的,因此我们不会在定时器中断发生前的那个时间段内干预它;而看门狗定时器中断是我们不希望它发生的,因此我们要想方设法地避免其发生。主要的方法就是在中断发生前,重新对看门狗定时器的寄存器进行赋值,使它的定时器重新开始计时。这种方法俗称喂狗,形象地比喻就是一条看门狗每隔一段时间(比如说一个小时)就会饿,所以就要叫唤,唯一使它不叫的方法就是给它喂食,那么下次叫唤的时间就是从当前喂食起的一个小时后。因此只要在上次喂食后的一个小时内再给它喂食,它就永远不会叫唤。 s3c2440的看门狗定时器不仅可以引起系统复位,还可以引起一般的中断,因此s3c2440的看门狗定时器可以当作一般的定时器使用。 s3c2440看门狗定时器的时钟频率的公式为: PCLK÷(Prescaler + 1)÷Division 其中Prescaler的取值范围为0~255,Division的取值为16,32,64和128。例如,当PCLK为50MHz时,设置Prescaler为249,Division为16,则看门狗定时器的时钟频率为12.5kHz。这两个参数由寄存器WTCON提供,除此以外,该寄存器还可以设置是否有效看门狗定时器的超时复位,是否有效看门狗定时器的超时中断等。看门狗定时器还有两个寄存器WTDAT和WTCNT,WTDAT用于确定超时期限,WTCNT为当前看门狗定时器的计数值,在第一次设置看门狗超时时间时,这两个寄存器都要被写入超时时间的初始值。当要启动超时中断时,还要设置必要的中断寄存器, 下面这个程序就是一个看门狗定时器的实例。该程序就是正常的跑马灯程序,但加了一个看门狗定时器。我们设置的看门狗定时器超时时,只会触发中断,不会引起系统复位。在中断函数内,蜂鸣器会响。我们设置看门狗定时器的超时期限为4秒,为了不让程序进入看门狗中断,必须在该期限内,往寄存器WTCNT内写数,迫使看门狗定时器重新开始计时。 #define _ISR_STARTADDRESS 0x33ffff00 #define pISR_WDT_AC97 (*(unsigned *)(_ISR_STARTADDRESS+0x44)) #define U32 unsigned int #define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control

基于labview跑马灯设计

选题分析: 随着人们生活环境的不断改善和美化,在许多场合可以看到彩色霓虹灯。 彩灯由于其丰富的灯光色彩,低廉的造价以及控制简单等特点而得到了广泛的应用,用彩灯来装饰已经成为一种时尚。 跑马灯是一种生活中比较常见的装饰,本文主要通过labview来设计了一个相对简单的对跑马灯的控制,实现了其有规律的亮灭,带来一定的观赏效果。 本文主要是实现了跑马灯的单个流水闪烁、 双路同步流水闪烁 、四路同步流水闪烁、全体同步闪烁,以此循环。本程序并控制闪烁的间隔时间,使其运行更具可观性。 方案设计: 本文主要设计了12个显示灯,并让其方形围成一圈。 运行效果: 单个流水闪烁:单个灯依次轮流闪烁 双路流水同步闪烁: 相对两灯同时依次轮流闪烁 四路同步流水闪烁:等间距四灯依次轮流闪烁 全体同步闪烁:全体灯同时闪烁 运行步骤: 单个流水闪烁→ 全体同步闪烁 → 双路流水同步闪烁

↑ ↓ 全体同步闪烁←四路同步流水闪烁←全体同步闪烁 以此循环。 运行控制: 直接点击labview运行按钮进行跑马灯演示。 开关:用于结束当前操作,控制其关断。当开始运行程序时也可通过关 断开关了结束程序的运行。 水平指针滑动杆:用于调节彩灯间的延时时间。通过其可调整灯闪烁的 快慢。 前面板的设计: 前面板主要由12个指示灯、一个开关及水平指针滑动杆构成。 水平指针滑动杆——用于调节彩灯间的延时时间。 指示灯——用以显示程序运行结果。 开关——用于结束当前操作。 对于前面板的设计相对简单,通过开关来控制其关断,水平指针滑动杆 来控制其延时时间,指示灯显示程序运行的结果,观看到跑马灯的演示 情况。

图1. 前面板 程序框图的设计: 设计思路: 本程序主要用到平铺式顺序结构和层叠式顺序结构顺序执行。 本程序用真假常量来控制灯亮与不亮。 本程序还用到了while循环和for循环,循环是用于达到闪烁和同步递进循环。 整个程序几乎每一帧都用到了延时,单位是毫秒,延时的目地是使本程序更具有可观性。

USB键盘驱动程序

/* * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $ * * Copyright (c) 1999-2001 Vojtech Pavlik * * USB HIDBP Keyboard support */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to <>, or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include #include #include #include #include #include #include /* * Version Information */ #define DRIVER_VERSION "" #define DRIVER_AUTHOR "Vojtech Pavlik <>" #define DRIVER_DESC "USB HID Boot Protocol keyboard driver" #define DRIVER_LICENSE "GPL"

嵌入式系统实训报告--走马灯

《嵌入式系统技术》 实训报告 1、实验目的 z熟悉A DS 开发环境调试环境。 z掌握简单的A RM 汇编指令的使用方法。 z掌握S3C2440A 的I/O 控制寄存器的配置。 z掌握A RM 汇编指令和C语言相互调用的方法 2、实验设备 z PC 机、ARM 仿真器、2440 实验箱、串口线。 3、实验内容 z熟悉A RM 开发环境的建立。 z使用A RM 汇编和C语言设置G PIO 口的相应寄存器。 z编写跑马灯程序。 4、实验原理 C 程序与汇编程序相互调用规则 为了使单独编译的C 语言程序和汇编程序之间能够相互调用,必须为子程序间的调用规定一定的规则。ATPCS ,即ARM ,Thumb 过程调用标准(ARM/Thumb Procedure Call Standard),是A RM 程序和T humb 程序中子程序调用的基本规则,它规定了一些子程序间调用的基本规则,如子程序调用过程中的寄存器的使用规则,堆栈的使用规则,参数的传递规则等。 下面结合实际介绍几种A TPCS 规则,如果读者想了解更多的规则,可以查看相关的书 籍。

1.基本A TPCS 基本A TPCS 规定了在子程序调用时的一些基本规则,包括下面3方面的内容: (1)各寄存器的使用规则及其相应的名称。 (2)数据栈的使用规则。 (3)参数传递的规则。 相对于其它类型的A TPCS,满足基本A TPCS 的程序的执行速度更快,所占用的内存更少。但是它不能提供以下的支持:ARM 程序和T humb 程序相互调用,数据以及代码的位置无关的支持,子程序的可重入性,数据栈检查的支持。 而派生的其他几种特定的ATPCS 就是在基本ATPCS 的基础上再添加其他的规则而形成的。其目的就是提供上述的功能。 2.寄存器的使用规则 寄存器的使用必须满足下面的规则: (1) 子程序间通过寄存器R0~R3 来传递参数。这时,寄存器R0~R3 可以记作A0~A3。被调用的子程序在返回前无需恢复寄存器R0~R3 的内容。 (2) 在子程序中,使用寄存器R4~Rll 来保存局部变量。这时,寄存器R4~R11 可以记作V1~V8。如果在子程序中使用到了寄存器V1~V8 中的某些寄存器,子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值;对于子程序中没有用到的寄存器则不必进行这些操作。在T humb 程序中,通常只能使用寄存器R4~R7 来保存局部变量。 (3) 寄存器R12 用作子程序间s cratch 寄存器,记作I P。在子程序间的连接代码段中常有这种使用规则。 (4) 寄存器R13 用作数据栈指针,记作S P。在子程序中寄存器R13 不能用作其他用途。寄存器S P 在进入子程序时的值和退出子程序时的值必须相等。 (5) 寄存器R14称为连接寄存器,记作LR。它用于保存子程序的返回地址。如果在子程序中保存了返回地址,寄存器R14则可以用作其他用途。 (6) 寄存器R15 是程序计数器,记作P C。它不能用作其他用途。 3.参数传递规则根据参数个数是否固定可以将子程序分为参数个数固定的 (nonvariadic)子程序和参数 个数可变的(variadic)子程序。这两种子程序的参数传递规则是不同 的。 (1)参数个数可变的子程序参数传递规则 对于参数个数可变的子程序,当参数不超过4个时,可以使用寄存器R0~R3 来传递参数;当参数超过4个时,还可以使用数据栈来传递参数。 在参数传递时,将所有参数看作是存放在连续的内存字单元中的字数据。然后,依次将各字数据传送到寄存器R0、R1、R2、R3 中,如果参数多于4个,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈。按照上面的规则,一个浮点数参数可以通过寄存器传递,也可以通过数据栈传递,也可能一半通过寄存器传递,另一半通过数据栈传递。 (2)参数个数固定的子程序参数传递规则对于参数个数固定的子程序,参数传递与 参数个数可变的子程序参数传递规则不同。 如果系统包含浮点运算的硬件部件,浮点参数将按照下面的规则传 递: ·各个浮点参数按顺序处理。 ·为每个浮点参数分配F P 寄存器。 ·分配的方法是,满足该浮点参数需要的且编号最小的一组连续的FP 寄存器。第

单片机跑马灯c语言程序

#include //头文件 #define uchar unsigned char //宏定义 sbit Beep = P3^4; // 蜂鸣器 uchar code led[]={ 0xff,0xfe,0xfd,0xf7,0xef,0xbf,0x7f,0x00 }; /**********延时子函数************/ void delay(unsigned int time) { unsigned int i,j; for(i=0;i0;j-=2) { P0 = led[j]; delay(500); } for(j=5;j>0;j-=2) { P0 = led[j]; delay(500); } } } /*****************计数器中断1***************/ void inttre() interrupt 3

{ unsigned int i,j; i=10; for(j=0;j<10;j++) { Beep=1; delay(i); Beep=0; delay(i); i+=60; } } /*******************外部中断1***************/ void inttrer() interrupt 2 { unsigned int i; for(i=1;i<7;i++) { P0 = led[i]; delay(500); } }

linux 设备输入子系统---源代码示例。自动捕获键盘鼠标等外设消息

Linux input 子系统详解与代码示例 李邦柱于杭州2014/01/09 Email:helpylee@https://www.360docs.net/doc/6f3109909.html, 由于linux的驱动模型增加了input层,导致几乎所有的底层驱动都把数据封装在event里上报给input子系统。由此看来,这种改变让kernel 更具有模块化,各个模块的耦合度更低了。下面我们一起来研究input 层^_^ 1.从用户层的角度看input(event事件) 了解linux的人一定会对/dev,/ sys, /proc这几个目录有所印象,这是从内核导出到用户层的接口(从这里几乎可以观览内核)。kernel为我们导出了input在用户态的接口,就是/dev/input/下的接口,所以我们只关注这个目录下的event*(event0/event1/……)字符设备。 那么这些event*是干什么用的?简单来说就是我们对计算机的输入(包括敲击键盘,移动鼠标等等操作)经过内核(底层驱动,input)处理最后就上报到这些event*里面了。 而这里event0,event1,..就是用来区分各个外设的,可以通过命令来查看外设具体和哪个event相关联:这个命令是:cat /proc/bus/input/devices 所以我们用此命令在linux系统查看外设信息。 2.在linux/input.h中有这些数据的结构: structinput_event { structtimeval time; //事件发生的时间 __u16 type; //事件类类型:按键和移动鼠标就是不同类型 __u16 code; __s32 value; //事件值:按键a和按键b就对应不同值 }; code: 事件的代码.如果事件的类型代码是EV_KEY,该代码code为设备键盘代码.代码植0~127为键盘上的按键代码,0x110~0x116 为鼠标上按键代码,其中0x110(BTN_ LEFT)为鼠标左键,0x111(BTN_RIGHT)为鼠标右键,0x112(BTN_ MIDDLE)为鼠标中键.其它代码含义请参

简易LED跑马灯设计

简易LED跑马灯设计 摘要 随着微电子技术的飞速发展,集成电路的集成度和性能提高、价格下降,特别是单片微处理器的出现,对现代社会的进步起到了巨大推进作用,也从各个方面改变了人们的生活,比如目前国内国外都大量使用的霓虹灯广告牌、交通显示信号灯,以及各种车辆、家用电器等普遍使用的指示信号灯,给人们的生活提供了便利。本文针对广告牌等显示器件中起到至关重要的作用的数字控制信号LED灯显示(跑马灯)进行一个简易的模拟设计。此实验项目中,使用8255芯片实现16位数码管显示,制作成一个简易的跑马灯,其中要运用386[pc]汇编语言编写相应代码,并且要针对8255的特点设计实验连线图,是对本科接口课程中学习到的软件以及硬件知识的一个综合运用,通过实际上机实验操作,编译设计不同的跑马灯效果。通过最后的综合实验调试,成功实现了简易跑马灯的效果显示,这是对跑马灯实际应用的一次有益接触,也是对该应用原理的一次初步实践。 【关键词】接口跑马灯 8255芯片 LED灯汇编语言

1 LED的应用领域以及LED跑马灯的研究意义 ?1.1 LED的应用领域 LED的应用领域非常广,包括通讯、消费性电子、汽车、照明、信号灯等,可大体区分为背光源、电子设备与照明、显示屏、汽车交通等五大领域。 ◆汽车交通:以汽车內装使用包括了仪表板、音箱等指示灯,及汽车外部(第三刹车灯、左右尾灯、方向灯等),另外还包括交通标志灯。 ◆背光源:主要是手机背光光源方面,是SMD型产品应用的最大市场。 ◆显示屏: LED显示屏作为一种新兴的显示媒体,随着大规模集成电路和计算机技术的高速发展,得到了飞速发展,它与传统的显示媒体―多彩霓虹灯、象素管电视墙、四色磁翻板相比较,以其亮度高、动态影像显示效果好、故障低、能耗少、使用寿命长、显示内容多样、显示方式丰富、性能价格比高等优势,已广泛应用于各行各业。 ◆电子设备与照明:LED以其功耗低,体积小,寿命长的特点,已成为各种电子设备指示灯的首选,目前几乎所有的电子设备都有LED的身影。 ?1.2 LED跑马灯的研究意义 本文主要是对LED显示屏应用的一个初步研究,跑马灯是对LED显示屏功能的基础模拟,通过对跑马灯形式的LED显示进行实验模拟,可以对LED的大型应用奠定基础,是将来完成完整LED效果显示设计的初级实践。LED跑马灯设计正好和本科接口基础设计课程相衔接,运用到了课程中学习到的相关接口知识,是对该课程知识的一个综合运用,有助于加强基础知识的掌握,提升个人实践能力。 2 相关实验芯片及原理的介绍 本实验需要器材:8255芯片一块,PC机一台,TD-PIT/TD-PIT-B实验箱一台。 ?2.1 LED灯管的发光以及驱动原理 图2.1 发光二极管结构图 LED灯管LED(Light Emitting Diode,图2.1),发光二极管,是一种固态的半导体器件,它可以直接把电转化为光。LED的心脏是一个半导体的晶片,晶片的一端附在一个支架上,一端是负极,另一端连接电源的正极,使整个晶片被环氧树脂封装起来。半导体晶片由三部分组成,一部分是P型半导体,在它里面空穴占主导地位,另一端是N型半导体,在这边主要是电子,中间通常是1至5个周期的量子阱。当电流通过导线作用于这个晶片的时候,电子和空穴就会被推向量子阱,在量子阱内电子跟空穴复合,然后就会以光子的形式发出能量,这就是LED发光的原理。而光的波长也就是光的颜色,是由形成P-N结的材料决定的。 在接口试验中通常会用到单色LED灯作信号显示,给LED灯输入数字信号,LED灯会根据信号的不同而显示亮或者灭。

跑马灯控制电路设计

HDL数字系统课程设计报告书 目录 一、设计目的 (2) 二、设计思路 (2) 三、设计过程 (2) 3.1、系统方案论证 (2) 3.2、程序代码设计 (3) 四、系统调试与结果 (5) 五、主要元器件与设备 (9) 六、课程设计体会与建议 (9) 6.1、设计体会 (9) 6.2、设计建议 (10) 七、参考文献 (10)

论文摘要: 共16个LED灯,连成一排,实现几种灯的组合显示。通过这次对跑马灯控制电路的设计与制作,了解了设计电路的程序,也了解了关于跑马灯工作的基本原理与设计理念,首先要将一个程序分成几个模块,分别调试每一个模块,当每个模块均能正常工作时,其次再将其都组合在一起再次调试与仿真,最后将程序下载到Altera公司ACEXTM系列EPEK30QC208-2芯片,观察程序是否能控制硬件的实现。此外,本实验也可通过EDA软件Quartus6.0和modelSim SE 6.0实现。 关键词: HDL 数字系统跑马灯设计

一、设计目的 1、熟悉Verilog HDL程序编程。 2、掌握Altera公司ACEXTM系列EPEK30QC208-2芯片的使用方法。 3、熟悉Quartus II 6.0和Modesim SE 6.0软件的使用。 4、了解16个数码管的显示原理和方法。 二、设计思路 1、编写跑马灯设计程序。 2、定义LED灯引脚分配。 3、设计状态控制。 4、下载到EPEK30QC208-2芯片上显示。 三、设计过程 3.1、系统方案论证 16位LED跑马灯设计框图如图1所示:

图1 LED跑马灯设计框图 3.2、程序代码设计 module paomadeng(rst,clk,sel,led); //端口定义,参数列表 input rst,clk; //rst复位,clk为4Hz的时钟信号input[1:0] sel; //sel 状态选择端口 output[15:0] led; //led 跑马灯显示 reg[15:0] led; reg[15:0] led_r,led_r1; reg cnt1,dir; //cnt1控制状态2 led灯的亮次数 reg[3:0] cnt2; //cnt2控制状态2 led灯的亮次数 reg[2:0] cnt3; //cnt3控制状态2 led灯的亮次数 always@(posedge clk) begin if(rst) begin cnt1<=0;cnt2<=0;cnt3<=0;dir<=0;end else case(sel) // LED按奇数,偶数依次显示 2'b00: begin led_r=16'b0101010101010101; if(cnt1==0)led<=led_r; else led<=led_r<<1; cnt1<=cnt1+1; end // LED顺序依次显示,顺序依次熄灭 2'b01: begin if(!dir) begin if(cnt2==0) begin led_r=16'b0000000000000001;led<=led_r;end else begin led<=(led<<1)+led_r;end if(cnt2==15) begin dir<=~dir;end

基于S3C2440的项目实训

合肥学院 嵌入式系统设计实验报告 (20 13- 2014第2学期) 专业:______11自动化卓越班_________ 实训项目:基于S3C2440的项目实训 实训时间:___2014___年__6___月_27_ 日实训成员:__ _____ _ ___ __ 指导老师:___________干开峰__ ________ 电子信息与电气工程系 2014年4月制

一、实训目的 1、掌握嵌入式系统设计的基本方法。 2、熟悉嵌入式系统设计流程。 3、能够按照需求完成嵌入式系统总体设计。 二、实训内容 本项目实训要求完成“数据采集系统”,从前端数据采集到后端触摸屏显示控制,包括硬件电路的连接、bootloader 和内核移植、根文件系统建立、设备驱动的编写以及 QT编程实现。 三、实训设备 硬件:micro2440 开发板、AD7705采集板 软件:Linux操作系统 四、实训设计方案 4.1 项目功能需求分析 1、功能需求 (1)基于SPI通信,完成AD7705和micro2440开发板硬件连接。 (2)完成基于micro2440的bootloader、内核移植和根文件系统建立。 (3)完成基于SPI协议的AD7705驱动程序设计。 (4)基于QT编程实现数据采集和显示功能。 2、性能需求 主控制器能够对AD7705传来的信号实现数据采集和显示功能。 4.2 方案设计 4.2.1 项目的总体设计 系统主要由电压信号、A/D转换器、S3C2440 控制器和LCD 控制器组成,结构图如图1所示。其中,电压信号可以是压力传感器、温度传感器等输出信号;A/D转换器是数字化的关键部件,决定了整个系统的精度;主控制器由S3C2440 构成;带触摸屏的LCD 控制器可以实现系统参数设置和实时显示最新状态。 图1 系统结构图

基于单片机的跑马灯课程设计(1)

电气及自动化课程设计报告题目:基于单片机的跑马灯课程设计 课程:单片机原理及其应用 学生姓名:刘昊杰 学生学号: 1414050319 年级: 2014级 专业:电气工程及其自动化 班级: 3班 指导教师:缪玉桂 机械与电气工程学院制 2016年11月

目录 1 设计的任务与要求 (1) 1.1 课程设计的任务 (1) 1.2课程设计的要求 (1) 2 芯片分析和设计概述 (2) 2.1 AT89C51芯片分析 (2) 3 设计概述 (5) 4 硬件电路设计 (6) 5 程序部分设计 (7) 6 实验总结 (12) 7 参考文献 (12)

基于单片机的跑马灯课程设计 学生:刘昊杰 指导教师:缪玉桂 机械与电气工程学院电气工程及其自动化专业 1 设计的任务与要求 1.1 课程设计的任务 (1)掌握单片机的接口技术及相关外围芯片的外特性,控制方法。 (2)通过课程设计,掌握以单片机核心的电路设计的基本方法和技术。 (3)通过实际程序设计和调试,逐步掌握模块化程序设计方法和调试技术。 (4)与模拟电子技术,数字电子技术等课程相结合,进一步熟悉和掌握单片机的结构及工作原理,为以后所学的后续课程打下良好的基础。 (5)通过完成一个包括电路设计和程序开发的完整过程,使学生了解开发一单片机应用系统的全过程,为今后从事相应打下基础。 1.2课程设计的要求 该设计使用AT89C51芯片作为控制芯片,利用P1口连接8个发光二极管,通过I/O 的值控制“跑马灯”的亮灭,以达到显示效果。开始时所有灯全亮,按下按键S时开始跑马灯,再按下按键S时停止,再按下S时继续,并要求有多种亮暗组合。

LINUX系统必备程序安装步骤

1.红帽企业版5获得root权限方法: su root

2. 红帽企业版5 启动samba的方法: a.在安装LINUX的过程中将所有选项都选择上,这样可以确保samba等软件 都已经安装好。 b. 修改/etc/samba/smb.conf,添加: [root] comment = Root Directories browseable = yes writeable = yes path = / valid users = smb(用户名) c.添加用户: RHEL5: Useradd smb //添加smb系统用户 Smbpasswd -a smb //修改密码 d.重新启动samba: /etc/init.d/smb restart e.windows访问LINUX 访问LINUX的IP地址,输入用户名smb及密码就可以正常访问linux了

3.建立tftp服务器: a.在安装LINUX的过程中将所有选项都选择上,这样可以确保tftp等软件都 已经安装好。 b.建立TFTP主工作目录: mkdir /tftpboot c.修改配置文件 vi /etc/xinet d.d/tftp修改内容如下: d.重新启动tftp /etc/init.d/xinetd restart e.确认TFTP启动的是否成功:netstat –a | grep tftp

4.NFS a.配置vi /etc/exports b.重新启动NFS服务器:/etc/init.d/nfs restart

5.升级安装LINUX内核: a.解压缩内核代码tar –xvzf linux-2.6.32.27 b.拷贝config 文件将目录boot下的原先LINUX内核的CONFIG文件复制到 新内核的根目录下名字为.config c.make menuconfig d.make bzImage e.make modules f. make modules_install g.制作init ramdisk: h.内核安装: i.升级内核后重新启动机器所遇到的问题解决办法: 方法:编译时修改.config文件中的“CONFIG_SYSFS_DEPRECATED_V2”,默认该选项为not set,被注释掉的,将其改为y。即修改为 “CONFIG_SYSFS_DEPRECATED_V2=y”,修改后,再编译,重启即正常了。

ARMS3C2440A讲解

以下程序在Keil4中建立项目,芯片选S3C 2410A 无论是S3C2410A还是S3C2440A,其IO口B都是11位二进制数,xxx xxxx xxxx,现在控制第5、6、7、8为做输出点亮LED灯(共阳极,输出0点亮),即xx8 765x xxxx, GPBCON equ 0x56000010 GPBDAT equ 0x56000014 GPBUP equ 0x56000018 xport xmain area Init,code,readonly entry export xmain ldr r0,=GPBCON ldr r1,[r0] bic r1,#0x3fC00 ;r1=xx00 0000 00xx xxxx xxxx orr r1,#0x15400 ;r1=xx01 0101 01xx xxxx xxxx str r1,[r0] ;r1传给GPBCON设置8765位为输出 ldr r0,=GPBUP ldr r1,[r0] orr r1,#0x1e0 ;r1=xx1 111x xxxx str r1,[r0] ;开B口第8、7、6、5位上拉电阻 ldr r0,=GPBDAT ldr r2,[r0] ;把B口最初状态保存在R2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LOOP dr r1,[r2] orr r1,#0x1c0 str r1,[r0] bl delay ;BL跳转时将PC+4值自动保存在R14即LR中,也就是将程序的下一个语句地址保存在lr中在跳;转后执行mov pc,lr相当于返回,这样BL相当于调用子程序,pc=lr相当于子程序返回 ;;;;;;;;;;;;;;;;;; dr r1,[r2] orr r1,#0x1a0 str r1,[r0] bl delay ;;;;;;;;;;;;;;;;;;;;; ldr r1,[r2] orr r1,#0x160

相关文档
最新文档