📄 nnrf2401.c
字号:
#include<linux/module.h>#include<linux/init.h>#include<linux/kernel.h>#include<linux/config.h>#include<linux/fs.h>#include<asm/uaccess.h>#include<linux/version.h>#include<linux/irq.h>#include<linux/poll.h>#include<linux/delay.h>#include<asm/arch/irq.h>#include<asm/hardware.h>#include<linux/spinlock.h>#include<asm/arch/S3C2440.h> //为了使用GPIO端口定义#include<linux/devfs_fs_kernel.h> //为了使用devfs_register和devfs_unregister函数MODULE_LICENSE("GPL");
#define DEVICE_NAME "nRF2401"
#define MAJOR_NUM 233#define MINOR_NUM 0
static devfs_handle_t devfs_handle=NULL;static devfs_handle_t devfs_nRF2401_dir=NULL; //在/dev下建立相应的目录#define DEV_DIR "nRF2401" static DECLARE_WAIT_QUEUE_HEAD(nRF2401_wait); static int ready=0;
#define DR1 GPIO_G9 //定义GPIO口与NRF2440的接口#define PWR_UP GPIO_B6#define CLK1 GPIO_G7#define MISO GPIO_G5#define MOSI GPIO_G6#define CE GPIO_E13#define CS GPIO_E12#define LED GPIO_F4
#define PACKETLEN 22
unsigned char RData[PACKETLEN]; //指向驱动程序申请的用于存放接收数据的内存区域
static struct nRF2401Config{ unsigned char n; //配置字长度 unsigned char buf[15];//配置字数组}config={15, { 0x00, //接收通道2有效数据长度 0xB0, //接收通道1有效数据长度 0x00,0x00,0x00,0x00,0x00, //接收通道2地址,最长5字节,缺少位用0填 0x00,0xcc,0xcc,0xcc,0xcc, //接收通道1地址,最长5字节,缺少位用0填 0x83, //32位地址长度(bit7-bit2);16bit CRC(bit1);CRC enable 0x4f,//单通道接收(bit7);ShockBrust(bit6);速率(bit5);晶振频率(bit4-bit2);功率(bit2-bit0) 0x01 //频道(bit7-bit1);发送/接收(bit0:0/1) } };static void SPI_init(void){ //IO initial set_gpio_ctrl(DR1|GPIO_MODE_ALT0);//设置为DR1为中断模式 set_gpio_ctrl(CE|GPIO_MODE_OUT|GPIO_PULLUP_EN); set_gpio_ctrl(CS|GPIO_MODE_OUT|GPIO_PULLUP_EN); set_gpio_ctrl(PWR_UP|GPIO_MODE_OUT|GPIO_PULLUP_EN); set_gpio_ctrl(CLK1|GPIO_MODE_ALT1|GPIO_PULLUP_EN);//设置引脚为SPI set_gpio_ctrl(MISO|GPIO_MODE_ALT1|GPIO_PULLUP_EN); set_gpio_ctrl(MOSI|GPIO_MODE_ALT1|GPIO_PULLUP_EN); set_gpio_ctrl(LED|GPIO_MODE_OUT|GPIO_PULLUP_EN);//设置LED引脚 write_gpio_bit(PWR_UP,0);//初始化nFR2401引脚
write_gpio_bit(CE,0);
write_gpio_bit(CS,0); write_gpio_bit(LED,1);//关LED
//REGISTER initial SPPRE1=0xff; //设置波特率为132,300bps SPCON1=0x18;//设置为查询方式 printk("SPI configured\n"); } static void SPI_poll_done(void){ int ncount=0; while(!(SPSTA1&0x01)){ //判断SPI发送寄存器是否已经准备好 ncount++; if(ncount>=5000){ printk("SPI state poll failed\n");
// return -1; break; } }
//return 0; }static void SPI_tx_data(unsigned char data){ //通过SPI发送数据 SPI_poll_done(); SPTDAT1=data; SPI_poll_done(); }
void RX_Packet(void)
{ //读取数据包
unsigned char i;
for(i=0;i<PACKETLEN;i++)
{
SPI_tx_data(0xff);
RData[i]=SPRDAT1;
} printk("recevie RX_Packet\n");
}
static void nRF2401_ON(void) { //nRF2401上电 write_gpio_bit(CE,0);
write_gpio_bit(CS,0);
write_gpio_bit(PWR_UP,1);
mdelay(3);//延时3ms,nrf2401进入待机模式
printk("nRF2401 on\n");
}
static void nRF2401_Config(void)
{ //nRF2401配置
unsigned char i;
write_gpio_bit(CE,0);
write_gpio_bit(CS,1);
udelay(10); //延时10us
for(i=0;i<config.n;i++){
SPI_tx_data(config.buf[i]);
}
write_gpio_bit(CS,0);
write_gpio_bit(CE,1);//激活接收模式,经过202us内部延时后进入接收模式
printk("nRF2401 configed\n");
}
static void nRF2401_Close(void)//关闭nRF2401
{
write_gpio_bit(CE,0);
write_gpio_bit(CS,0);
write_gpio_bit(PWR_UP,0);
printk("nRF2401 close\n");
}
static void nRF2401_irq(int irq,void *dev_id,struct pt_regs *reg)
{
unsigned int flags; write_gpio_bit(LED,0);//开LED,表示接收到数据
save_flags(flags); //中断处理时禁止再次中断
cli();
//printk("nRF2401have prepared the datas!\n"); //中断处理函数 //mdelay(1000);
RX_Packet();
restore_flags(flags); write_gpio_bit(LED,1);//关LED,表示读完数据 ready=1;
wake_up_interruptible(&nRF2401_wait); //通知应用程序有数据可读
}
static int requestb_irq(void) //中断申请函数
{
set_external_irq(IRQ_EINT17,EXT_RISING_EDGE,GPIO_PULLUP_DIS);//DR1上升沿触发
if(request_irq(IRQ_EINT17,&nRF2401_irq,SA_INTERRUPT,DEVICE_NAME,&nRF2401_irq)){
printk(DEVICE_NAME" request_irq failed!\n");
return -1;
} printk("irq succes!\n");
return 0;
}
static void freeb_irq(void)
{
free_irq(IRQ_EINT17,nRF2401_irq);
}
static int nRF2401_open(struct inode *inode,struct file *file){
ready=0;
nRF2401_ON();
nRF2401_Config(); printk(DEVICE_NAME" open\n"); MOD_INC_USE_COUNT; return 1; }static int nRF2401_release(struct inode *inode,struct file *file){ nRF2401_Close(); printk(DEVICE_NAME" release\n");
MOD_DEC_USE_COUNT; return 1; }static ssize_t nRF2401_read(struct file *file,char *buf,size_t len,loff_t *off){ __copy_to_user(buf,RData,sizeof(RData));
ready=0; return sizeof(RData);}/*static ssize_t nRF2401_write(struct file *file,const char *buf,size_t len,loff_t *off){ __copy_from_user(&,buf,sizeof()); return sizeof();}*/static unsigned int nRF2401_select(struct file *file,struct poll_table_struct *wait){ //printk("poll ready is%d\n",ready); if(ready)return 1; poll_wait(file,&nRF2401_wait,wait);//使外部应用程序阻塞,等待数据准备好 return 0;}
static struct file_operations nRF2401_fops={ owner: THIS_MODULE, open:nRF2401_open, release:nRF2401_release, //ioctl:nRF2401_ioctl, read:nRF2401_read,// write:nRF2401_write, poll:nRF2401_select, };
static int nRF2401_init(void){ int ret; ret=register_chrdev(MAJOR_NUM,DEVICE_NAME,&nRF2401_fops); if(ret) { printk(DEVICE_NAME" register failure\n"); return ret; } else printk(DEVICE_NAME" register success\n"); ret=requestb_irq(); if(ret){ ret=unregister_chrdev(MAJOR_NUM,DEVICE_NAME); if(ret) { printk(DEVICE_NAME" unregister failure\n"); } else printk(DEVICE_NAME" unregister success\n"); return ret; } devfs_nRF2401_dir=devfs_mk_dir(NULL,DEV_DIR,NULL); devfs_handle=devfs_register(devfs_nRF2401_dir,DEVICE_NAME,DEVFS_FL_DEFAULT,MAJOR_NUM,MINOR_NUM,S_IFCHR|S_IRUSR|S_IWUSR,&nRF2401_fops,NULL); SPI_init(); return ret;}static void nRF2401_exit(void){ int ret; devfs_unregister(devfs_handle); freeb_irq(); ret=unregister_chrdev(MAJOR_NUM,DEVICE_NAME); if(ret) { printk(DEVICE_NAME" unregister failure\n"); } else printk(DEVICE_NAME" unregister success\n"); } module_init(nRF2401_init);module_exit(nRF2401_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -