ARM9 2440硬件SPI驱动程序-NRF24L01

发布者:Xiangtan最新更新时间:2017-09-23 来源: eefocus关键字:ARM9  SPI  驱动程序  NRF24L01 手机看文章 扫描二维码
随时随地手机看文章
从开始接触,到驱动编写调试完成,前前后后花费10多天,网上浏览了一下,目前还没有找到硬件SPI控制NRF24L01的驱动程序,绝大多数都是软件SPI,但是软件SPI不好,不稳定,既然都写驱动程序了,肯定要用硬件SPI啦,这样才能学到东西。学习的过程中,通过看韦东山的SPI视频,和参考他写的两个驱动程序。然后花费了四五天,终于将驱动写好了。
这个驱动可以通过ioctl切换接收和发送模式,通过read,write选择接收数据还是发送数据,废话少说,上代码
   #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nrf.h"/* 构造注册 spi_driver */#define RX_MODE   0xf1#define TX_MODE   0xf2static int major;static struct class *class;static int spi_NRF24L01_ce_pin;static unsigned char *ker_buf;static struct spi_device *spi_NRF24L01_dev;static unsigned char  opencount = 0;static volatile int int_flag = 0;static DECLARE_WAIT_QUEUE_HEAD(nrf24l01_waitq);   /*生成一个等待队列头wait_queue_head_t,名字为nrf24l01_waitq*/static  unsigned char TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x10};    //本地地址static  unsigned char RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x10};    //接收地址struct pin_desc{                unsigned int pin;                unsigned int key_val;
};/*引脚描述结构体*/struct pin_desc pins_desc[2]={  /*按下时 :0x01 0x02   ... 松开始0x81 0x 82 ...*/
               {S3C2410_GPG(0),0x01},

}; static uint8  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,
};static  uint8  RxBuf[RxBufSize]={0};static void NRF24L01_Set_CE(char val)
{
    s3c2410_gpio_setpin(spi_NRF24L01_ce_pin, val);
}/*寄存器访问函数:用来设置 24L01 的寄存器的值。基本思路就是通过 WRITE_REG 命令(也
就是 0x20+寄存器地址)把要设定的值写到相应的寄存器地址里面去,并读取返回值。对于
函数来说也就是把 value 值写到 reg 寄存器中*/static unsigned char SPI_RW_Reg(unsigned char reg,unsigned char value)
{    unsigned char status;    unsigned char tx_buf[2];    unsigned char rx_buf[2];
    tx_buf[0] = reg;
    tx_buf[1] = value;
    spi_write(spi_NRF24L01_dev, tx_buf, 2);
    status = rx_buf[0]; 
    return (status);        
}/*读取寄存器值的函数:基本思路就是通过 READ_REG 命令(也就是 0x00+寄存器地址),把
寄存器中的值读出来。对于函数来说也就是把 reg 寄存器的值读到 reg_val 中去*/static void SPI_Read(int *pMID, int *pDID,unsigned char reg)
{    unsigned char tx_buf[2];    unsigned char rx_buf[2];
    tx_buf[0] = reg;
    tx_buf[1] = 0x00;
    spi_write_then_read(spi_NRF24L01_dev, tx_buf, 2, rx_buf, 2);
    *pMID = rx_buf[0];
    *pDID = rx_buf[1];  
} /*接收缓冲区访问函数:主要用来在接收时读取 FIFO 缓冲区中的值。基本思路就是通过
READ_REG 命令把数据从接收 FIFO(RD_RX_PLOAD)中读出并存到数组里面去*///static unsigned char SPI_Read_Buf(unsigned char reg,unsigned char * ker_buf,unsigned char bytes)static void SPI_Read_Buf(unsigned char reg, unsigned char * buf, int len)
{    /* spi_write_then_read规定了tx_cnt+rx_cnt < 32
     * 所以对于大量数据的读取,不能使用该函数
     */
    unsigned char i=0;  
    unsigned char tx_buf[1];    unsigned char tx_buf1[len];    struct spi_transfer t[] = {
            {
                .tx_buf     = tx_buf,
                .len        = 1,
            },
            {
                .tx_buf     = tx_buf1,
                .rx_buf     = buf,
                .len        = len,
            },
        };    struct spi_message  m;    for(i=0;i

这个是头文件 nrf.h

//NRF24L01#define TX_ADR_WIDTH    5        // 5 uint8s TX address width#define RX_ADR_WIDTH    5        // 5 uint8s RX address width#define TX_PLOAD_WIDTH  32    // 20 uint8s TX payload#define RX_PLOAD_WIDTH  32       // 20 uint8s TX payload//NRF24L01寄存器指令#define READ_REG        0x00    // 读寄存器指令#define WRITE_REG       0x20    // 写寄存器指令#define RD_RX_PLOAD     0x61    // 读取接收数据指令#define WR_TX_PLOAD     0xA0    // 写待发数据指令#define FLUSH_TX        0xE1    // 冲洗发送 FIFO指令#define FLUSH_RX        0xE2    // 冲洗接收 FIFO指令#define REUSE_TX_PL     0xE3    // 定义重复装载数据指令#define NOP             0xFF    // 保留//SPI(nRF24L01)寄存器地址#define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA           0x01  // 自动应答功能设置#define EN_RXADDR       0x02  // 可用信道设置#define SETUP_AW        0x03  // 收发地址宽度设置#define SETUP_RETR      0x04  // 自动重发功能设置#define RF_CH           0x05  // 工作频率设置#define RF_SETUP        0x06  // 发射速率、功耗功能设置#define STATUS          0x07  // 状态寄存器#define OBSERVE_TX      0x08  // 发送监测功能#define CD              0x09  // 地址检测          #define RX_ADDR_P0      0x0A  // 频道0接收数据地址#define RX_ADDR_P1      0x0B  // 频道1接收数据地址#define RX_ADDR_P2      0x0C  // 频道2接收数据地址#define RX_ADDR_P3      0x0D  // 频道3接收数据地址#define RX_ADDR_P4      0x0E  // 频道4接收数据地址#define RX_ADDR_P5      0x0F  // 频道5接收数据地址#define TX_ADDR         0x10  // 发送地址寄存器#define RX_PW_P0        0x11  // 接收频道0接收数据长度#define RX_PW_P1        0x12  // 接收频道0接收数据长度#define RX_PW_P2        0x13  // 接收频道0接收数据长度#define RX_PW_P3        0x14  // 接收频道0接收数据长度#define RX_PW_P4        0x15  // 接收频道0接收数据长度#define RX_PW_P5        0x16  // 接收频道0接收数据长度#define FIFO_STATUS     0x17  // FIFO栈入栈出状态寄存器设置#define MAX_TX          0x10  //达到最大发送次数中断#define TX_OK           0x20  //TX发送完成中断#define RX_OK           0x40  //接收到数据中断#define TxBufSize    32#define RxBufSize    32typedef unsigned int uint16 ;
typedef unsigned char uint8 ;


关键字:ARM9  SPI  驱动程序  NRF24L01 引用地址:ARM9 2440硬件SPI驱动程序-NRF24L01

上一篇:STM32 软件模拟SPI时序驱动NRF24L01
下一篇:STM32值SPI的使用及SPI初始化注意事项

推荐阅读最新更新时间:2024-03-16 15:38

stm32---SPI与外部FLASH
stm32外部flash是EN25QXX 芯片 使用 STM32F1 的 SPI 和外部 FLASH(EN25QXX)进行通信,实现数据的读写 操作。本章要实现的功能是:首先检测外部 FLASH 是否正常,然后使用 K__UP 和 K_DOWN 键控制 FLASH 的写入和读取,并将 数据显示在 串口助手上,同时控制 D1 指示灯不断闪烁,提示系统正常 运行 W25Q128 将 16M 的容量分为 256 个块( Block),每个块大小为 64K 字 节,每个块又分为 16 个扇区( Sector),每个扇区 4K 个字节。 W25Q128 的最小擦除单位为一个扇区,也就是每次必须擦除 4K 个字节。这样我们需要给 W2
[单片机]
关于STM32 SPI NSS问题的探讨
对于STM32的SPI ,Reference Manual中是给出的schematic如下: 按照标准的SPI协议,当SPI被配置为主机模式后,通过SPI对从设备进行操作时,其NSS应该自动置低,从而选中(使能)从设备;一旦不对从设备进行操作,NSS立刻置为高。 但是,我在实际调试过程中却发现:STM32 SPI NSS无法自动实现跳变。 一旦SPI初始化完成并使能SPI,NSS立刻置低,然后保持不变。 这个问题一直无法解决,直到我在ST官方论坛上看到国外有些技术人员也在讨论这个问题,他们得出的结论是:STM32 SPI NSS无法自动跳变。 RichardE Post
[单片机]
关于STM32 <font color='red'>SPI</font> NSS问题的探讨
WinCE和Win2000/XP设备驱动开发的区别
引 言     Windows CE是一个32位、多任务、多线程的嵌入式操作系统,是微软专门为信息设备、移动应用、消费类电子产品、嵌入式应用等非PC领域设计的操作系统产品,在外观和使用的感觉上十分接近桌面Windows系统。它使用平面内存模式寻址,可以同时运行多个程序并支持一个程序中的多个线程,并且非常精炼,只有很小的内存要求。与基于PC的操作系统不同,Windows CE不需要标准硬件,反而支持各种各样的CPU(如X86、PowerPC、ARM、MIPS等),通过OEM适配层(OEM adaptation layer)可以把Windows CE适配到任何硬件平台。Windows CE是微软Windows操作系统家族的一个成员
[嵌入式]
基于ARM9的嵌入式网关的研究
   摘 要: 介绍了一种基于ARM9的嵌入式以太网的设计方案。基于ARM内核微处理器S3C2410的功能特点及其外扩组成部分,分析了以太网控制器芯片RTL8019AS的性能以及与S3C2410的接口。在软件设计上,分析了BootLoader的作用,介绍了Linux的移植,并给出了通信程序的流程图,实现了嵌入式以太网的数据传输。    关键词: 嵌入式系统;网关;ARM;移植    引 言   无所不在的网络给网络接入设备带来了巨大的发展机遇。而随着网络接入市场的迅速增长,嵌入式网络接入开始成为嵌入式系统技术中最令人关注的一个领域。在嵌入式网络技术的推动下将会形成这样一个局面:在网络上传输的信息中,将有70%的信息来自嵌入式
[嵌入式]
基于WINCE S3C2440 的LED驱动程序的编写
在SMDK2440的BSP包里经常看见这两句语句: volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE; volatile INTreg *s2440INT = (INTreg *)INT_BASE; 这两条语句简单的理解就是把s2440IOP和IOP_BASE等价,把s2440INT和INT_BASE等价。 IOP_BASE和INT_BASE在s244.h头文件中 #define IOP_BASE 0xB1600000 // 0x56000000 typedef struct { unsigned int rGPACON; // 00 unsigned
[单片机]
ATmega168 SPI数据模式与时序
ATmega168有四种 XCKn (SCK)相位与极性的组合与串行数据有关,具体由 UCPHAn与UCPOLn决 定。 数据传输的时序图请见 Figure77。 数据位的移出与锁定发生在 XCKn 信号的相反边沿,以保证有足够的时间使数据稳定。UCPOLn 与 UCPHAn 的功能总结见 Table86。改变这两位的设置将破坏正在进行的通讯。 。
[单片机]
ATmega168 <font color='red'>SPI</font>数据模式与时序
STM32F7使用SPI发送完成和接收中断
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。 但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应; 或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。 此时就需要用到发送完成和接收中断了。 前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。 接缓冲区满中断 新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断: SPI_HandleTypeDef SPI3_Handler; //SPI2句柄
[单片机]
STM32F7使用<font color='red'>SPI</font>发送完成和接收中断
恩智浦四款32位ARM9 MCU
2008年3月28日,恩智浦半导体推出了全新的LPC3200系列微控制器,进一步扩展了其ARM7™ 和ARM9™ 微控制器产品线。恩智浦LPC3200系列基于ARM926EJ™ 处理器,针对消费电子、工业、医疗和汽车电子应用,为设计师提供一种高性能、高功耗效率的微控制器。恩智浦LPC3200微控制器系列包括LPC3220、LPC3230、LPC3240和LPC3250。 恩智浦LPC3200系列采用90纳米工艺设计,结合了一个ARM926EJ核、一个矢量浮点协处理器(VFP)、一个LCD控制器、一个以太网MAC、On-The-Go USB、一个高效的总线阵列以及大量的标准外设,使得嵌入式系统设
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved