首先来说一下这个linux中的定时器,这个定时器会在特定的时间去调用特定的函数已达到实现某操作的目的,和我们的定时闹钟差不多
下面来说下具体的参数代表的含义:
jiffies:全局变量,用来记录自系统启动以来(也就是开发板上电以来)产生的节拍总数。启动时内核将该变量初始化为0;
此后每次时钟中断处理程序增加该变量的值。每一秒钟中断次数HZ,jiffies一秒内增加HZ。系统运行时间 = jiffie/HZ. ---------->>(秒)
jiffies用途:计算流逝时间和时间管理
其中HZ是一个常数,和平台无关,可以自己配置,值为50~1200,X86下是默认1000
首先我们要把定时器初始化和添加到内核,用这两个函数
init_timer(&my_timer);//初始化内核定时器
add_timer(&my_timer);//将这个节点添加到定时器的链表当中
这两个函数里面的参数my_timer都是struct timer_list类型的,所以我们要创建一个定时器的链表
struct timer_list my_timer;
这个结构体的定义如下:
struct timer_list {
/*
* All fields that change during normal runtime grouped to the
* same cacheline
*/
//定时器可以作为链表的一个节点
struct list_head entry;
//定时值基于jiffies
unsigned long expires;
//定时器内部值
struct tvec_base *base;
//定时器处理函数
void (*function)(unsigned long);
//定时器处理函数参数
unsigned long data;
int slack;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
我们定义了这个结构体,在此之后我们可以操纵这个结构体实现具体操作
接下来是实现在特定时间要去做的事,可以来亮灯,中断或者其他事,我们这里用蜂鸣器来操作
先来看看开发板的蜂鸣器的原理图:
(1)蜂鸣器接口位于电路板的底板,看电路图可知道是高电平有效。
(2)相对应的找到核心板的接口。由此可知,我们的蜂鸣器是GPD0_0
接下来找数据手册,找到对应的寄存器,然后配置它就可以了。
2、查数据手册,找到相关的寄存器,并配置
(1)找到GPD0CON,地址是0x114000A0,我们需要配置GPD0CON(0)为输出状态。也就是写0x1这个值到这个寄存器。
(2)找到GPD0DAT这个寄存器,用于配置蜂鸣器的高低电平,物理地址是0x114000A4,刚好与上一个差4个字节的偏移
我们只要对这个寄存器写1和写0,那么蜂鸣器就可以叫起来了
这里我们用系统提供给我们的函数来给寄存器赋值会简单的很多很多
EXYNOS4_GPD0(0);// 获取寄存器地址
gpio_set_value(EXYNOS4_GPD0(0),0);//给获取到地址的寄存器赋值为0
这种方法小白化,可以发发减去对寄存器操作时候位移,逻辑运算和赋值过程中出现的错误,推荐使用这种方法,当然裸机开发还是老老实实位移赋值吧!!
蜂鸣器的实现函数如下:
static void Bell_init()
{
gpio_request(buzzer_gpio,buzzer_name);//申请gpio
s3c_gpio_cfgpin(buzzer_gpio,S3C_GPIO_OUTPUT);//调用板级的gpio函数,将寄存器配置成输出状态,相当于给对应为赋值为0
gpio_set_value(buzzer_gpio,0);//初始化的只为0,赋值为1代表响,通过高低电平控制
}
完整的驱动代码如下:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/timer.h> /*timer*/
#include <asm/uaccess.h> /*jiffies*/
#include <linux/delay.h>
#define buzzer_gpio EXYNOS4_GPD0(0)
#define buzzer_name "bell"
struct timer_list my_timer;
static void Bell_init()
{
gpio_request(buzzer_gpio,buzzer_name);//申请gpio
s3c_gpio_cfgpin(buzzer_gpio,S3C_GPIO_OUTPUT);//调用板级的gpio函数,将寄存器配置成输出状态,相当于给对应为赋值为0
gpio_set_value(buzzer_gpio,0);//初始化的只为0,赋值为1代表响,通过高低电平控制
}
void my_fun(unsigned int value)
{
gpio_set_value(buzzer_gpio,1);//这个时候蜂鸣器会响
mdelay(5000);//响五秒钟就关闭
gpio_set_value(buzzer_gpio,0);//这个时候蜂鸣器会响
}
static int __init myclock_init (void)
{
Bell_init();//初始化bell,这个函数是让蜂鸣器响的
init_timer(&my_timer);//初始化内核定时器
my_timer.data=1;//给执行的函数传参
my_timer.expires=jiffies+(2 * HZ);//现在的jiffies值在加上5秒钟
my_timer.function=my_fun;//到了特定时间要去执行的函数
add_timer(&my_timer);//将这个节点添加到定时器的链表当中
return 0;
}
static void __exit myclock_exit (void)
{
del_timer(&my_timer);
}
module_init(myclock_init);
module_exit(myclock_exit);
MODULE_LICENSE("GPL");