免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1306 | 回复: 0
打印 上一主题 下一主题

Linux下设备应用和驱动程序的编写(以RSSI为例) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-24 17:01 |只看该作者 |倒序浏览

                作者:ARM混迹江湖
[摘自]http://blog.tianya.cn/blogger/post_show.asp?BlogID=648077&PostID=9434859
Linux下所有的设备都是以文件的形式来操作的。设备软件分为两部分:应用程序和驱动程序,其中,应用程序负责打开设备并对它发出读写指令,驱动程序接受指令并完成读写的过程。
本文以AD5310用于AP/BG为例,讲述其应用和驱动的编写过程。
1. 硬件电路


 其中GPIO为CPU管脚,当J2上有Power Meter接上时,BNC_EN为低,程序开始从系统中获取RSSI,换算成相应的值以SPI时序送给AD5310,AD5310把它转化为相应电压,在Power Meter上显示。
2. 驱动实现
 2.1 代码编写
 驱动的编写主要是编写操作函数,例如读写等,因此驱动程序的结构比较单一,其主要的不同是操作函数的实现过程。
AD5310驱动的实现代码即说明如下:
#ifndef __KERNEL__ //判断驱动是编译进内核还是编译成模块
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif

#include … //包含相关头文件
#ifndef __MOD_INC_USE_COUNT
#define AH_MOD_INC_USE_COUNT(_m) \
 if (!try_module_get(_m)) { \
 printk(KERN_WARNING "try_module_get failed\n"); \
 return NULL; \
 }
#define AH_MOD_DEC_USE_COUNT(_m) module_put(_m)
#else
#define AH_MOD_INC_USE_COUNT(_m) MOD_INC_USE_COUNT
#define AH_MOD_DEC_USE_COUNT(_m) MOD_DEC_USE_COUNT
#endif
… //此处声明函数
struct file_operations spi_fops= //告诉系统应用程序的某个命令由谁来执行
{ //file_operation 是系统定义的结构体
 .owner = THIS_MODULE,
 .open = AD5310_open,
 .release = AD5310_release,
 .write = AD5310_write,
 .read = AD5310_read,
};
char spi_name[]="AD5310"; //device name
static int gmajor = 254; //device ID
/*************************************/
static int __init spidrv_init_module(void) //register device
{
int retv; //register_chrdev()是linux系统注册函数
 retv=register_chrdev(gmajor,spi_name,&spi_fops);
 if(retv> 12;
 input = input & 0x01;
 *buf = input;
 return(1);
}
/*********************************************************************
 *write data to output GPIO9
 *AD5310 input register contents:
 * DB15(MSB) ........................DB0(LSB)
 * x x PD1 PD0 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 x x
 *
 *PD1 PD0 = 0 0 normal operation
 *PD1 PD0 = 0 1 1K resister to GND power down modes
 *PD1 PD0 = 1 0 100K to GND power down modes
 *PD1 PD0 = 1 1 Three-State power down modes
 ********************************************************************/
static int AD5310_write(struct file *fp,char *buf,int len,loff_t *loff)
{
 int i;
 int temp;
 int spibuf;
 char *p;
 int writedata;

 p=buf; //get the data ,buf[1] low buf[0] high
 writedata=*p;
 p++;
 writedata = (writedata  1023 || writedata  /dev/null
 #mknod /dev/AD5310 c 254 1
此时若驱动正常工作,就会输出打印信息 SPI device OK! ,并且在/dev 目录下可以看到 AD5310 这个设备。
3. 应用实现
Linux下应用程序以文件的形式来操作设备,其最基本的操作顺序为
Open() -> read()/write() -> close()
RSSI应用实现的代码如下:
#define __KERNEL__
#include … //包含需要的头文件
#define … //定义相关变量
/*******************************************************************
 *get the RSSI value
 *******************************************************************/
int GetRSSIvalue(void)
 {
 int8_t rssivalue;
 const char *ifname;
 char aa[5] = {"ath0"};
 ifname = aa;
 u_char buf[24*1024];
 struct iwreq iwr;
 u_char *cp;
 int s, len;
 s = socket(AF_INET, SOCK_DGRAM, 0);
 if (s isi_rssi;
 cp += si->isi_len, len -= si->isi_len;
 } while (len >= sizeof(struct ieee80211req_sta_info));
 return(rssivalue);
}
/*******************************************************************
 *main function
 *******************************************************************/
int main(int argc,char **argv)
{
 int rssivalue;
 int senddata;
 int RSSIprecision;
 char inputstate[2];
 char databuf[2];
 const int maxrssi=66;
 const int minrssi=2;
 int fd;
 int size;
if((fd=open("/dev/AD5310",O_RDWR))==-1) //打开设备文件
{
 perror("device open fail\n");
 exit(1)
}
 RSSIprecision=1023/maxrssi;
 Delay(5);
 while(1)
 {
 size = read(fd,inputstate,1,0); //读取GPIO12状态,查看是否有Meter接入
 if(inputstate[0]==1) //no meter,high
 {
 printf("RSSI not enabled!\n");
 printf("Please mount RSSI meter!\n");
 Delay(1000);
 }
 else //有Meter接入
 {
 printf("mount RSSI meter OK!");
 rssivalue = GetRSSIvalue(); //从系统中获得RSSI的值
 printf("RSSI:%4d",rssivalue);
 if(rssivalue > maxrssi)
 { //over load,display max vcc
 senddata = 1023;
 }
 else if(rssivalue > 8;
 write(fd,databuf,2,0); //把数据发送给AD5310
 printf("databuf[1]=%d\n",databuf[1]);
 printf("databuf[0]=%d\n",databuf[0]);
 sleep(1); //延时
 }
 }
}
/**************************************************************/
/*end of RSSI_AD5310*/

另外,在编写真正的应用程序之前,为了保证驱动程序的正确性,一般会先写一些小的测试应用程序来测试驱动,在驱动正确的情况下才会编写测试我们需要的应用程序。
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/98073/showart_1976386.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP