刚刚接触到linux,有很多东西还不是很熟悉,希望大神指正。
前些日子做了一个项目远程家电控制系统,用的stm32f4;后面为了最求更高的境界,就前往学linux了,其中一万个坑呀。
就想到吧nrf24l01的驱动移植到linux上看行不,进过一段时间的尝试,成功了,虽然只是最简单的,没有用到中断,只是用到了模拟的spi,查询方式,不过至少是可行的。
总共有三个文件24l01.c 24l01.h my_nrf24l01_dev.c
文件24l01.c
#include "24l01.h"
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#define SPI_DELAY 1000
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x02}; //send addr
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //read addr
/**************************************************
Function: SPI_RW();
Description:
Writes one byte to nRF24L01, and return the byte read
from nRF24L01 during write, according to SPI protocol
**************************************************/
u8 SPI_RW(u8 byte)
{
u8 bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
{
MOSI((byte & 0x80)>>7); // output 'byte', MSB to MOSI
ndelay(SPI_DELAY);
byte = (byte << 1); // shift next bit into MSB..
SCK(1); // Set SCK high..
ndelay(SPI_DELAY);
byte |= MISO; // capture current MISO bit
SCK(0); // ..then set SCK low again
ndelay(SPI_DELAY);
}
return(byte); // return read byte
}
//init spi gpio
void NRF24L01_Init_Gpio(void){
//init miso mosi sck cs ce irq for spi
//miso ->> e.11
//mosi ->> e.12
//sck ->> e.13
//cs ->> g.2
//ce ->> g.5
//irq ->> g.6
//printk(KERN_DEBUG"init_nrf24l01_gpio");
s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
s3c2410_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_cfgpin(S3C2410_GPG(2), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_cfgpin(S3C2410_GPG(6), S3C2410_GPIO_INPUT);
s3c2410_gpio_pullup(S3C2410_GPG(0),0);
//s3c2410_gpio_pullup(S3C2410_GPE(12),1);
//s3c2410_gpio_pullup(S3C2410_GPE(13),1);
//s3c2410_gpio_pullup(S3C2410_GPG(2),1);
//s3c2410_gpio_pullup(S3C2410_GPG(6),1);
//s3c2410_gpio_pullup(S3C2410_GPG(5),1);
s3c2410_gpio_setpin(S3C2410_GPE(12), 0);
s3c2410_gpio_setpin(S3C2410_GPE(13), 0);
s3c2410_gpio_setpin(S3C2410_GPG(7), 0);
s3c2410_gpio_setpin(S3C2410_GPG(5), 0);
}
void NRF24L01_Init(void)
{
NRF24L01_Init_Gpio();
NRF24L01_CE(0);
NRF24L01_CSN(1);
mdelay(50);
NRF24L01_RX_Mode();
}
//check nrf2401
u8 NRF24L01_Check(void)
{
u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
u8 i;
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//ÐŽÈë5žö×֜ڵĵØÖ·.
NRF24L01_Read_Buf(TX_ADDR,buf,5); //¶Á³öÐŽÈëµÄµØÖ·
for(i=0;i<5;i++)if(buf[i]!=0XA5)break;
printk(KERN_DEBUG"i=%d\n",i);
if(i!=5)return 1;//fail
return 0; //suc
}
//SPIÐŽŒÄŽæÆ÷
//reg:Öž¶šŒÄŽæÆ÷µØÖ·
//value:ÐŽÈëµÄÖµ
u8 NRF24L01_Write_Reg(u8 reg,u8 value)
{
u8 status;
NRF24L01_CSN(0); //ʹÄÜSPIŽ«Êä
status =SPI_RW(reg);//·¢Ë͌ĎæÆ÷ºÅ
SPI_RW(value); //ÐŽÈëŒÄŽæÆ÷µÄÖµ
NRF24L01_CSN(1); //œûÖ¹SPIŽ«Êä
return(status); //·µ»Ø׎ֵ̬
}
//¶ÁÈ¡SPIŒÄŽæÆ÷Öµ
//reg:Òª¶ÁµÄŒÄŽæÆ÷
u8 NRF24L01_Read_Reg(u8 reg)
{
u8 reg_val;
NRF24L01_CSN(0); //ʹÄÜSPIŽ«Êä
SPI_RW(reg); //·¢Ë͌ĎæÆ÷ºÅ
reg_val=SPI_RW(0XFF);//¶ÁÈ¡ŒÄŽæÆ÷ÄÚÈÝ
NRF24L01_CSN(1); //œûÖ¹SPIŽ«Êä
return(reg_val); //·µ»Ø׎ֵ̬
}
//ÔÚÖž¶šÎ»ÖöÁ³öÖž¶š³€¶ÈµÄÊýŸÝ
//reg:ŒÄŽæÆ÷(λÖÃ)
//*pBuf:ÊýŸÝÖžÕë
//len:ÊýŸÝ³€¶È
//·µ»ØÖµ,ŽËŽÎ¶ÁµœµÄ׎̬ŒÄŽæÆ÷Öµ
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
{
u8 status,u8_ctr;
NRF24L01_CSN(0); //ʹÄÜSPIŽ«Êä
status=SPI_RW(reg);//·¢Ë͌ĎæÆ÷Öµ(λÖÃ),²¢¶Áȡ׎ֵ̬
for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI_RW(0XFF);//¶Á³öÊýŸÝ
NRF24L01_CSN(1); //¹Ø±ÕSPIŽ«Êä
return status; //·µ»Ø¶ÁµœµÄ׎ֵ̬
}
//ÔÚÖž¶šÎ»ÖÃÐŽÖž¶š³€¶ÈµÄÊýŸÝ
//reg:ŒÄŽæÆ÷(λÖÃ)
//*pBuf:ÊýŸÝÖžÕë
//len:ÊýŸÝ³€¶È
//·µ»ØÖµ,ŽËŽÎ¶ÁµœµÄ׎̬ŒÄŽæÆ÷Öµ
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
u8 status,u8_ctr;
NRF24L01_CSN(0); //ʹÄÜSPIŽ«Êä
status = SPI_RW(reg);//·¢Ë͌ĎæÆ÷Öµ(λÖÃ),²¢¶Áȡ׎ֵ̬
for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI_RW(*pBuf++); //ÐŽÈëÊýŸÝ
NRF24L01_CSN(1); //¹Ø±ÕSPIŽ«Êä
return status; //·µ»Ø¶ÁµœµÄ׎ֵ̬
}
//Æô¶¯NRF24L01·¢ËÍÒ»ŽÎÊýŸÝ
//txbuf:Žý·¢ËÍÊýŸÝÊ×µØÖ·
//·µ»ØÖµ:·¢ËÍÍê³É׎¿ö
#include <linux/time.h>
u8 NRF24L01_TxPacket(u8 *txbuf)
{
u8 sta;
u8 i=0;
//SPIHighSpeed(SPI_BaudRatePrescaler_256);//spiËÙ¶ÈΪ10.5Mhz£š24L01µÄ×îŽóSPIʱÖÓΪ10Mhz£©
NRF24L01_CE(0);
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//ÐŽÊýŸÝµœTX BUF 32žö×ÖœÚ
NRF24L01_CE(1);//Æô¶¯·¢ËÍ
//printk(KERN_DEBUG"send data");
while(NRF24L01_IRQ!=0&&(i<50)){i++;};//µÈŽý·¢ËÍÍê³É
sta=NRF24L01_Read_Reg(STATUS); //¶Áȡ׎̬ŒÄŽæÆ÷µÄÖµ
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //Çå³ýTX_DS»òMAX_RTÖжϱêÖŸ
if(sta&MAX_TX)//Žïµœ×îŽóÖØ·¢ŽÎÊý
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//Çå³ýTX FIFOŒÄŽæÆ÷
return MAX_TX;
}
if(sta&TX_OK)//·¢ËÍÍê³É
{
return TX_OK;
}
return 0xff;//ÆäËûÔÒò·¢ËÍʧ°Ü
}
//Æô¶¯NRF24L01·¢ËÍÒ»ŽÎÊýŸÝ
//txbuf:Žý·¢ËÍÊýŸÝÊ×µØÖ·
//·µ»ØÖµ:0£¬œÓÊÕÍê³É£»ÆäËû£¬ŽíÎóŽúÂë
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
u8 sta;
//SPIHighSpeed(SPI_BaudRatePrescaler_256); //spiËÙ¶ÈΪ10.5Mhz£š24L01µÄ×îŽóSPIʱÖÓΪ10Mhz£©
sta=NRF24L01_Read_Reg(STATUS); //¶Áȡ׎̬ŒÄŽæÆ÷µÄÖµ
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //Çå³ýTX_DS»òMAX_RTÖжϱêÖŸ
if(sta&RX_OK)//œÓÊÕµœÊýŸÝ
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//¶ÁÈ¡ÊýŸÝ
NRF24L01_Write_Reg(FLUSH_RX,0xff);//Çå³ýRX FIFOŒÄŽæÆ÷
return 0;
}
return 1;//ûÊÕµœÈκÎÊýŸÝ
}
//žÃº¯Êý³õÊŒ»¯NRF24L01µœRXģʜ
//ÉèÖÃRXµØÖ·,ÐŽRXÊýŸÝ¿í¶È,Ñ¡ÔñRFƵµÀ,²šÌØÂʺÍLNA HCURR
//µ±CE±äžßºó,ŒŽœøÈëRXģʜ,²¢¿ÉÒÔœÓÊÕÊýŸÝÁË
void NRF24L01_RX_Mode(void)
{
NRF24L01_CE(0);
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//ÐŽRXœÚµãµØÖ·
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //ʹÄÜÍšµÀ0µÄ×Ô¶¯ÓŠŽð
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);//ʹÄÜÍšµÀ0µÄœÓÊÕµØÖ·
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //ÉèÖÃRFÍšÐÅƵÂÊ
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//Ñ¡ÔñÍšµÀ0µÄÓÐЧÊýŸÝ¿í¶È
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//ÉèÖÃTX·¢Éä²ÎÊý,0dbÔöÒæ,2Mbps,µÍÔëÉùÔöÒ濪Æô
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//ÅäÖûù±Ÿ¹€×÷ģʜµÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,œÓÊÕģʜ
NRF24L01_CE(1); //CEΪžß,œøÈëœÓÊÕģʜ
}
//žÃº¯Êý³õÊŒ»¯NRF24L01µœTXģʜ
//ÉèÖÃTXµØÖ·,ÐŽTXÊýŸÝ¿í¶È,ÉèÖÃRX×Ô¶¯ÓŠŽðµÄµØÖ·,Ìî³äTX·¢ËÍÊýŸÝ,Ñ¡ÔñRFƵµÀ,²šÌØÂʺÍLNA HCURR
//PWR_UP,CRCʹÄÜ
//µ±CE±äžßºó,ŒŽœøÈëRXģʜ,²¢¿ÉÒÔœÓÊÕÊýŸÝÁË
//CEΪžßŽóÓÚ10us,ÔòÆô¶¯·¢ËÍ.
void NRF24L01_TX_Mode(void)
{
NRF24L01_CE(0);
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//ÐŽTXœÚµãµØÖ·
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //ÉèÖÃTXœÚµãµØÖ·,Ö÷ҪΪÁËʹÄÜACK
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //ʹÄÜÍšµÀ0µÄ×Ô¶¯ÓŠŽð
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //ʹÄÜÍšµÀ0µÄœÓÊÕµØÖ·
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//ÉèÖÃ×Ô¶¯ÖØ·¢ŒäžôʱŒä:500us + 86us;×îŽó×Ô¶¯ÖØ·¢ŽÎÊý:10ŽÎ
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //ÉèÖÃRFÍšµÀΪ40
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //ÉèÖÃTX·¢Éä²ÎÊý,0dbÔöÒæ,2Mbps,µÍÔëÉùÔöÒ濪Æô
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //ÅäÖûù±Ÿ¹€×÷ģʜµÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,œÓÊÕģʜ,¿ªÆôËùÓÐÖжÏ
NRF24L01_CE(1);//CEΪžß,10usºóÆô¶¯·¢ËÍ
}
u8 NRF24L01_SEND_Data(u8 *data){
u8 result;
NRF24L01_TX_Mode();
result=NRF24L01_TxPacket((u8*)data);
NRF24L01_RX_Mode();
return result;
}
文件24l01.h
#ifndef __24L01_H
#define __24L01_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <linux/gpio.h>
#include <linux/delay.h>
//
//NRF24L01ŒÄŽæÆ÷²Ù×÷ÃüÁî
#define NRF_READ_REG 0x00 //¶ÁÅäÖÌĎæÆ÷,µÍ5λΪŒÄŽæÆ÷µØÖ·
#define NRF_WRITE_REG 0x20 //ÐŽÅäÖÌĎæÆ÷,µÍ5λΪŒÄŽæÆ÷µØÖ·
#define RD_RX_PLOAD 0x61 //¶ÁRXÓÐЧÊýŸÝ,1~32×ÖœÚ
#define WR_TX_PLOAD 0xA0 //ÐŽTXÓÐЧÊýŸÝ,1~32×ÖœÚ
#define FLUSH_TX 0xE1 //Çå³ýTX FIFOŒÄŽæÆ÷.·¢ÉäģʜÏÂÓÃ
#define FLUSH_RX 0xE2 //Çå³ýRX FIFOŒÄŽæÆ÷.œÓÊÕģʜÏÂÓÃ
#define REUSE_TX_PL 0xE3 //ÖØÐÂʹÓÃÉÏÒ»°üÊýŸÝ,CEΪžß,ÊýŸÝ°ü±»²»¶Ï·¢ËÍ.
#define NOP 0xFF //¿Õ²Ù×÷,¿ÉÒÔÓÃÀŽ¶Á׎̬ŒÄŽæÆ÷
//SPI(NRF24L01)ŒÄŽæÆ÷µØÖ·
#define CONFIG 0x00 //ÅäÖÌĎæÆ÷µØÖ·;bit0:1œÓÊÕģʜ,0·¢Éäģʜ;bit1:µçÑ¡Ôñ;bit2:CRCģʜ;bit3:CRCʹÄÜ;
//bit4:ÖжÏMAX_RT(Žïµœ×îŽóÖØ·¢ŽÎÊýÖжÏ)ʹÄÜ;bit5:ÖжÏTX_DSʹÄÜ;bit6:ÖжÏRX_DRʹÄÜ
#define EN_AA 0x01 //ʹÄÜ×Ô¶¯ÓŠŽð¹ŠÄÜ bit0~5,¶ÔÓŠÍšµÀ0~5
#define EN_RXADDR 0x02 //œÓÊÕµØÖ·ÔÊÐí,bit0~5,¶ÔÓŠÍšµÀ0~5
#define SETUP_AW 0x03 //ÉèÖõØÖ·¿í¶È(ËùÓÐÊýŸÝÍšµÀ):bit1,0:00,3×ÖœÚ;01,4×ÖœÚ;02,5×ÖœÚ;
#define SETUP_RETR 0x04 //œšÁ¢×Ô¶¯ÖØ·¢;bit3:0,×Ô¶¯ÖØ·¢ŒÆÊýÆ÷;bit7:4,×Ô¶¯ÖØ·¢ÑÓʱ 250*x+86us
#define RF_CH 0x05 //RFÍšµÀ,bit6:0,¹€×÷ÍšµÀƵÂÊ;
#define RF_SETUP 0x06 //RFŒÄŽæÆ÷;bit3:Ž«ÊäËÙÂÊ(0:1Mbps,1:2Mbps);bit2:1,·¢É乊ÂÊ;bit0:µÍÔëÉù·ÅŽóÆ÷ÔöÒæ
#define STATUS 0x07 //׎̬ŒÄŽæÆ÷;bit0:TX FIFOÂú±êÖŸ;bit3:1,œÓÊÕÊýŸÝÍšµÀºÅ(×îŽó:6);bit4,Žïµœ×î¶àŽÎÖØ·¢
//bit5:ÊýŸÝ·¢ËÍÍê³ÉÖжÏ;bit6:œÓÊÕÊýŸÝÖжÏ;
#define MAX_TX 0x10 //Žïµœ×îŽó·¢ËÍŽÎÊýÖжÏ
#define TX_OK 0x20 //TX·¢ËÍÍê³ÉÖжÏ
#define RX_OK 0x40 //œÓÊÕµœÊýŸÝÖжÏ
#define OBSERVE_TX 0x08 //·¢ËÍŒì²âŒÄŽæÆ÷,bit7:4,ÊýŸÝ°ü¶ªÊ§ŒÆÊýÆ÷;bit3:0,ÖØ·¢ŒÆÊýÆ÷
#define CD 0x09 //ÔزšŒì²âŒÄŽæÆ÷,bit0,ÔزšŒì²â;
#define RX_ADDR_P0 0x0A //ÊýŸÝÍšµÀ0œÓÊÕµØÖ·,×îŽó³€¶È5žö×ÖœÚ,µÍ×ÖœÚÔÚÇ°
#define RX_ADDR_P1 0x0B //ÊýŸÝÍšµÀ1œÓÊÕµØÖ·,×îŽó³€¶È5žö×ÖœÚ,µÍ×ÖœÚÔÚÇ°
#define RX_ADDR_P2 0x0C //ÊýŸÝÍšµÀ2œÓÊÕµØÖ·,×îµÍ×֜ڿÉÉèÖÃ,žß×ÖœÚ,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P3 0x0D //ÊýŸÝÍšµÀ3œÓÊÕµØÖ·,×îµÍ×֜ڿÉÉèÖÃ,žß×ÖœÚ,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P4 0x0E //ÊýŸÝÍšµÀ4œÓÊÕµØÖ·,×îµÍ×֜ڿÉÉèÖÃ,žß×ÖœÚ,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P5 0x0F //ÊýŸÝÍšµÀ5œÓÊÕµØÖ·,×îµÍ×֜ڿÉÉèÖÃ,žß×ÖœÚ,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define TX_ADDR 0x10 //·¢Ë͵ØÖ·(µÍ×ÖœÚÔÚÇ°),ShockBurstTMģʜÏÂ,RX_ADDR_P0ÓëŽËµØÖ·ÏàµÈ
#define RX_PW_P0 0x11 //œÓÊÕÊýŸÝÍšµÀ0ÓÐЧÊýŸÝ¿í¶È(1~32×ÖœÚ),ÉèÖÃΪ0Ôò·Ç·š
#define RX_PW_P1 0x12 //œÓÊÕÊýŸÝÍšµÀ1ÓÐЧÊýŸÝ¿í¶È(1~32×ÖœÚ),ÉèÖÃΪ0Ôò·Ç·š
#define RX_PW_P2 0x13 //œÓÊÕÊýŸÝÍšµÀ2ÓÐЧÊýŸÝ¿í¶È(1~32×ÖœÚ),ÉèÖÃΪ0Ôò·Ç·š
#define RX_PW_P3 0x14 //œÓÊÕÊýŸÝÍšµÀ3ÓÐЧÊýŸÝ¿í¶È(1~32×ÖœÚ),ÉèÖÃΪ0Ôò·Ç·š
#define RX_PW_P4 0x15 //œÓÊÕÊýŸÝÍšµÀ4ÓÐЧÊýŸÝ¿í¶È(1~32×ÖœÚ),ÉèÖÃΪ0Ôò·Ç·š
#define RX_PW_P5 0x16 //œÓÊÕÊýŸÝÍšµÀ5ÓÐЧÊýŸÝ¿í¶È(1~32×ÖœÚ),ÉèÖÃΪ0Ôò·Ç·š
#define NRF_FIFO_STATUS 0x17 //FIFO׎̬ŒÄŽæÆ÷;bit0,RX FIFOŒÄŽæÆ÷¿Õ±êÖŸ;bit1,RX FIFOÂú±êÖŸ;bit2,3,±£Áô
//bit4,TX FIFO¿Õ±êÖŸ;bit5,TX FIFOÂú±êÖŸ;bit6,1,Ñ»··¢ËÍÉÏÒ»ÊýŸÝ°ü.0,²»Ñ»·;
//
//
#define NRF24L01_CE(a) s3c2410_gpio_setpin(S3C2410_GPG(5), (a)) //
#define NRF24L01_CSN(a) s3c2410_gpio_setpin(S3C2410_GPG(2), (a))//
#define NRF24L01_IRQ s3c2410_gpio_getpin(S3C2410_GPG(6)) //
#define MISO s3c2410_gpio_getpin(S3C2410_GPG(0))
#define MOSI(a) s3c2410_gpio_setpin(S3C2410_GPE(12), (a))
#define SCK(a) s3c2410_gpio_setpin(S3C2410_GPE(13), (a))
//24L01·¢ËÍœÓÊÕÊýŸÝ¿í¶È¶šÒå
#define TX_ADR_WIDTH 5 //5×֜ڵĵØÖ·¿í¶È
#define RX_ADR_WIDTH 5 //5×֜ڵĵØÖ·¿í¶È
#define TX_PLOAD_WIDTH 32 //20×֜ڵÄÓû§ÊýŸÝ¿í¶È
#define RX_PLOAD_WIDTH 32 //20×֜ڵÄÓû§ÊýŸÝ¿í¶È
void NRF24L01_Init(void);//³õÊŒ»¯
void NRF24L01_RX_Mode(void);//ÅäÖÃΪœÓÊÕģʜ
void NRF24L01_TX_Mode(void);//ÅäÖÃΪ·¢ËÍģʜ
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//ÐŽÊýŸÝÇø
u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);//¶ÁÊýŸÝÇø
u8 NRF24L01_Read_Reg(u8 reg); //¶ÁŒÄŽæÆ÷
u8 NRF24L01_Write_Reg(u8 reg, u8 value);//ÐŽŒÄŽæÆ÷
u8 NRF24L01_Check(void);//Œì²é24L01ÊÇ·ñŽæÔÚ
u8 NRF24L01_TxPacket(u8 *txbuf);//·¢ËÍÒ»žö°üµÄÊýŸÝ
u8 NRF24L01_RxPacket(u8 *rxbuf);//œÓÊÕÒ»žö°üµÄÊýŸÝ
u8 NRF24L01_SEND_Data(u8 *data);
// USER START (Optionally insert additional static code)
// USER END
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
文件my_nrf24l01_dev.c 驱动文件
#include <linux/miscdevice.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include "24l01.h"
u8 nrf24l01_buffer[32]={0};
const char *MY_DEVICE_NAME="nrf24l01_dev";
static int sbc2440_nrf24l01_ioctl(
struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg){
printk(KERN_DEBUG"ioctl");
//nrf24l01 cs enable or disable
s3c2410_gpio_setpin(S3C2410_GPG(2), cmd);
return 0;
}
static int my_open(struct inode *id,struct file* filp){
char flag=0;
NRF24L01_Init();
mdelay(50);
try_module_get(THIS_MODULE);
flag=NRF24L01_Check();
// flag for 1 fail
if(flag==1){
return -1;
}
return 0;
}
static int my_release(struct inode *id ,struct file* filp){
module_put(THIS_MODULE);
return 0;
}
static ssize_t my_read(struct file *mfile ,char __user *user,size_t t,
loff_t *f){
NRF24L01_RX_Mode();
if(NRF24L01_RxPacket(nrf24l01_buffer)==1){
return -EFAULT;
}
if(copy_to_user(user,nrf24l01_buffer,32)){
return -EFAULT;
}
return sizeof(nrf24l01_buffer);
}
static ssize_t my_write(struct file *mfile,const char __user *user,
size_t t,loff_t *f){
int result;
char data[32]={0};
// printk(KERN_DEBUG"write..");
//copy_from_user(data,user,32);
NRF24L01_TX_Mode();
result=NRF24L01_TxPacket((u8*)user);
ndelay(20);
if(result==1){
return -EFAULT;
}
return sizeof(nrf24l01_buffer);
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.ioctl = sbc2440_nrf24l01_ioctl,
.read = my_read,
.write = my_write,
.open = my_open,
.release= my_release,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "my_nrf24l01",
.fops = &dev_fops,
};
static int __init dev_init(void){
int ret;
printk(KERN_DEBUG"init..");
NRF24L01_Init();
ret = misc_register(&misc);
return ret;
}
static void __exit dev_exit(void){
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lotoohe Inc.");
在Kconfig中的配置,直接编译成为驱动模块
利用insmod命令加载模块:insmod my_nrf24l01_dev.ko
利用rmmod 命令卸载模块:rmmod my_nrf24l01_dev
config MINI2440_LOT_NRF24L01
tristate "NRF24L01 drvier for lotoohe mini2440 development boards"
depends on MACH_MINI2440
default y if MACH_MINI2440
help
this is NRF24L01 drvier for lotoohe mini2440 devlopment boards
obj-$(CONFIG_MINI2440_LOT_NRF24L01) += my_nrf24l01.o
my_nrf24l01-objs = 24l01.o my_nrf24l01_dev.o
这只是一个最简单的版本,希望大家指正,我已经测试过能够正常使用。