nRF51822 SPI 드라이브 ADXL362

5553 단어 nRF51822
하드웨어 플랫폼: 미설 nRF51822 개발판
소프트웨어 플랫폼: MDK522
SDK 버전: SDK5
nRF51822의 임의의 파이프라인은 SPI의 파이프라인으로 설정할 수 있으며, 공식적으로 준 코드는 SPI마스터, 안에 두 가지 함수만 있음:spimaster_init 및 spimaster_tx_rx, 앞에는 초기화 함수, 뒤에는 양방향 전송 함수.
1. nRF51822 SPI 사용
spimaster_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으로 선택하고 전송된 크기를 선택한 다음 두 개의 데이터 라인의 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
"); } 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
",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을 맞추는 것도 좋다. 그래서 최종적으로 무슨 문제인지 알 수 없다. 그러나 시계 신호가 없는 상황이 발생하면 먼저 속도를 최소화해 보자.

좋은 웹페이지 즐겨찾기