|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2012-7-21 21:33:11
|
显示全部楼层
驱动程序
#include "NRF24L01.h"
typedef unsigned int uint16;
typedef unsigned char uint8;
int devmajor = NRF_MAJOR;
int devminor = NRF_MINOR;
dev_t dev = 0;
struct NRF_dev
{
struct cdev cdev;
};
struct NRF_dev *NRF_devices;
struct class *nrf_class; //自动创建结点
uint8 TxBuf[32]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x30,0x31
};
uint8 RxBuf[32]={0x00};
uint8 TX_ADDRESS[TX_ADR_WIDTH] = { 0x34, 0x43, 0x10, 0x10, 0x01 }; //本地地址
uint8 RX_ADDRESS[RX_ADR_WIDTH] = { 0x34, 0x43, 0x10, 0x10, 0x01 }; //接收地址
/* 打开计数 */
uint open_count = 0;
//状态标志
uint8 sta;
int get_data=0;
unsigned char flag = 0;
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
uint8 SPI_RW(uint8 uchar);
uint8 SPI_Read(uint8 reg);
uint8 SPI_RW_Reg(uint8 reg, uint8 value);
uint8 SPI_Read_Buf(uint8 reg, uint8 *pBuf, uint8 uchars);
uint8 SPI_Write_Buf(uint8 reg, uint8 * pBuf, uint8 uchars);
void SetRX_Mode(void);
unsigned char nRF24L01_RxPacket(unsigned char *rx_buf);
unsigned char nRF24L01_TxPacket(unsigned char *tx_buf);
uint8 init_NRF24L01(void);
static ssize_t nrf24l01_write(struct file *filp,const char *buffer, size_t count,loff_t *ppos);
static ssize_t nrf24l01_read(struct file * filp,char *buffer,size_t count,loff_t *ppos);
static int nrf24l01_open(struct inode *node, struct file *file);
static int nrf24l01_release(struct inode *node, struct file *file);
static void __exit nrf24l01_exit(void);
static int __init nrf24l01_init(void);
/**********************************************************/
//函数:uint SPI_RW(uint uchar)
//功能:NRF24L01的SPI写时序
/**********************************************************/
uint8 SPI_RW(uint8 uchar)
{
uint8 bit_ctl;
for (bit_ctl = 0; bit_ctl < 8;bit_ctl++)
{
if(uchar & 0x80)
MOSI_H;
else
MOSI_L;
ndelay(20);
uchar <<= 1; //Shift next bit into MSB
SCK_H; //Set SCK high
ndelay(60);
uchar |= MISO_STU; //Capture current MISO bit
SCK_L;
ndelay(70);
}
return uchar;
}
/*******************************************/
// 函数:uint8 SPI_Read(uint8 reg)
// 功能:NRF24L01的SPI时序
/*******************************************/
uint8 SPI_Read(uint8 reg)
{
uint8 reg_val;
CSN_L; // CSN low, initialize SPI communication...
ndelay(60);
SPI_RW(reg); // Select register to read from..
reg_val = SPI_RW(0); // ..then read registervalue
CSN_H; // CSN high, terminate SPI communication
ndelay(60);
return (reg_val); // return register value
}
/*******************************************/
//功能:NRF24L01的读写寄存器函数
/*******************************************/
uint8 SPI_RW_Reg(uint8 reg, uint8 value)
{
uint8 status;
CSN_L; // CSN low, init SPI transaction
ndelay(140);
status = SPI_RW(reg); // select register
SPI_RW(value); // ..and write value to it..
CSN_H; // CSN high again
ndelay(60);
return (status); // return nRF24L01 status uint8
}
/************************************************************************/
//函数:uint8 SPI_Read_Buf(uint8 reg, uint8 *pBuf, uint8 uchars)
//功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数
/************************************************************************/
uint8 SPI_Read_Buf(uint8 reg, uint8 *pBuf, uint8 uchars)
{
uint8 status, uchar_ctr;
CSN_L; // Set CSN low, init SPI tranaction
ndelay(140);
status = SPI_RW(reg); // Select register to write to and read status uint8
for (uchar_ctr = 0; uchar_ctr < uchars; uchar_ctr++)
{
pBuf[uchar_ctr] = SPI_RW(0);
}
CSN_H;
ndelay(60);
return (status); // return nRF24L01 status uint8
}
/************************************************************************/
//函数:uint8 SPI_Write_Buf(uint8 reg, uint8 *pBuf, uint8 uchars)
//功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数
/************************************************************************/
uint8 SPI_Write_Buf(uint8 reg, uint8 *pBuf, uint8 uchars)
{
uint8 status, uchar_ctr;
CSN_L; //SPI使能
ndelay(140);
status = SPI_RW(reg);
printk(KERN_WARNING"status = %x\n",status);
for (uchar_ctr = 0; uchar_ctr < uchars; uchar_ctr++) //
{
SPI_RW(*pBuf++);
ndelay(30);
}
CSN_H; //关闭SPI
ndelay(60);
return (status); //
}
/************************************************************************/
//函数:void SetRX_Mode(void)
//功能:数据接收配置
/************************************************************************/
void SetRX_Mode(void)
{
CE_L;
ndelay(60);
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC,主接收
CE_H;
udelay(150);
}
/************************************************************************/
//函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf )
//功能:数据读取后放如rx_buf接收缓冲区中
/************************************************************************/
unsigned char nRF24L01_RxPacket(unsigned char *rx_buf)
{
unsigned char revale = 0;
sta = SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况
printk(KERN_WARNING" SPI_Read sta = %x\n",sta);
if (sta & 0x40) // 判断是否接收到数据
{
printk(KERN_WARNING"222");
CE_L; //StandBy I模式
//udelay(150);
SPI_Read_Buf(RD_RX_PLOAD, rx_buf, RX_PLOAD_WIDTH);
// read receive payload from RX_FIFO buffer
{printk(KERN_WARNING"rx=%d",rx_buf[9]);}
printk("\n");
revale = 1; //读取数据完成标志
}
SPI_RW_Reg(WRITE_REG + STATUS, sta);
//接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
return revale;
}
/************************************************************************/
//函数:unsigned char nRF24L01_TxPacket(unsigned char * tx_buf)
//功能:发送 tx_buf中数据
/************************************************************************/
unsigned char nRF24L01_TxPacket(unsigned char *tx_buf)
{
CE_L; //StandBy I模式
ndelay(60);
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据
printk(KERN_WARNING"nRF24L01_TxPacket write tx_buf=%s\n",tx_buf);
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); //使能自动应答,通道0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1f); //自动重发延时500+86us
SPI_RW_Reg(WRITE_REG + RF_CH, 0); //
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送
udelay(2000);
CE_H; //置高CE,激发数据发送
udelay(50);
CE_L;
return 1;
}
/************************************************************************/
//初始化函数
/************************************************************************/
uint8 init_NRF24L01(void)
{
udelay(100);
MISO_UP;
//CE_UP;
//CSN_UP;
//SCK_UP;
//MOSI_UP;
IRQ_UP;
CE_OUT;
CSN_OUT;
SCK_OUT;
MOSI_OUT;
MISO_IN;
IRQ_IN;
udelay(500);
CE_L; // chip enable
ndelay(60);
CSN_H; // Spi disable
ndelay(60);
SCK_L; // Spi clock line init high
ndelay(60);
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); //频道0自动,ACK应答允许
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //允许接收地址只有频道0,如果需要多频道可以参考Page21
SPI_RW_Reg(WRITE_REG + RF_CH, 0); //设置信道工作为2.4GHZ,收发必须一致
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dB
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC,主接收
printk("nrf24l01_init success \n");
mdelay(1000);
return 1;
}
/************************************************************************/
/************************************************************************/
static ssize_t nrf24l01_write(struct file *filp,const char *buffer, size_t count,loff_t *ppos)
{
if(copy_from_user(&TxBuf,buffer,count))
{
printk("Can't Send Data !");
return -EFAULT;
}
nRF24L01_TxPacket(buffer);
SPI_RW_Reg(WRITE_REG+STATUS,sta);
printk("Send Data OK \n");
return count;
}
/************************************************************************/
/************************************************************************/
static ssize_t nrf24l01_read(struct file * filp,char *buffer,size_t count,loff_t *ppos)
{
int flag,AB=0;
mdelay(200);
SPI_RW_Reg(WRITE_REG+STATUS,0XFF);
init_NRF24L01();
SetRX_Mode();
AB=nRF24L01_RxPacket(RxBuf);
printk("AB=%d",AB);
printk("\n");
flag=copy_to_user(buffer,&RxBuf,count);
{printk(KERN_WARNING"a=%d",RxBuf[9]);}
printk("\n");
SPI_RW_Reg(WRITE_REG+STATUS,0XFF);
if(flag>0)
{
printk(KERN_WARNING"11\n");
return -EFAULT;
}
return count;
}
/************************************************************************/
/************************************************************************/
static int nrf24l01_open(struct inode *node, struct file *file)
{
if (open_count == 1)
return -EBUSY;
flag=init_NRF24L01();
mdelay(200);
if (flag == 0) {
printk("unable to open device!\n");
return -1;
} else {
open_count++;
printk("NRF24L01 device opened!\n");
return 0;
}
}
/************************************************************************/
/************************************************************************/
static int nrf24l01_release(struct inode *node, struct file *file)
{
open_count--;
printk(DEVICE_NAME "released !\n");
return 0;
}
/************************************************************************/
/************************************************************************/
static struct file_operations nrf24l01_fops = {
.owner = THIS_MODULE,
.open = nrf24l01_open,
.write = nrf24l01_write,
.read = nrf24l01_read,
.release = nrf24l01_release,
};
/************************************************************************/
/************************************************************************/
static void __exit nrf24l01_exit(void)
{
if(NRF_devices)
{
cdev_del(&NRF_devices->cdev);
kfree(NRF_devices);
}
device_destroy(nrf_class,MKDEV(devmajor,0));
class_destroy(nrf_class);
unregister_chrdev_region(dev,1);
printk(KERN_WARNING"NRF24L01 unregister success \n");
}
/************************************************************************/
/************************************************************************/
static int __init nrf24l01_init(void)
{
int ret;
if(devmajor)
{
dev = MKDEV(devmajor,devminor);
ret = register_chrdev_region(dev,1,DEVICE_NAME);
}
else
{
ret = alloc_chrdev_region(&dev,devminor,1,DEVICE_NAME);
devmajor = MAJOR(dev);
}
if (ret < 0) {
printk(DEVICE_NAME " Can't register major number\n");
return ret;
}
printk(KERN_WARNING"NRF24L01 get major %d\n",devmajor);
NRF_devices = kmalloc(sizeof(struct NRF_dev),GFP_KERNEL);
if(!NRF_devices)
{
ret = -ENOMEM;
goto fail;
}
memset(NRF_devices,0,sizeof(struct NRF_dev));
cdev_init(&NRF_devices->cdev,&nrf24l01_fops);
NRF_devices->cdev.owner = THIS_MODULE;
NRF_devices->cdev.ops = &nrf24l01_fops;
ret = cdev_add(&NRF_devices->cdev,dev,1);
if(ret)
{
printk(KERN_WARNING"Error %d adding DEMO\n",ret);
}
/*动态创建结点;静态方法:mknod /dev/name c major minor*/
nrf_class = class_create(THIS_MODULE,DEVICE_NAME);
if(IS_ERR(nrf_class))
{
printk("Err:failed in creating class \n");
return -1;
}
device_create(nrf_class,NULL,MKDEV(devmajor,0),NULL,DEVICE_NAME);
return 0;
fail:
nrf24l01_exit();
return ret;
}
module_init(nrf24l01_init);
module_exit(nrf24l01_exit);
MODULE_AUTHOR("lanxin");
MODULE_DESCRIPTION("NRF24L01 Driver For Mini2440");
MODULE_LICENSE("GPL");
|
|