📄 sht11_driver.c
字号:
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <linux/tqueue.h>
#include <linux/wait.h>
#include <asm/irq.h>
#include <asm/arch/hardware.h>
//#include <asm/arch/irqs.h>
#include <linux/devfs_fs_kernel.h>
//#include <asm/arch/AT91RM9200_TWI.h>
#include <asm/arch/pio.h>
/////////////////////////////////
void sht_ack();
////////////////////////////////
#define IO_MAJOR 101 //
#define DEVICE_NAME "sht11_driver"
#define AT91C_BASE_PIOA 0xFFFFF400 // TWI PIOA Base Address
#define AT91C_BASE_PMC 0xFFFFFC00 // PMC
static void * pioa_base;
static void * pmc_base;
#define uchar unsigned char
unsigned char com_data,com_datal,com_datah;
int io_open(struct inode * inode, struct file * filp);
int io_release(struct inode * inode, struct file * filp);
ssize_t io_read(struct file * filp, char * buf, size_t count, loff_t * l);
ssize_t io_write(struct file * filp,const char *buf,size_t count,loff_t * l);
//static int io_ioctl(struct inode *inode,struct file * file,unsigned int cmd,unsigned long arg);
int io_ioctl(struct inode *inode,struct file * file,unsigned int cmd,unsigned long arg);
struct file_operations io_fops = {
open: io_open,
ioctl: io_ioctl,
release: io_release,
read: io_read,
write: io_write,
};
void delay(int n)
{
int i;
for(i=0;i<n*1000;i++);
}
void sht_start()
{
int i;
outl(0x02000000,pioa_base+0x14); //sda=1
delay(2);
for(i=0;i<9;i++)
{
sht_ack();
}
outl(0x04000000,pioa_base+0x30); //scl=1
delay(2);
outl(0x02000000,pioa_base+0x10);
outl(0x02000000,pioa_base+0x34); //sda=0
delay(4);
outl(0x04000000,pioa_base+0x34); //scl=0
delay(1);
outl(0x04000000,pioa_base+0x30); //scl=1
delay(2);
outl(0x02000000,pioa_base+0x14); //sda=1
delay(1);
outl(0x04000000,pioa_base+0x34);
delay(2);
}
////////////////////////////////////////////0x04000000是对scl写一个数,
//////////////////////0x02000000是对SDA写数,
void sht_ack()
{
outl(0x04000000,pioa_base+0x34); //scl=0
delay(1);
outl(0x04000000,pioa_base+0x30); //scl=1
delay(2);
outl(0x04000000,pioa_base+0x34); //scl=0
delay(1);
}
void shift8(uchar a) //8位移位输出
{
unsigned char i;
com_data=a;
for(i=0;i<8;i++)
{
if((com_data&0x80)!=0)
{
outl(0x02000000,pioa_base+0x14);
delay(2);
outl(0x04000000,pioa_base+0x30);
delay(1);
outl(0x04000000,pioa_base+0x34);
delay(1);
com_data=com_data*2;
}
if((com_data&0x80)==0)
{
outl(0x02000000,pioa_base+0x10);
outl(0x02000000,pioa_base+0x34);
delay(2);
outl(0x04000000,pioa_base+0x30);
delay(2);
outl(0x04000000,pioa_base+0x34);
delay(1);
com_data=com_data*2;
}
}
}
int io_open(struct inode * inode, struct file * filp)
{
MOD_INC_USE_COUNT;
pioa_base=ioremap_nocache(AT91C_BASE_PIOA,0x100);
pmc_base =ioremap_nocache(AT91C_BASE_PMC,0x100);
outl(0xffffffff,pmc_base+0x10);
outl(0x06000000,pioa_base);
// outl(0xf9ffffff,pioa_base+0x04); //25/26 out
outl(0x04000000,pioa_base+0x10);
outl(0x02000000,pioa_base+0x14);
// outl(0xf9ffffff,pioa_base+0x14); //26 out
// outl(0x00000000,pioa_base+0x30);
// outl(0xffffffff,pioa_base+0x34); //25/26 out
// outl(0x00000000,pioa_base+0x40);
outl(0xffffffff,pioa_base+0x44); //25/26 out
// outl(0x00000000,pioa_base+0xA0);
outl(0xffffffff,pioa_base+0xA4); //25/26 out
return 0;
}
int io_release(struct inode * inode,struct file * filp)
{
MOD_DEC_USE_COUNT;
iounmap(pioa_base);
iounmap(pmc_base);
return 0;
}
ssize_t io_read(struct file * filp, char * buf, size_t count, loff_t * l)
{
}
ssize_t io_write(struct file * filp,const char *buf,size_t count,loff_t * l)
{
}
int io_ioctl(struct inode *inode,struct file * file,unsigned int cmd,unsigned long arg)
{
int temp;
long tem,tem1,tem2;
uchar i;
uchar command; //command=3时,测量温度;command=5时,测量湿度
command =cmd;
///////////////////////////
// data_sht11=1;
// sck_sht11=0;
///////////////////////////
sht_start();
shift8(command); //向SHT11发送测量命令
outl(0x02000000,pioa_base+0x14);
sht_ack();
delay(10); //等待测量
while((inl(pioa_base+0x3c)&0x02000000)!=0);
com_data=0;
for(i=0;i<8;i++) //取高八位
{
com_data=com_data*2;
outl(0x04000000,pioa_base+0x30);
delay(2);
if(((inl(pioa_base+0x3c))&0x02000000)!=0)
{
com_data=com_data+1;
}
outl(0x04000000,pioa_base+0x34);
delay(2);
}
outl(0x02000000,pioa_base+0x10);
outl(0x02000000,pioa_base+0x34);
sht_ack();
com_datah=com_data;
outl(0x02000000,pioa_base+0x14);
for(i=0;i<8;i++) //取低八位
{
com_data=com_data*2;
outl(0x04000000,pioa_base+0x30);
delay(2);
if((inl(pioa_base+0x3c)&0x02000000)!=0)
{
com_data=com_data+1;
}
outl(0x04000000,pioa_base+0x34);
delay(2);
}
// data_sht11=0;
// sck_sht11=1;
// outl(0x02000000,pioa_base+0x10);
// outl(0x02000000,pioa_base+0x34);
outl(0x04000000,pioa_base+0x30);
com_datal=com_data;
//通过运算得出测量结果
if(command==3)
{
temp=(com_datah&0x3f)*256+com_datal; //得到温度测量结果
temp=temp/100-40; //实际的温度值
// printk("%d\n",temp);
// printk("%d\n",com_datah);
// printk("%d\n",com_datal);
}
else
{
temp=(com_datah&0x0f)*256+com_datal; //得到湿度测量结果
// temp=
tem =(long)temp;
// tem=(tem*40)/1000+(tem*5)/10000-(((tem*2.8)/1000)*tem)/1000-4; //实际的湿度值
// tem=(tem*40)/1000+(tem*5)/10000;
tem1=tem*405;
tem1=tem1/10000;
tem2=tem*2.8;
tem2=tem2/1000;
tem2=tem2*tem;
tem2=tem2/1000;
tem=tem1-tem2-4;
temp=(int)tem;
// printk("%d\n",temp);
// printk("%f\n",tem);
// printk("%d\n",com_datah);
// printk("%d\n",com_datal);
}
return(temp);
}
int __init myio_init(void)
{
int ret_val=0;
ret_val=register_chrdev(IO_MAJOR,DEVICE_NAME,&io_fops);
if (ret_val < 0)
{
printk("can't get major %d", IO_MAJOR);
return ret_val;
}
printk("<1>register_chrdev: %d\n", ret_val);
return 0;
}
static void __exit myio_cleanup(void)
{
unregister_chrdev(IO_MAJOR, DEVICE_NAME);
}
module_init(myio_init);
module_exit(myio_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -