|  | 
 
| 本帖最后由 维C1° 于 2013-11-30 20:05 编辑 
 nrf24l01是用普通引脚来模拟SPI时序的,在裸机上调试成功了,可以发射可以接收,但是把它丢到驱动里,就出问题了.发送数据不成功。以下是驱动内容,麻烦各位帮个忙看看,我调了好久了。
 这里由于字数要求省去头文件的定义了
 #define DEVICE_NAME  "NRF24L01"  //设备名称
 //引脚相关的宏定义
 #define CSN       S3C2410_GPG0
 #define CSN_OUTP  S3C2410_GPG0_OUTP
 #define CE        S3C2410_GPG3
 #define CE_OUTP   S3C2410_GPG3_OUTP
 #define MOSI      S3C2410_GPG5
 #define MOSI_OUTP S3C2410_GPG5_OUTP
 #define SCK       S3C2410_GPG6
 #define SCK_OUTP  S3C2410_GPG6_OUTP
 #define MISO      S3C2410_GPG7
 #define MISO_INP  S3C2410_GPG7_INP
 #define IRQ       S3C2410_GPG11
 #define IRQ_INP   S3C2410_GPG11_INP
 
 //NRF24L01端口定义
 #define CE_OUT      s3c2410_gpio_cfgpin(CE, CE_OUTP)
 #define CE_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)
 #define SCK_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)
 #define MISO_STU    s3c2410_gpio_getpin(MISO)
 
 #define IRQ_IN      s3c2410_gpio_cfgpin(IRQ, IRQ_INP)
 #define IRQ_STU     s3c2410_gpio_getpin(IRQ)
 
 #define MOSI_OUT    s3c2410_gpio_cfgpin(MOSI, MOSI_OUTP)
 #define MOSI_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)
 #define CSN_UP      s3c2410_gpio_pullup(CSN, 1)
 #define CSN_L       s3c2410_gpio_setpin(CSN, 0)
 #define CSN_H       s3c2410_gpio_setpin(CSN, 1)
 
 //NRF24L01
 #define TX_ADDR_WITDH    5        // 5 uint8s TX address width
 #define RX_ADDR_WITDH    5        // 5 uint8s RX address width
 #define TX_DATA_WITDH    4        // 20 uint8s TX payload
 #define RX_DATA_WITDH    4        // 20 uint8s TX payload
 (因为字数的限制,这里略去一些NRF24L01寄存器指令 和寄存器地址的宏定义声明了)
 ...............................................
 
 //全局变量
 U8 TxBuf[4]={ 0x00,0x00,0x00,0x00};
 U8 test_TxBuf[4]={ 0x01,0x01,0x00,0x00};
 U8 opencount = 0;
 U8 TxAddr[]={0x34,0x43,0x10,0x10,0x01};//发送地址
 U8 RevTempDate[5];//最后一位用来存放结束标志
 
 void NRFDelay(U16 t)
 {
 unsigned int x,y;
 for(x=t;x>0;x--)
 for(y=20;y>0;y--);
 }
 
 //NRF24L01初始化
 U8 NRF24L01Int(void)
 {
 NRFDelay(2);//让系统什么都不干
 CE_UP;
 CSN_UP;
 SCK_UP;
 MOSI_UP;
 CE_OUT;
 CSN_OUT;
 SCK_OUT;
 MOSI_OUT;
 MISO_IN;
 IRQ_IN;
 
 udelay(500);
 CE_L;
 ndelay(60);
 CSN_H;
 ndelay(60);
 SCK_L;
 ndelay(60);                      这里我有一个疑问,这个延时函数好像延时不对, ndelay(1) ,ndelay(10)的延时时间一样,这是怎么回事?
 return 1;
 }
 //功能:NRF24L01的SPI写时序
 U8 NRFSPI(U8 date)
 {
 U8 i;
 for(i=0 ;i<8 ;i++)
 {
 if(date & 0x80)
 MOSI_H;
 else
 MOSI_L;
 date=date<<1;
 SCK_H;
 ndelay(10);                                       在裸机上这些延时不需要写,在驱动上,有网友说要参照24l01的手册来加延时,但是
 加上必要的延时也没有什么作用啊
 date |= MISO_STU;
 SCK_L;
 ndelay(10);
 }
 return(date);
 }
 
 
 //NRF24L01的SPI时序
 U8 NRFReadReg(U8 RegAddr)
 {
 U8 BackDate;
 CSN_L;
 ndelay(10);
 NRFSPI(RegAddr);
 BackDate=NRFSPI(0x00);
 CSN_H;
 ndelay(70);
 return(BackDate);
 }
 
 //NRF24L01读写寄存器函数
 U8 NRFWriteReg(U8 RegAddr,U8 date)
 {
 U8 BackDate;
 CSN_L;
 BackDate=NRFSPI(RegAddr);//写入地址
 NRFSPI(date);//写入值
 CSN_H;
 return(BackDate);
 }
 
 //SPI读取RXFIFO寄存器的值
 U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen)
 {    U8 BackDate,i;
 CSN_L; //启动时序
 BackDate=NRFSPI(RegAddr);//写入要读取的寄存器地址
 for(i=0;i<DateLen;i++) //读取数据
 {
 RxDate=NRFSPI(0);
 ndelay(1);
 }
 CSN_H;
 return(BackDate);
 }
 
 //SPI写入TXFIFO寄存器的值
 U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen)
 {   U8 BackDate,i;
 CSN_L;
 BackDate=NRFSPI(RegAddr);//写入要写入寄存器的地址
 for(i=0;i<DateLen;i++)//写入数据
 {
 NRFSPI(*TxDate++);
 ndelay(1);
 }
 CSN_H;
 return(BackDate);
 }
 //NRF设置为发送模式并发送数据
 void NRFSetTxMode(U8 *TxDate)
 {  //发送模式
 CE_L;
 NRFWriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_ADDR_WITDH);//写寄存器指令+P0地址使能指令+发送地址+地址宽度
 NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);//为了应答接收设备,接收通道0地址和发送地址相同
 NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WITDH);//写入数据
 /******下面有关寄存器配置**************/
 NRFWriteReg(W_REGISTER+EN_AA,0x01);       // 使能接收通道0自动应答
 NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);   // 使能接收通道0
 NRFWriteReg(W_REGISTER+SETUP_RETR,0x0a);  // 自动重发延时等待250us+86us,自动重发10次
 NRFWriteReg(W_REGISTER+RF_CH,0x40);         // 选择射频通道0x40
 NRFWriteReg(W_REGISTER+RF_SETUP,0x07);    // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
 NRFWriteReg(W_REGISTER+CONFI_G,0x0e);      // CRC使能,16位CRC校验,上电
 CE_H;
 mdelay(1);
 }
 //NRF设置为接收模式并接收数据
 //接收模式
 void NRFSetRXMode(void)
 {
 CE_L;
 NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);  // 接收设备接收通道0使用和发送设备相同的发送地址
 NRFWriteReg(W_REGISTER+EN_AA,0x01);               // 使能接收通道0自动应答
 NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);           // 使能接收通道0
 NRFWriteReg(W_REGISTER+RF_CH,0x40);                 // 选择射频通道0x40
 NRFWriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WITDH);  // 接收通道0选择和发送通道相同有效数据宽度
 NRFWriteReg(W_REGISTER+RF_SETUP,0x07);            // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
 NRFWriteReg(W_REGISTER+CONFI_G,0x0f);             // CRC使能,16位CRC校验,上电,接收模式
 CE_H;
 NRFDelay(30);
 }
 U8 CheckACK(void)
 {
 U8 sta;
 sta=NRFReadReg(R_REGISTER+STATUS);
 if((sta&0x20)||(sta&0x10))
 {
 NRFWriteReg(W_REGISTER+STATUS,0XFF);
 CSN_L;
 NRFSPI(FLUSH_TX);//用于清空FIFO !!关键!!不然会出现意想不到的后果!!!大家记住!!
 CSN_H;
 return 0;
 }
 else
 return 1;
 }
 //文件的写函数
 static int nrf24l01_write(struct file *filp, const char *buffer,size_t count)
 {
 if(copy_from_user(TxBuf,buffer,count))  //从内核空间复制到用户空间
 {
 printk("Can't Send Data! " ) ;
 return -EFAULT;
 }
 NRFSetTxMode(TxBuf);
 if(!CheckACK())
 {
 printk ( "Write Success!\n" ) ;
 }
 else
 printk ( "Write Faild!\n" ) ;
 return 1;
 }
 //的读函数
 static int nrf24l01_read(struct file *filp, char *buffer,size_t count)
 {
 U8 sta;
 NRFSetRXMode();
 sta=NRFReadReg(R_REGISTER+STATUS);//发送数据后读取状态寄存器
 if(sta & 0x40)               // 判断是否接收到数据
 {
 CE_L; //待机
 NRFReadRxDate(R_RX_PAYLOAD,RevTempDate,RX_DATA_WITDH);// 从RXFIFO读取数据 接收4位即可,后一位位结束位
 NRFWriteReg(W_REGISTER+STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标
 //return(1);   //读取数据完成标志
 }
 NRFWriteReg(W_REGISTER+STATUS,0xff);
 printk("read \n" ) ;
 }
 static int nrf24l01_open(struct inode *node, struct file *file)
 {
 U8 flag = 0,a=1;
 if(opencount == 1) return -EBUSY;
 flag = NRF24L01Int();
 /*
 while(1)
 {
 CE_H;
 ndelay(10);                         我是在这里测延时函数的延时时间的,用示波器看引脚电平的变化,测出来 ndelay()延时不准确
 CE_L;
 ndelay(1);
 }
 */
 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,
 .write = nrf24l01_write,
 .read = nrf24l01_read,
 .release = nrf24l01_release,
 .open=nrf24l01_open,
 };
 static struct miscdevice misc = {
 .minor = MISC_DYNAMIC_MINOR,
 .name = DEVICE_NAME,
 .fops = &nrf24l01_fops,
 };
 static int __init nrf24l01_init(void)
 {
 int ret;
 printk("Initial driver for NRF24L01......................\n" ) ;
 ret = misc_register(&misc);
 mdelay(10);
 if (ret < 0)
 {
 printk(DEVICE_NAME " can't register major number\n");
 return ret;
 }
 else
 {
 printk(DEVICE_NAME " register success\n");
 return 0;
 }
 }
 static void __exit nrf24l01_exit(void)
 {
 misc_deregister(&misc);
 printk("NRF24L01 unregister success \n" ) ;
 }
 module_init(nrf24l01_init);
 module_exit(nrf24l01_exit);
 
 | 
 |