nRF51822 SPI 驱动 ADXL362

硬件平台:微雪nRF51822开发板

软件平台:MDK522

SDK版本:SDK5


nRF51822的任意管脚可以配置成SPI的管脚,其官方给的代码有一个SPI_master,里面只有两个函数:spi_master_init 和 spi_master_tx_rx,前面一个是初始化函数,后面一个是双向传输函数。


1. nRF51822 SPI的使用


在spi_master_config.h 文件里面配置管脚信息


// SPI0. 
#define SPI_PSELSCK0            25u                                     /**< SPI clock GPIO pin number. */
#define SPI_PSELMOSI0           24u                                     /**< SPI Master Out Slave In GPIO pin number. */
#define SPI_PSELMISO0           23u                                     /**< SPI Master In Slave Out GPIO pin number. */
#define SPI_PSELSS0             30u      					                     	/**< SPI Slave Select GPIO pin number. */

// SPI1.
#define SPI_PSELSCK1            19u                                     /**< SPI clock GPIO pin number. */
#define SPI_PSELMOSI1           20u                                     /**< SPI Master Out Slave In GPIO pin number. */
#define SPI_PSELMISO1           22u                                     /**< SPI Master In Slave Out GPIO pin number. */
#define SPI_PSELSS1             21u                                     /**< SPI Slave Select GPIO pin number. */



此处的SPI0为我们需要使用的,与ADXL8632进行连接


初始化函数

spi_base_address = spi_master_init(SPI0,SPI_MODE0,false);   //选择SPI0,mode0,lsb false

传输函数:选择为SPI0,传输的size,然后是两个数据线的buff

bool spi_master_tx_rx(uint32_t *spi_base_address, uint16_t transfer_size, const uint8_t *tx_data, uint8_t *rx_data)


2. adxl362的驱动编写


在官网(http://www.analog.com/cn/products/mems/accelerometers/adxl362.html#product-documentation)上有驱动的上层代码,主要是初始化和寄存器的一些操作。需要我们自己编写底层的SPI的操作,而且driver里面SPI是有write和read函数的,我们需要使用spi_master_tx_rx这个函数来完成操作。


2.1 读一个寄存器的数据


首先需要读取ID值,我们改进的函数为:

bool ADXL362_ReadOneReg(u8_t Reg, u8_t* Data)
{

    /* Write transaction */
    uint8_t transfer_size = 3;               //先是read命令,然后是寄存器地址,最后是数据
    SPIMasterBuffer[0] = ADXL362_READ_REG;   //read命令  
    SPIMasterBuffer[1] = Reg;                 //寄存器地址
  	spi_master_tx_rx((uint32_t *)NRF_SPI0,transfer_size,SPIMasterBuffer,SPISlaveBuffer);    //进行数据双向传输
    /* Send received value back to the caller */
    *Data = SPISlaveBuffer[2];               //在MISO线上第三个数据则是ID数据

    return true;
}

2.2 写一个寄存器的数据

bool ADXL362_WriteOneReg(u8_t WriteAddr, u8_t Data)
{
    SPIWriteLength = 3;    //write命令+寄存器地址+写入的数据
    SPIReadLength = 0;
    SPIMasterBuffer[0] = ADXL362_WRITE_REG;
    SPIMasterBuffer[1] = WriteAddr;
    SPIMasterBuffer[2] = (Data);
    /* Check if we got an ACK or TIMEOUT error */
    spi_master_tx_rx((uint32_t *)NRF_SPI0,SPIWriteLength,SPIMasterBuffer,SPISlaveBuffer);
    return true;
}

2.3 改进官方的读取多个寄存器的函数

void ADXL362_GetRegisterValue(unsigned char* pReadData,
                              unsigned char  registerAddress,
                              unsigned char  bytesNumber)
{
    unsigned char M_buffer[32];     //MOSI的数据
    unsigned char S_buffer[32];     //MISO的数据
    unsigned char index = 0;
	
	/* Write transaction */
    uint8_t transfer_size = bytesNumber + 2;    //读取多个数据,再加上读取命令和开始地址
    M_buffer[0] = ADXL362_READ_REG;             //读取命令
    M_buffer[1] = registerAddress;              //开始地址
		
		
	
    spi_master_tx_rx((uint32_t *)NRF_SPI0,transfer_size,M_buffer,S_buffer);  //传输了读取命令,然后开始读取
    /* Send received value back to the caller */
    for(index = 0; index < bytesNumber; index++)
    {
        pReadData[index] = S_buffer[index + 2];    //除去前面两个之后,后面的都是MISO上读取到的寄存器数据
    }

}

2.4 改进官方的写两个寄存器的函数


void ADXL362_SetRegisterValue(unsigned short registerValue,
                              unsigned char  registerAddress,
                              unsigned char  bytesNumber)
{
	
    SPIWriteLength = bytesNumber+2;
    SPIReadLength = 0;
    SPIMasterBuffer[0] = ADXL362_WRITE_REG;
    SPIMasterBuffer[1] = registerAddress;
    SPIMasterBuffer[2] = (registerValue & 0x00FF);     //we can get the last 8 bit
    SPIMasterBuffer[3] = (registerValue >> 8);           //we can get the first 8 bit
    /* Check if we got an ACK or TIMEOUT error */
    spi_master_tx_rx((uint32_t *)NRF_SPI0,SPIWriteLength,SPIMasterBuffer,SPISlaveBuffer);
}

至此,底层的接口基本上适配完毕了,这样的话其他的函数可以直接基于这些函数来调用了。


2.5 初始化函数


bool ADXL362_Init(void)
{
    unsigned char regValue = 0;

    spi_base_address = spi_master_init(SPI0,SPI_MODE0,false);
		
		if (spi_base_address == 0) {
			printf("the spi is not  ok\r\n");
    }
		spi_master_enable(SPI0);
		
    ADXL362_GetRegisterValue(&regValue, ADXL362_REG_PARTID, 1);
    if((regValue == ADXL362_PART_ID))
    {
//			printf("the acc is on, and the geten id is %d\r\n",regValue);
			ADXL362_WriteOneReg(ADXL362_REG_FILTER_CTL, 0x10);
			ADXL362_WriteOneReg(ADXL362_REG_INTMAP2, 0x01);
			ADXL362_WriteOneReg(ADXL362_REG_POWER_CTL, 0x02);
			return true;
    }
		else{
			return false;
		}
}

初始化之后可以在寄存器里面拿到数据了。



3. debug的状态


SPI出了问题,使用示波器发现SPI的时钟产生一两个之后就停了,完整的时钟信号都没有。


在确定各种初始化都没问题之后,发现产生的时钟的频率也不对,在调低了时钟速率之后,这个问题得到了解决,从1M变成125K之后变好了,再调上1M也是好的,所以最终是啥问题不可得知,但是如果遇到时钟信号都没有的情况,先把速率调至最低试试。




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值