Hi I am working on a project where I am trying to implement Bi-directional communication between 2 nrf modules connected to stm32f411ve dev boards.
I am facing issue with adding a dynamic payload along with my ack message
below is nrf driver code for the receiver side and also the spi code.
I am unable to understand how and where should I call the W_TX_PAYLOAD command
/* * SPI.c * * Created on: Nov 10, 2024 * Author: Asus */ #include"SPI.h" #include"stdio.h" #define AF05 (0x05) void SPI_INIT(){ //enable clock for GPIOA RCC->AHB1ENR|=RCC_AHB1ENR_GPIOAEN; //set PA5, PA6 and PA7 to alternate function mode GPIOA->MODER|=GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1; //set which type of alternate function is GPIOA->AFR[0]|=(AF05<<20)|(AF05<<24)|(AF05<<28); //enable clock access to SPI1 RCC->APB2ENR|=RCC_APB2ENR_SPI1EN; //set software slave managment SPI1->CR1|=SPI_CR1_SSM|SPI_CR1_SSI; //set SPI in master mode MODIFY_FIELD(SPI1->CR1, SPI_CR1_MSTR, 1); MODIFY_FIELD(SPI1->CR1, SPI_CR1_BR, 3); MODIFY_FIELD(SPI1->CR1, SPI_CR1_CPHA, 0); MODIFY_FIELD(SPI1->CR1, SPI_CR1_CPOL, 0); //MODIFY_FIELD(SPI1->CR1, SPI_CR1_LSBFIRST, 1); SPI1->CR2 |= 0x4; SPI1->CR1 |= 0x40; // Enabling SPI SPI periph MODIFY_FIELD(SPI1->CR1, SPI_CR1_SPE, 1); } //send multiple bytes in case size>1 void SPI_TX_MULTI(uint8_t *data_ptr,int size){ int i=0; uint8_t temp; while(i<size){ while(!(SPI1->SR & (SPI_SR_TXE))){} SPI1->DR = data_ptr[i]; i++; } /*Wait until TXE is set*/ while(!(SPI1->SR & (SPI_SR_TXE))){} /*Wait for BUSY flag to reset*/ while((SPI1->SR & (SPI_SR_BSY))){} /*Clear OVR flag*/ temp = SPI1->DR; temp = SPI1->SR; } void SPI_READ_MULTI(uint8_t *data_ptr,int size){ while(size) { /*Send dummy data*/ SPI1->DR =0; /*Wait for RXNE flag to be set*/ while(!(SPI1->SR & (SPI_SR_RXNE))){} /*Read data from data register*/ *data_ptr++ = (SPI1->DR); size--; } }
/* * NRF_DRIVER.c * * Created on: Nov 10, 2024 * Author: Asus */ #include"NRF_DRIVER.h" #include"delay.h" #include"SPI.h" #include"utilities.h" #include<stdio.h> void init_CSN_CE_PINS(){ RCC->AHB1ENR|=RCC_AHB1ENR_GPIOAEN; MODIFY_FIELD(GPIOA->MODER, GPIO_MODER_MODER4, ESF_GPIO_MODER_OUTPUT); // NSS pin for now4 as outpu MODIFY_FIELD(GPIOA->MODER, GPIO_MODER_MODER0, ESF_GPIO_MODER_OUTPUT); // NSS pin for now4 as outpu } void CSN_SELECT_NRF(){ GPIOA->BSRR |= GPIO_BSRR_BR_4; //pull low to enable nrf } void CSN_UNSELECT_NRF(){ GPIOA->BSRR |= GPIO_BSRR_BS_4; //make high to disable } void NRF_ENABLE(){ GPIOA->BSRR |= GPIO_BSRR_BS_0; } void NRF_DISABLE(){ GPIOA->BSRR |= GPIO_BSRR_BR_0; } void NRF_WRITE_REGISTER(uint8_t REG_ADDRESS,uint8_t data){ uint8_t trans_buff[2]; trans_buff[0]=REG_ADDRESS|W_REGISTER; trans_buff[1]=data; CSN_SELECT_NRF(); SPI_TX_MULTI(trans_buff,2); CSN_UNSELECT_NRF(); } void NRF_WRITE_REG_MULTI_BYTES(uint8_t REG_ADDRESS,uint8_t* data_trans,int size_trans){ uint8_t trans_buff[2]; trans_buff[0]=REG_ADDRESS|W_REGISTER; CSN_SELECT_NRF(); SPI_TX_MULTI(trans_buff,1); SPI_TX_MULTI(data_trans,size_trans); CSN_UNSELECT_NRF(); } uint8_t NRF_READ_REGISTER(uint8_t REG_ADDRESS){ uint8_t data_returned=0; CSN_SELECT_NRF(); SPI_TX_MULTI(®_ADDRESS,1); SPI_READ_MULTI(&data_returned,1); CSN_UNSELECT_NRF(); return data_returned; } void NRF_READ_REGISTER_MULTI(uint8_t REG_ADDRESS,uint8_t *RECV_BUFFER,int RECV_BUFFER_SIZE){ CSN_SELECT_NRF(); SPI_TX_MULTI(®_ADDRESS,1); SPI_READ_MULTI(RECV_BUFFER,RECV_BUFFER_SIZE); CSN_UNSELECT_NRF(); } void NRF_PTX_CONFIG(uint8_t *Address, uint8_t channel){ NRF_DISABLE(); NRF_WRITE_REGISTER(RF_CH,channel); //select channel NRF_WRITE_REG_MULTI_BYTES(TX_ADDR,Address,5); //set address // un comment belowo code to setup for auto ack uint8_t current_pipe_status=NRF_READ_REGISTER(EN_RXADDR); current_pipe_status=current_pipe_status|(1<<0);//enable pipe 1 NRF_WRITE_REGISTER(EN_RXADDR,current_pipe_status); NRF_WRITE_REG_MULTI_BYTES(RX_ADDR_P0,Address,5); //pipe address NRF_WRITE_REGISTER(CONFIG,0x0a); //powwr on device and keep in tx mode delay(5); //NRF_ENABLE(); } void NRF_PRX_CONFIG(uint8_t *Address, uint8_t channel){ NRF_DISABLE(); NRF_WRITE_REGISTER(RF_CH,channel); //select channel uint8_t current_pipe_status=NRF_READ_REGISTER(EN_RXADDR); current_pipe_status=current_pipe_status|(1<<1);//enable pipe 1 NRF_WRITE_REGISTER(EN_RXADDR,current_pipe_status); NRF_WRITE_REG_MULTI_BYTES(RX_ADDR_P1,Address,5); //pipe address //since we have dynamic payload we dont need thus below //NRF_WRITE_REGISTER(RX_PW_P1,32); //data 32 bytes width NRF_WRITE_REGISTER(CONFIG,0x0b); //powwr on device and keep in tx mode NRF_ENABLE(); } void nrf24_reset(uint8_t REG) { if (REG == STATUS) { NRF_WRITE_REGISTER(STATUS, 0x00); } else if (REG == FIFO_STATUS) { NRF_WRITE_REGISTER(FIFO_STATUS, 0x11); } else { NRF_WRITE_REGISTER(CONFIG, 0x08); NRF_WRITE_REGISTER(EN_AA, 0x3F); NRF_WRITE_REGISTER(EN_RXADDR, 0x03); NRF_WRITE_REGISTER(SETUP_AW, 0x03); NRF_WRITE_REGISTER(SETUP_RETR, 0x03); NRF_WRITE_REGISTER(RF_CH, 0x02); NRF_WRITE_REGISTER(RF_SETUP, 0x0E); NRF_WRITE_REGISTER(STATUS, 0x00); NRF_WRITE_REGISTER(OBSERVE_TX, 0x00); NRF_WRITE_REGISTER(CD, 0x00); uint8_t rx_addr_p0_def[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}; NRF_WRITE_REG_MULTI_BYTES(RX_ADDR_P0, rx_addr_p0_def, 5); uint8_t rx_addr_p1_def[5] = {0xC2, 0xC2, 0xC2, 0xC2, 0xC2}; NRF_WRITE_REG_MULTI_BYTES(RX_ADDR_P1, rx_addr_p1_def, 5); NRF_WRITE_REGISTER(RX_ADDR_P2, 0xC3); NRF_WRITE_REGISTER(RX_ADDR_P3, 0xC4); NRF_WRITE_REGISTER(RX_ADDR_P4, 0xC5); NRF_WRITE_REGISTER(RX_ADDR_P5, 0xC6); uint8_t tx_addr_def[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}; NRF_WRITE_REG_MULTI_BYTES(TX_ADDR, tx_addr_def, 5); NRF_WRITE_REGISTER(RX_PW_P0, 0); NRF_WRITE_REGISTER(RX_PW_P1, 0); NRF_WRITE_REGISTER(RX_PW_P2, 0); NRF_WRITE_REGISTER(RX_PW_P3, 0); NRF_WRITE_REGISTER(RX_PW_P4, 0); NRF_WRITE_REGISTER(RX_PW_P5, 0); NRF_WRITE_REGISTER(FIFO_STATUS, 0x11); NRF_WRITE_REGISTER(DYNPD, 0); NRF_WRITE_REGISTER(FEATURE, 0); } } void NRF_INIT(){ SPI_INIT(); //initalize spi comms init_CSN_CE_PINS(); NRF_DISABLE(); nrf24_reset(0); NRF_WRITE_REGISTER(CONFIG, 0); // will be configured later //NRF_WRITE_REGISTER(EN_AA, 0x00); // No Auto ACK /*uncomment below code to enable auto ack stuff*/ //NRF_WRITE_REGISTER(EN_AA, 0x3f); // No Auto ACK //NRF_WRITE_REGISTER(SETUP_RETR, 0x03); // 15 retries, 500µs delay NRF_WRITE_REGISTER (EN_RXADDR, 0); // Not Enabling any data pipe right now NRF_WRITE_REGISTER (SETUP_AW, 0x03); // 5 Bytes for the TX/RX address //NRF_WRITE_REGISTER (SETUP_RETR, 0x00); // No retransmission NRF_WRITE_REGISTER (RF_CH, 0); // will be setup during Tx or RX //enable dynamic payloads on all pipes //for DYNP I require EN_AA and Requires EN_DPL and ENAA_P0 NRF_WRITE_REGISTER (DYNPD, 0x3f); // will be setup during Tx or RX NRF_WRITE_REGISTER (FEATURE, 0x6); // enable dynamic payload length NRF_WRITE_REGISTER(EN_AA, 0x3f); // No Auto ACK NRF_WRITE_REGISTER(SETUP_RETR, 0xff); // 15 retries, 500µs delay NRF_WRITE_REGISTER (RF_SETUP, 0x0e); // Power= 0db, data rate = 2Mbps //NRF_ENABLE(); } void NRD_SEND_CMD (uint8_t cmd) { // Pull the CS Pin LOW to select the device CSN_SELECT_NRF(); SPI_TX_MULTI(&cmd, 1); // Pull the CS HIGH to release the device CSN_UNSELECT_NRF(); } uint8_t NRF_TX_DATA(uint8_t *data_ptr){ uint8_t tx_fifo_stat; uint8_t status_reg; CSN_SELECT_NRF(); uint8_t cmd = W_TX_PAYLOAD; SPI_TX_MULTI( &cmd, 1); SPI_TX_MULTI(data_ptr,32);//send payload CSN_UNSELECT_NRF(); NRF_ENABLE(); delay(10); NRF_DISABLE(); tx_fifo_stat=NRF_READ_REGISTER(FIFO_STATUS); status_reg=NRF_READ_REGISTER(STATUS); printf("tx_fifo_stat is - %d",tx_fifo_stat); printf("status register- %d",status_reg); if ((tx_fifo_stat&(1<<4)) && (!(tx_fifo_stat&(1<<3)))){ cmd=FLUSH_TX; NRD_SEND_CMD(cmd); NRF_WRITE_REGISTER(FIFO_STATUS, 0x11); //reset fifo return 1; } if(status_reg &(1<<4)){ printf("max number of retransmission \n \r %d \n \r",status_reg); status_reg=status_reg|(1<<4); NRF_WRITE_REGISTER(STATUS,status_reg); status_reg=NRF_READ_REGISTER(STATUS); printf("after clearing flag? %d \n \r",status_reg); cmd=FLUSH_TX; NRD_SEND_CMD(cmd); NRF_WRITE_REGISTER(FIFO_STATUS, 0x11); //reset fifo } return 0; } uint8_t is_data_on_pipe(uint8_t pipenum){ uint8_t status_reg=NRF_READ_REGISTER(STATUS); //if 6 th bit is set and respective data pipe is set //printf("reciever status %d \n \r",status_reg); if((status_reg & (1<<6))&& status_reg &(1<<pipenum)){ //clear rx_dr NRF_WRITE_REGISTER(STATUS,(1<<6)); return 1; //data recieved } return 0; } //uint8_t NRF_SEND_PAYLOAD_WIDTH_READ(uint8_t cmd){ // uint8_t temp; // while(!(SPI1->SR & (SPI_SR_TXE))){} // SPI1->DR = cmd; // temp = SPI1->DR; // temp = SPI1->SR; // while (!(SPI1->SR & SPI_SR_RXNE)) {} // return (uint8_t)(SPI1->DR); //} //this code needs to be modefied for dyanmic first we will send //R_RX_PL_WID first and then R_RX_PAYLOAD void NRF_RECV_DATA(uint8_t *data_ptr_RECV){ CSN_SELECT_NRF(); uint8_t cmd=W_ACK_PAYLOAD|0; SPI_TX_MULTI( &cmd, 1); uint8_t ack_payLoad[]={0x56}; SPI_TX_MULTI(ack_payLoad, sizeof(ack_payLoad)); CSN_UNSELECT_NRF(); delay(10); uint8_t status_reg=NRF_READ_REGISTER(STATUS); uint8_t tx_fifo_stat=NRF_READ_REGISTER(FIFO_STATUS); delay(10); cmd = R_RX_PL_WID; uint8_t payLoad_width=0; CSN_SELECT_NRF(); //payLoad_width=NRF_SEND_PAYLOAD_WIDTH_READ(cmd); //next comand to read payload SPI_TX_MULTI( &cmd, 1); SPI_READ_MULTI(&payLoad_width,1);//recieve width printf("\n \r payloadWidth %d \n \r",payLoad_width); CSN_UNSELECT_NRF(); delay(10); printf("status_reg %d \n \r",status_reg); printf("tx_fifo_stat %d \n \r",tx_fifo_stat); CSN_SELECT_NRF(); cmd=R_RX_PAYLOAD; SPI_TX_MULTI( &cmd, 1); SPI_READ_MULTI(data_ptr_RECV,payLoad_width);//recieve data CSN_UNSELECT_NRF(); cmd=FLUSH_RX; delay(20); NRD_SEND_CMD(cmd); //flush rx fifo delay(10); if(tx_fifo_stat&(1<<5)){ cmd=FLUSH_TX; NRD_SEND_CMD(cmd); } }
Thanks