linux系统下的s3c6410定时器驱动+温度湿度传感器驱动程序源代码
#include <linux/module.h>#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <plat/regs-timer.h>
#include <mach/regs-irq.h>
#include <asm/mach/time.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-a.h>
#include <mach/gpio-bank-b.h>
#include <mach/gpio-bank-c.h>
#include <mach/gpio-bank-d.h>
#include <mach/gpio-bank-e.h>
#include <mach/gpio-bank-f.h>
#include <mach/gpio-bank-g.h>
#include <mach/gpio-bank-h.h>
#include <mach/gpio-bank-i.h>
#include <mach/gpio-bank-j.h>
#include <mach/gpio-bank-k.h>
#include <mach/gpio-bank-m.h>
#include <mach/gpio-bank-n.h>
#include <mach/gpio-bank-o.h>
#include <mach/gpio-bank-p.h>
#include <mach/gpio-bank-q.h>
#define DEVICE_NAME "timer0"
//the sensor var
unsigned tmp_sensor;
unsigned int shidu=0;
unsigned int temperature=0;
int check=0;
#defineSensor_SDA1_HIGHs3c6410_ioSetData(C,0,1) //GPC0 high
#defineSensor_SDA1_LOW s3c6410_ioSetData(C,0,0)
#defineSensor_SDA1_IN s3c6410_ioSetDir(C,0,0)
#defineGET_Sensor_SDA1 tmp_sensor=readl(S3C64XX_GPCDAT);tmp_sensor=temp_sensor&0x01
unsigned char Sensor_Data={0};
unsigned char Sensor_Check=0; //校验和
unsigned char Sensor_AnswerFlag=0;//收到起始标志位
unsigned char Sensor_ErrorFlag=0; //读取传感器错误标志
unsigned intSys_CNT=0;
externint s3c6410_ioSetData(char IO_id ,unsigned char IO_number,unsigned char status );
externint s3c6410_ioSetDir(char IO_id ,unsigned char IO_number,unsigned char status );
unsigned int count_timer0=0;
unsigned int tmp_timer0=0;
unsigned int sensor_time=0;
//传感器函数部分
/********************************************\
|* 功能: 读传感器发送单个字节 *|
\********************************************/
unsigned char Read_SensorData()
{
unsigned char i,cnt;
unsigned char buffer,tmp;
buffer = 0;
for(i=0;i<8;i++)
{
cnt=0;
while(!(GET_Sensor_SDA1,temp_sensor)) //检测上次低电平是否结束 一旦有高电平,延时30us后看一下还是否是高电平,若还是则是1若不是则是0
{
if(++cnt >= 39) //>50us循环一次刚好是64个clk 1.28us
{
break;
}
}
//延时Min=26us Max50us 跳过数据"0" 的高电平
udelay(30); //延时30us
//判断传感器发送数据位
tmp =0;
if((GET_Sensor_SDA1,temp_sensor))
{
tmp = 1;
}
cnt =0;
while((GET_Sensor_SDA1,temp_sensor)) //等待高电平 结束
{
if(++cnt >= 20)//>35us
{
break;
}
}
buffer <<=1;
buffer |= tmp;
}
return buffer;
}
/********************************************\
|* 功能: 读传感器
返回值:0错误 1正确
\********************************************/
unsigned char Read_Sensor()
{
unsigned char i;
//主机拉低(Min=800USMax=20Ms)
Sensor_SDA1_LOW;//拉低
udelay(2000); //延时2Ms
//释放总线 延时(Min=30us Max=50us) 拉高30us
Sensor_SDA1_HIGH;
udelay(38); // 拉高 30到40us
//主机设为输入 判断传感器响应信号
Sensor_SDA1_IN;//主机设置为输入
Sensor_AnswerFlag = 0;// 传感器响应标志
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(GET_Sensor_SDA1==0)
{
Sensor_AnswerFlag = 1;//收到起始信号
Sys_CNT = 0;
//判断从机是否发出 80us 的低电平响应信号是否结束
while(!(GET_Sensor_SDA1,temp_sensor))//如果为0,则一直在这里循环 一旦有高电平则执行下边的语句
{
if(++Sys_CNT>60) //防止进入死循环>80us
{
Sensor_ErrorFlag = 1;
return 0;
}
}
Sys_CNT = 0;
//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
while((GET_Sensor_SDA1,temp_sensor))
{
if(++Sys_CNT>60) //防止进入死循环>80us实际是50us
{
Sensor_ErrorFlag = 1;
return 0;
}
}
// 数据接收 传感器共发送40位数据
// 即5个字节 高位先送5个字节分别为湿度高位 湿度低位 温度高位 温度低位 校验和
// 校验和为:湿度高位+湿度低位+温度高位+温度低位
for(i=0;i<5;i++)
{
Sensor_Data = Read_SensorData();
}
}
else
{
Sensor_AnswerFlag = 0; // 未收到传感器响应
}
return 1;
}
static irqreturn_t Mytimer0_Interupt(int irq,void *dev_id)
{
if(irq!=IRQ_TIMER0)
{
printk(KERN_NOTICE "bad irq % d in timer0 \n", irq);
return -1;
}
//传感器部分 要求至少2.4秒一次
if(sensor_time==120)
{
sensor_time=0;
Read_Sensor();
check=Sensor_Data+Sensor_Data+Sensor_Data+Sensor_Data;
if(Sensor_Data==check)
{
temperature = (float)(Sensor_Data*256+Sensor_Data);
shidu=(float)(Sensor_Data*256+Sensor_Data);
}
else
{
temperature=0;
shidu=0;
}
printk(KERN_NOTICE "The temperature is:%-4.1f\n",temperature);
printk(KERN_NOTICE "The shidu is:%-4.1f\n",shidu);
}
//计数部分
count_timer0++;
if(count_timer0==50)
{
printk(KERN_NOTICE "timer_irq is ok:%d \n", count_timer0);
count_timer0=0;
tmp_timer0++;
if(tmp_timer0>=2)
tmp_timer0=0;
if(tmp_timer0==0)
s3c6410_ioSetData('M',0,0);//亮
else
s3c6410_ioSetData('M',0,1);//灭
}
return IRQ_HANDLED;
// return 0;
}
//cmd:0:stop,1:start
//arg: reserved
static long s3c6410_Timer0(struct file *filp, unsigned int cmd, unsigned long arg)
{
//printk(KERN_NOTICE "timer0 is ok 1\n");
//printk(KERN_ALERT "timer0 is ok 2\n");
unsigned long tcfg0;//寄存器0x00
unsigned long tcfg1;//寄存器0x04
unsigned long tcon;//控制寄存器 0x08
unsigned int tcnt;//计数值
unsigned long tint;//中断寄存器 0x44
s3c6410_ioSetDir('M',0,1);
tcon = __raw_readl(S3C_TCON);
tint = __raw_readl(S3C64XX_TINT_CSTAT);
tcfg1 = __raw_readl(S3C_TCFG1);
tcfg0 = __raw_readl(S3C_TCFG0);
if (cmd == 0)
{
tcon&=~(1<<0);
tint&=~(1<<0);
__raw_writel(tcon, S3C_TCON);
__raw_writel(tint, S3C64XX_TINT_CSTAT);
}
else
{
//设置分频比
tcfg0 &= ~S3C_TCFG_PRESCALER0_MASK;
tcfg0 |= (66-1);
tcfg1&=~S3C_TCFG1_MUX0_MASK;
tcfg1|=S3C_TCFG1_MUX0_DIV4;
__raw_writel(tcfg0, S3C_TCFG0);
__raw_writel(tcfg1, S3C_TCFG1);
tcnt=5000; //0.02s
__raw_writel(tcnt, S3C_TCNTB(0));
__raw_writel(tcnt/2, S3C_TCMPB(0));
tint|=1<<0;
__raw_writel(tint, S3C64XX_TINT_CSTAT);
tcon&=~(0x0f<<0);
tcon|=0x0b;
__raw_writel(tcon, S3C_TCON);
tcon &= ~0x2<<0; //clear manual update bit
__raw_writel(tcon, S3C_TCON);
}
return 0;
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = s3c6410_Timer0,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
int ret1;
ret1 = misc_register(&misc);
ret=request_irq(IRQ_TIMER0,Mytimer0_Interupt,IRQ_TYPE_LEVEL_HIGH,DEVICE_NAME,NULL);
if(ret<0)
{printk(KERN_NOTICE "Register IOPWM failed!\n");
return ret;
}
printk (KERN_NOTICE "timer0 interrupt is ok! \n");
return ret1;
}
static void __exit dev_exit(void)
{
free_irq(IRQ_TIMER0,NULL);
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jack Sun");
MODULE_DESCRIPTION("S3C6410 Timer0 Driver");
没有示波器,传感器部分未成功,定时器可以工作了
你看看是不是你的驱动和系统里面的驱动同时调用的同一个管脚 飞凌-unix 发表于 2013-10-12 16:27 static/image/common/back.gif
你看看是不是你的驱动和系统里面的驱动同时调用的同一个管脚
哦哦~系统里的驱动?是什么意思,我用io口模拟I2C协议,对传感器进行控制,您的意思是系统里的驱动将io的时序搞乱了吗? 恨水长东 发表于 2014-4-23 16:22 static/image/common/back.gif
楼主求单独的定时器程序和测试程序啊!!!求求你了
私信楼主,他不一定看帖子 恨水长东 发表于 2014-4-24 07:37 static/image/common/back.gif
谢谢委员长,我想知道关于定时器寄存器的头文件是哪一个呢
我在你的另一个帖子中回复你了,估计你是没有去查看吧,地址连接:http://bbs.witech.com.cn/forum.php?mod=viewthread&tid=47772&extra=page%3D1%26filter%3Dtypeid%26typeid%3D27%26typeid%3D27
页:
[1]