nfr24l01驱动

来源:互联网 发布:中京创意域名交易平台 编辑:程序博客网 时间:2024/06/09 14:45
#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/miscdevice.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <mach/map.h>#include <mach/regs-clock.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>#define uchar unsigned char#define S3C64XX_GPICON (S3C64XX_GPI_BASE+0x00)#define S3C64XX_GPIDAT (S3C64XX_GPI_BASE+0x04)#define S3C64XX_GPIPUD (S3C64XX_GPI_BASE+0x08)/**NRF24L01 command**/#define READ_REG 0x00 #define WRITE_REG 0x20 #define RD_RX_PLOAD 0x61 #define WR_TX_PLOAD 0xA0 #define FLUSH_TX 0xE1 #define FLUSH_RX 0xE2 #define REUSE_TX_PL 0xE3 #define NOP 0xFF /**NRF24L01 Register addr**/#define CONFIG 0x00 // 'Config' register address#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address#define EN_RXADDR 0x02 // 'Enabled RX addresses' register address#define SETUP_AW 0x03 // 'Setup address width' register address#define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address#define RF_CH 0x05 // 'RF channel' register address#define RF_SETUP 0x06 // 'RF setup' register address#define STATUS 0x07 // 'Status' register address#define OBSERVE_TX 0x08 // 'Observe TX' register address#define CD 0x09 // 'Carrier Detect' register address#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address#define RX_ADDR_P1 0x0B // 'RX address pipe1' register address#define RX_ADDR_P2 0x0C // 'RX address pipe2' register address#define RX_ADDR_P3 0x0D // 'RX address pipe3' register address#define RX_ADDR_P4 0x0E // 'RX address pipe4' register address#define RX_ADDR_P5 0x0F // 'RX address pipe5' register address#define TX_ADDR 0x10 // 'TX address' register address#define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address#define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address#define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address#define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address#define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address#define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address#define FIFO_STATUS 0x17 // 'FIFO Status Register' register address/**bus width**/#define TX_ADR_WIDTH    5   //5×??úμ?μ??·?í?è#define RX_ADR_WIDTH    5   //5×??úμ?μ??·?í?è#define TX_PLOAD_WIDTH  32  //2×??úμ?ó??§êy?Y?í?è#define RX_PLOAD_WIDTH  32  //2×??úμ?ó??§êy?Y?í?è/**functions**/uchar init_NRF24L01(void);uchar SPI_RW(uchar tmp);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uchar SPI_RW_Reg(uchar reg, uchar value);uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);void nRF24L01_TxPacket(unsigned char * tx_buf);/** I/O function**/void write_con(unsigned int mask,unsigned int con);void write_dat(unsigned int mask,unsigned int dat);void write_pud(unsigned int mask,unsigned int pud);unsigned int get_MISO(void); unsigned char TX_ADDRESS[]={0x34,0x43,0x10,0x10,0x01};unsigned char RX_ADDRESS[]={0x34,0x43,0x10,0x10,0x01};#define TxBufSize 32unsigned char  TxBuf[TxBufSize]={ 0x01,0x02,0x03,0x4,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,0x32,};uchar opencount = 0;unsigned int     sta;   //×?ì?±ê??#define   RX_DR    6#define   TX_DS    5#define   MAX_RT   4#define DEVICE_NAME "NRF24L01"#define NRF_MAJOR 97static int nrf_major=NRF_MAJOR;static int nrf_minor;struct nrf_dev{struct cdev cdev;char data_tx[TX_PLOAD_WIDTH];char data_rx[RX_PLOAD_WIDTH];};struct nrf_dev *nrf_devp;/**pin configure**///GPI0#define CE_OUT write_con(0x03,0x01)  //数据线设置为输出#define CE_UP write_pud(0x03,0x02)  //打开上拉电阻#define CE_L write_dat(0x01,0)     //拉低数据线电平#define CE_H write_dat(0x01,1)    //拉高数据线电平//GPI1#define CSN_OUT write_con(0x03<<2,0x01<<2)   //数据线设置为输出#define CSN_UP write_pud(0x03<<2,0x02<<2   )   //打开上拉电阻#define CSN_L write_dat(0x01<<1,0<<1)   //拉低数据线电平#define CSN_H write_dat(0x01<<1,1<<1)  //拉高数据线电平//GPI2#define SCK_OUT write_con(0x03<<4,0x01<<4)   //数据线设置为输出#define SCK_UP write_pud(0x03<<4,0x02<<4)  //打开上拉电阻#define SCK_L write_dat(0x01<<2,0<<2)     //拉低数据线电平#define SCK_H write_dat(0x01<<2,1<<2)   //拉高数据线电平//GPI3#define MOSI_OUT write_con(0x03<<6,0x01<<6)   //数据线设置为输出#define MOSI_UP write_pud(0x03<<6,0x02<<6)  //打开上拉电阻#define MOSI_L write_dat(0x01<<3,0<<3)  //拉低数据线电平#define MOSI_H write_dat(0x01<<3,1<<3)  //拉高数据线电平//GPI4#define MISO_IN write_con(0x03<<8,0x00<<8)    //数据线设置为输出#define MISO_UP write_pud(0x03<<8,0x02<<8)   //打开上拉电阻#define MISO_STU  get_MISO()   //数据状态//GPI5#define IRQ_IN write_con(0x03<<10,0x00<<10)   //数据线设置为输出#define IRQ_UP write_pud(0x03<<10,0x02<<10)  //打开上拉电阻#define IRQ_L write_dat(0x01<<5,0<<5)   //拉低数据线电平#define IRQ_H write_dat(0x01<<5,1<<5)  //拉高数据线电平/*pin & nrf*//*******************CE-GPI0CSN-GPI1SCK-GPI2MOSI-GPI3MISO-GPI4IRQ-GPI5********************/void write_con(unsigned int mask,unsigned int con){unsigned int tmp;tmp=readl(S3C64XX_GPICON);tmp=((tmp&(~mask))|con);writel(tmp,S3C64XX_GPICON);}void write_dat(unsigned int mask,unsigned int dat){unsigned int tmp;tmp=readl(S3C64XX_GPIDAT);tmp=((tmp&(~mask))|dat);writel(tmp,S3C64XX_GPIDAT);}void write_pud(unsigned int mask,unsigned int pud){unsigned int tmp;tmp=readl(S3C64XX_GPIPUD);tmp=((tmp&(~mask))|pud);writel(tmp,S3C64XX_GPIPUD);}unsigned int get_MISO(void){unsigned int tmp=0;tmp=readl(S3C64XX_GPIDAT);if(tmp&(1<<4))return 1;else return 0;}uchar init_NRF24L01(void){    MISO_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);    SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);    SPI_RW_Reg(WRITE_REG + RF_CH, 0);     SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);    SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);     return 1;}uchar SPI_RW(uchar tmp){  uchar bit_ctr;  for(bit_ctr=0 ;bit_ctr<8 ;bit_ctr++) // output 8-bit  {if(tmp & 0x80)         // output 'tmp', MSB to MOSIMOSI_H;elseMOSI_L;tmp = (tmp<<1);           // shift next bit into MSB..SCK_H;               // Set SCK high..ndelay(60);tmp |= get_MISO();          // capture current MISO bitSCK_L;                //then set SCK low againndelay(60);  }return tmp;            // return read tmp }uchar SPI_Read(uchar reg){  uchar 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}void SetRX_Mode(void){  CE_L;  ndelay(60);  SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);  udelay(1);  CE_H;  udelay(130);}uchar SPI_RW_Reg(uchar reg, uchar value){uchar status;     CSN_L;      ndelay(60);  status = SPI_RW(reg);   SPI_RW(value);          CSN_H;          ndelay(60);     return status;}uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uchar status,uint8_ctr;     CSN_L;  ndelay(60);status = SPI_RW(reg);  for(uint8_ctr=0;uint8_ctr<uchars;uint8_ctr++)  {    pBuf[uint8_ctr] = SPI_RW(0);    ndelay(20);  }  CSN_H;  ndelay(60);    return status;}uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){ uchar status,uint8_ctr;  CSN_L;  ndelay(60); status = SPI_RW(reg);     for(uint8_ctr=0; uint8_ctr<uchars; uint8_ctr++)  {     SPI_RW(*pBuf++);     ndelay(20);  }  CSN_H;     ndelay(60);    return status;}unsigned char nRF24L01_RxPacket(unsigned char* rx_buf){  unsigned char revale=0;  sta=SPI_Read(STATUS);   if(sta&(1<<RX_DR))  {     CE_L;              udelay(50);     SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);     SPI_RW_Reg(FLUSH_RX,0);     revale =1;  }  SPI_RW_Reg(WRITE_REG+STATUS,sta);  return revale;}void nRF24L01_TxPacket(unsigned char * tx_buf){CE_L;   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);  CE_H;  udelay(10);}static int nrf_open(struct inode *inode,struct file *filp){uchar flag=0;if(opencount==1)return -EBUSY;flag=init_NRF24L01();mdelay(100);if(flag==0){printk("unable to init device!\n");return -1;}else{opencount++;printk("device open success!\n");return 0;}}static ssize_t nrf_read(struct file *filp,char __user *buf,size_t count,loff_t *pos){uchar temp[32]={0};SetRX_Mode();mdelay(1000); if(nRF24L01_RxPacket(temp)){copy_to_user(buf,temp,count);}else{printk("Can't Receive data!\n");return 1;}printk("Read OK!\n");return 0;}static ssize_t nrf_write(struct file *filp,const char __user *buf,size_t count,loff_t *pos){if(copy_from_user(nrf_devp->data_tx,buf,count))    //?ó?úo?????????μ?ó??§????  {  printk("Can't Send Data !\n"); return -EFAULT;  }  nRF24L01_TxPacket(nrf_devp->data_tx);mdelay(1000);  SPI_RW_Reg(WRITE_REG+STATUS,0XFF);   printk("Write OK! \n");  return 0;}static int nrf_release(struct inode *inode,struct file *filp){printk("Device has been closed!\n");opencount--;return 0;}static struct file_operations nrf_fops={.owner=THIS_MODULE,.open=nrf_open,.release=nrf_release,.read=nrf_read,.write=nrf_write,};static int __init nrf_init(void){int ret,err;dev_t devno;ret=alloc_chrdev_region(&devno,0,1,DEVICE_NAME);nrf_major=MAJOR(devno);nrf_minor=MINOR(devno);#if 0devno=MKDEV(nrf_major,0);if(devno){ret=register_chrdev_region(devno,3,DEVICE_NAME);}else{ret=alloc_chrdev_region(&devno,0,1,DEVICE_NAME);nrf_major=MAJOR(devno);}#endifif(ret<0)return ret;nrf_devp=kmalloc(sizeof(struct nrf_dev),GFP_KERNEL);if(!nrf_devp){printk("Error get dev memory!\n");ret=-ENOMEM;goto fail_malloc;}memset(nrf_devp,0,sizeof(struct nrf_dev));cdev_init(&nrf_devp->cdev,&nrf_fops);nrf_devp->cdev.owner=THIS_MODULE;err=cdev_add(&nrf_devp->cdev,devno,1);if(err)printk("Add dev error!\n");return 0;fail_malloc:unregister_chrdev_region(devno,1);return ret;}static void __exit nrf_exit(void){cdev_del(&nrf_devp->cdev);kfree(nrf_devp);unregister_chrdev_region(MKDEV(nrf_major,0),1);}module_init(nrf_init);module_exit(nrf_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("TANG");

0 0
原创粉丝点击