linux下的nrf24l01驱动程序

来源:互联网 发布:返利网是淘宝客吗 编辑:程序博客网 时间:2024/05/24 06:41


文件名:nrf24l01.c
功能:linux下的nrf24l01驱动程序

#include <linux/config.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
#include<linux/devfs_fs_kernel.h>

#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/arch/regs-gpio.h>

typedef unsigned int uint16 ;
typedef unsigned char uint8 ;
//和引脚相关的宏定义
#defineCSN      S3C2410_GPF3
#defineCSN_OUTP     S3C2410_GPF3_OUTP
#defineMOSI     S3C2410_GPF4
#defineMOSI_OUTP     S3C2410_GPF4_OUTP
#defineIRQ      S3C2410_GPG3
#defineIRQ_INP      S3C2410_GPG3_INP
#defineMISO     S3C2410_GPG2
#defineMISO_INP     S3C2410_GPG2_INP
#defineSCK      S3C2410_GPG5
#define SCK_OUTP  S3C2410_GPG5_OUTP
#defineCE       S3C2410_GPG6
#defineCE_OUTP       S3C2410_GPG6_OUTP

#defineDEVICE_NAME      “nrf24l01″ //设备名称,在可以 /proc/devices 查看
#define NRF24L01_MAJOR  271  //主设备号
#defineTxBufSize   32

uint8  TxBuf[TxBufSize]={
 0×01,0×02,0×03,0×4,0×05,0×06,0×07,0×08,
 0×09,0×10,0×11,0×12,0×13,0×14,0×15,0×16,
 0×17,0×18,0×19,0×20,0×21,0×22,0×23,0×24,
 0×25,0×26,0×27,0×28,0×29,0×30,0×31,0×32,
};

//NRF24L01端口定义
#define CE_OUT  s3c2410_gpio_cfgpin(CE,CE_OUTP)  //数据线设置为输出
#defineCE_UP       s3c2410_gpio_pullup(CE,1)       //打开上拉电阻
#define CE_L  s3c2410_gpio_setpin(CE,0)   //拉低数据线电平
#define CE_H  s3c2410_gpio_setpin(CE,1)   //拉高数据线电平

#define SCK_OUT  s3c2410_gpio_cfgpin(SCK,SCK_OUTP) //数据线设置为输出
#defineSCK_UP       s3c2410_gpio_pullup(SCK,1)       //打开上拉电阻
#define SCK_L  s3c2410_gpio_setpin(SCK,0)  //拉低数据线电平
#define SCK_H  s3c2410_gpio_setpin(SCK,1)  //拉高数据线电平

#define MISO_IN  s3c2410_gpio_cfgpin(MISO,MISO_INP) //数据线设置为输出
#defineMISO_UP       s3c2410_gpio_pullup(MISO,1)       //打开上拉电阻
#defineMISO_STU      s3c2410_gpio_getpin(MISO)  //数据状态

#define IRQ_IN  s3c2410_gpio_cfgpin(IRQ,IRQ_INP) //数据线设置为输出
#defineIRQ_UP       s3c2410_gpio_pullup(IRQ,1)       //打开上拉电阻
#define IRQ_L  s3c2410_gpio_setpin(IRQ,0)   //拉低数据线电平
#define IRQ_H  s3c2410_gpio_setpin(IRQ,1)   //拉高数据线电平

#define MOSI_OUT s3c2410_gpio_cfgpin(MOSI, MOSI_OUTP)//数据线设置为输出
#defineMOSI_UP       s3c2410_gpio_pullup(MOSI,1)       //打开上拉电阻
#define MOSI_L  s3c2410_gpio_setpin(MOSI,0)  //拉低数据线电平
#define MOSI_H  s3c2410_gpio_setpin(MOSI,1)  //拉高数据线电平

#define CSN_OUT  s3c2410_gpio_cfgpin(CSN,CSN_OUTP) //数据线设置为输出
#defineCSN_UP       s3c2410_gpio_pullup(CSN,1)       //打开上拉电阻
#define CSN_L  s3c2410_gpio_setpin(CSN,0)  //拉低数据线电平
#define CSN_H  s3c2410_gpio_setpin(CSN,1)  //拉高数据线电平
 

//NRF24L01
#defineTX_ADR_WIDTH         // 5 uint8s TX address width
#defineRX_ADR_WIDTH         // 5 uint8s RX address width
#define TX_PLOAD_WIDTH 32    // 20uint8s TX payload
#define RX_PLOAD_WIDTH 32      // 20 uint8s TX payload
uint8 const TX_ADDRESS[TX_ADR_WIDTH]={0×34,0×43,0×10,0×10,0×01};   //本地地址
uint8 const RX_ADDRESS[RX_ADR_WIDTH]={0×34,0×43,0×10,0×10,0×01};   //接收地址
//NRF24L01寄存器指令
#defineREAD_REG       0×00    //读寄存器指令
#defineWRITE_REG      0×20    //写寄存器指令
#defineRD_RX_PLOAD    0×61    //读取接收数据指令
#defineWR_TX_PLOAD    0xA0    //写待发数据指令
#defineFLUSH_TX       0xE1    // 冲洗发送FIFO指令
#defineFLUSH_RX       0xE2    // 冲洗接收FIFO指令
#defineREUSE_TX_PL    0xE3    //定义重复装载数据指令
#defineNOP            0xFF    //保留
//SPI(nRF24L01)寄存器地址
#defineCONFIG         0×00  // 配置收发状态,CRC校验模式以及收发状态响应方式
#defineEN_AA          0×01  // 自动应答功能设置
#defineEN_RXADDR      0×02  // 可用信道设置
#defineSETUP_AW       0×03  // 收发地址宽度设置
#defineSETUP_RETR     0×04  // 自动重发功能设置
#defineRF_CH          0×05  // 工作频率设置
#defineRF_SETUP       0×06  // 发射速率、功耗功能设置
#defineSTATUS         0×07  // 状态寄存器
#defineOBSERVE_TX     0×08  // 发送监测功能
#defineCD             0×09  //地址检测          
#defineRX_ADDR_P0     0x0A  // 频道0接收数据地址
#defineRX_ADDR_P1     0x0B  // 频道1接收数据地址
#defineRX_ADDR_P2     0x0C  // 频道2接收数据地址
#defineRX_ADDR_P3     0x0D  // 频道3接收数据地址
#defineRX_ADDR_P4     0x0E  // 频道4接收数据地址
#defineRX_ADDR_P5     0x0F  // 频道5接收数据地址
#defineTX_ADDR        0×10  // 发送地址寄存器
#defineRX_PW_P0       0×11  // 接收频道0接收数据长度
#defineRX_PW_P1       0×12  // 接收频道0接收数据长度
#defineRX_PW_P2       0×13  // 接收频道0接收数据长度
#defineRX_PW_P3       0×14  // 接收频道0接收数据长度
#defineRX_PW_P4       0×15  // 接收频道0接收数据长度
#defineRX_PW_P5       0×16  // 接收频道0接收数据长度
#defineFIFO_STATUS    0×17  // FIFO栈入栈出状态寄存器设置

 

uint8 init_NRF24L01(void);

uint8 SPI_RW(uint8 tmp);

uint8 SPI_Read(uint8 reg);

void SetRX_Mode(void);

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);

unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);

void nRF24L01_TxPacket(unsigned char * tx_buf);

//全局变量
uint8 opencount = 0;
//
uint8    sta;   //状态标志
#define  RX_DR    6
#define  TX_DS    5
#define  MAX_RT   4

 

//NRF24L01初始化
uint8 init_NRF24L01(void)
{

   MISO_UP;

   CE_OUT;
   CSN_OUT;
   SCK_OUT;
   MOSI_OUT;
   MISO_IN;
    IRQ_IN;

   udelay(500);

   CE_L;    // chipenable
   ndelay(60);
   CSN_H;   // Spi disable
   ndelay(60);
   SCK_L;   // Spi clock line inithigh
   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,0×01);     //  频道0自动 ACK应答允许
   SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0×01); // 允许接收地址只有频道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,0×07);        //设置发射速率为1MHZ,发射功率为最大值0dB
   SPI_RW_Reg(WRITE_REG + CONFIG,0x0f);          // IRQ收发完成中断响应,16位CRC ,主接收

   mdelay(1000);
   nRF24L01_TxPacket(TxBuf);
   SPI_RW_Reg(WRITE_REG+STATUS,0XFF);
    printk(“test1 \n”);
   mdelay(1000);

    return(1);
}
//函数:uint8 SPI_RW(uint8 tmp)
//功能:NRF24L01的SPI写时序tmp
uint8 SPI_RW(uint8 tmp)
{
    uint8bit_ctr;

   for(bit_ctr=0 ;bit_ctr<8 ;bit_ctr++) // output8-bit
    {
 if(tmp &0×80)        // output ‘tmp’, MSB to MOSI
    MOSI_H;
 else
    MOSI_L;
 
       tmp <<=1;          // shift next bit into MSB..

       SCK_H;                  // Set SCK high..
 ndelay(60);

       tmp |=MISO_STU;         // capture current MISO bit
       SCK_L;                  // ..then set SCK low again
 ndelay(60);
    }
   return(tmp);                   // return read tmp
}

 

//函数:uint8 SPI_Read(uint8 reg)
//功能:NRF24L01的SPI时序
uint8 SPI_Read(uint8 reg)
{
    uint8reg_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)
{
    uint8status;  

   CSN_L;                  // CSN low, init SPI transaction
   ndelay(60);
    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, uint8uchars)
//功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数
uint8 SPI_Read_Buf(uint8 reg, uint8 *pBuf, uint8 uchars)
{
    uint8status,uint8_ctr;
   
   CSN_L;                           // Set CSN low, init SPI tranaction
   ndelay(60);
    status =SPI_RW(reg);              // Select register to write to and read status uint8
   
   for(uint8_ctr=0;uint8_ctr<uchars;uint8_ctr++)
    {
       pBuf[uint8_ctr] =SPI_RW(0);   //
       ndelay(20);
    }
   
    CSN_H;
   ndelay(60);
   
   return(status);                   // return nRF24L01 status uint8
}
//函数:uint8 SPI_Write_Buf(uint8 reg, uint8 *pBuf, uint8uchars)
//功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数
uint8 SPI_Write_Buf(uint8 reg, uint8 *pBuf, uint8 uchars)
{
    uint8status,uint8_ctr;
   
   CSN_L;           //SPI使能 
   ndelay(60);
    status =SPI_RW(reg);  
   for(uint8_ctr=0; uint8_ctr<uchars; uint8_ctr++)//
    {
       SPI_RW(*pBuf++);
    ndelay(20);
    }
   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 ,主接收
   //udelay(1);
    CE_H;
   udelay(130);
}

 

//函数:unsigned char nRF24L01_RxPacket(unsigned char*rx_buf)
//功能:数据读取后放如rx_buf接收缓冲区中
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
{
    unsignedchar revale=0;

   sta=SPI_Read(STATUS);   //读取状态寄存其来判断数据接收状况
    if(sta&(1<<RX_DR))    // 判断是否接收到数据
    {
       CE_L;            //SPI使能
    udelay(50);
       SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receivepayload from RX_FIFO buffer
       revale=1;         //读取数据完成标志
    }
   SPI_RW_Reg(WRITE_REG+STATUS,sta);  //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
    returnrevale;
}
//函数:void nRF24L01_TxPacket(unsigned char * tx_buf)
//功能:发送 tx_buf中数据
void nRF24L01_TxPacket(unsigned char * tx_buf)
{
   CE_L;          //StandBy I模式
   ndelay(60);
   SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); //装载接收端地址
   SPI_Write_Buf(WR_TX_PLOAD, tx_buf,TX_PLOAD_WIDTH);             // 装载数据
   SPI_RW_Reg(WRITE_REG + CONFIG,0x0e);           // IRQ收发完成中断响应,16位CRC,主发送
   CE_H;       //置高CE,激发数据发送
   udelay(10);
}

//文件的写函数
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(TxBuf);
   SPI_RW_Reg(WRITE_REG+STATUS,0XFF);
    printk(“OK!\n”);
   return(10);
}

//的读函数
static ssize_t nrf24l01_read(struct file *filp, char *buffer,
             size_t count, loff_t *ppos)
{
   nRF24L01_TxPacket(TxBuf);
   SPI_RW_Reg(WRITE_REG+STATUS,0XFF);
    printk(“read\n”);

    return(10);
}

static int nrf24l01_open(struct inode *node, struct file*file)
{
  uint8 flag = 0;

  if(opencount == 1)
    return-EBUSY;
 
  flag = init_NRF24L01();

  mdelay(100);
  if(flag == 0)
    {
     printk(“uable to open device!\n”);
     return -1;
    }
  else
   {
     opencount++;
     printk(“device opened !\n”);
     return 0;
   }
}

static int nrf24l01_release(struct inode *node, struct file*file)
{
  opencount–;
  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 int __init nrf24l01_init(void)
{
    int ret;

   printk(“Initial driver for NRF24L01………………….\n”);
    ret =register_chrdev(NRF24L01_MAJOR, DEVICE_NAME,&nrf24l01_fops);
   mdelay(10);
    if (ret< 0)
    {
       printk(DEVICE_NAME ” can’t register major number\n”);
       return ret;

    }

   devfs_mk_cdev(MKDEV(NRF24L01_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR| S_IRGRP, DEVICE_NAME);
 
    printk(DEVICE_NAME ” register success\n”);
    return 0;
   
}

static void __exit nrf24l01_exit(void)
{
   unregister_chrdev(NRF24L01_MAJOR, DEVICE_NAME);
   printk(“NRF24L01 unregister success \n”);
}
module_init(nrf24l01_init);
module_exit(nrf24l01_exit);
MODULE_LICENSE(“GPL”);

原创粉丝点击