main.c
0.01MB
main.h
0.00MB
stm32f4xx_it.c
0.01MB
NRF24L01.c
0.01MB
NRF24L01.h
0.00MB
SPI.c
0.00MB
SPI.h
0.00MB

코드를 작성했을 때 시간이 가장 오래 걸렸고 가장 힘들게 코드를 만들었던 nrf24l01 모듈이다.

 

2개 이상의 모듈이 필요했고 TX, RX 2개의 코드를 작성해야 했고 한 개의 코드만 문제가 있어도 작동하지 않아 어려움을 겪었다.

 

SPI 통신을 사용하여 제어를 하며 현제 코드는 interrupt, DMA를 사용하지 않았다. 이후에 SPI DMA를 사용하여 코드를 작성해 볼 생각이다.

 

 

코드 생성 - (0)

PIN
Parameter Settings

SPI1과 SPI3를 사용한다.

 

SPI1과 SPI3의 세팅은 동일하며 Prescaler 부분만 각각의 Baud Rate를 같게 설정했다.

 

 

EXIT

RX 모드로 동작하는 nrf24l01 모듈에서 데이터를 받았다는 것을 알려주기 위한 외부 인터럽트 핀을 하나 추가하여 코드를 생성한다.

 

nrf24l01의 interrupt는 active low이므로 Falling edge로 설정한다.

 

 

코드 - main.c (1)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* USER CODE BEGIN 2 */
 
  NRF24L01 nrf1, nrf2;
  uint8_t counter=0;
  uint8_t status=0;
  uint8_t data[6]={0x12,0xcd,0x34,0x45,0x5f,0x67};
 
  LL_SPI_Enable(SPI1);
  LL_SPI_Enable(SPI3);
  printf("start\r\n");
 
  nrf_init(&nrf1, SPI1, RX,NRF1_CS_GPIO_Port,NRF1_CS_Pin,NRF1_CE_GPIO_Port,NRF1_CE_Pin,32);
 
  nrf_init(&nrf2, SPI3, TX,NRF2_CS_GPIO_Port,NRF2_CS_Pin,NRF2_CE_GPIO_Port,NRF2_CE_Pin,32);
 
  printf("======= 1\r\n ");
  dump_reg(&nrf1);
  printf("======= 2\r\n ");
  dump_reg(&nrf2);
 
  /* USER CODE END 2 */
 

 

3번째 줄에서 NRF24L01 구조체 변수 2개를 선언한다. nrf1은 RX, nrf2는 TX의 용도로 사용한다.

 

12번째 줄과 14번째 줄에서 nrf1, nrf2를 초기화한다. 내부의 코드를 보면 어떤 값으로 레지스터들을 초기화하는지 볼 수 있다. PORT, PIN에 대한 매크로는 main.h에 정의되어 있다.

 

초기화할 때 주의해야 할 점이 있는데 TX모드 모듈 내부의 TX_ADDR과 RX_ADDR_P0의 값이 같고 RX모드 모듈 내부의 RX_ADDR_Rx의 값이 같아야 한다. 값이 다를 경우 통신이 되지 않는다. 데이터시트에 나오지만 지나칠 수 있다. 

 

17번째 줄과 19번째 줄에서 nrf1과 nrf2에 해당하는 모듈들의 레지스터 값들을 덤프 해서 출력한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
counter++;
for(uint8_t i=0;i<32;i++){
      TXdata[i]=counter+(i*2);
}
printf("\r\n");
 
nrf_TX_payload(&nrf2,TXdata);
nrf_enable_pulse(&nrf2,TIM2,20);
LL_mDelay(500);
printf("%d\r\n",counter);
 
if(nrf_condition==1){
      nrf_RX_payload(&nrf1,RXdata);
      for(uint8_t i=0;i<25;i++){
          printf("%d ",RXdata[i]);
          if(i%10==9){
              printf("\r\n");
          }
      }
      printf("\r\n");
      nrf_condition=0;
}
 

 

while문 내부의 코드이다.

 

2에서 4번째 줄까지 TXdata 배열에 임의의 값들을 저장한다.

 

7번째 줄에서 payload에 TXdata들이 들어가고 8번째 줄에서 enable port에 pulse 신호를 인가해 데이터를 무선으로 전송한다.

 

9번째 줄에 의해 500ms후에 데이터를 다른 모듈에서 읽어 들인다.

 

12번째 줄에서 22번째 줄까지 데이터를 읽어 들이는데 nrf_condition의 변수는 stm32f4xx_it.c 파일의 EXIT코드에 의해 1로 SET 된다. 즉 모듈에서 데이터를 받았을 경우 NRF_1IRQ 핀인 PB6에 Falling edge Interrupt가 발생한다.

 

 

결과 - (2)

Dump

 

1번째 사진은 dump_reg()가 실행됐을 때 출력되는 데이터들이다. 값들이 원하는 설정값들로 변한 모습을 볼 수 있고 TX모드일 경우 TX모드 모듈 내부의 TX_ADDR과 RX_ADDR_P0값이 같아야 한다.

 

2번째 사진은 값들이 제대로 들어오는 모습을 보여준다.

 

 

 

-

시간이 오래 걸리고 작성하기 어려웠던 코드였다.

 

하지만 그만큼 사용할 수 있는 곳이 많아 개인적으로 좋아하는 모듈이다.

 

HAL 드라이버 쿼드콥터에 간단한 팔로우미 기능과 각도 등의 데이터를 받을 때 사용했다. 기존 코드는 HAL코드로 작성했지만 SPI 통신부분과 GPIO 부분을 수정하여 LL 드라이버 코드로 변경했다.

 

nrf24l01.c 코드에 대한 얘기는 안 썼는데 양이 너무 많고, 데이터시트를 안 보면 설명할 수 없는 내용이 많아 넘겼다.

 

또한 블로그에서 지향하고자 하는 방향이 어느 정도 지식은 가지고 있지만 실제 코드를 작성하는데 어려움이 있는 사람을 위하는 생각으로 글을 쓰고 있기 때문에 실제 코드를 직접 분석해보면서 알아가는 게 더 좋다고 생각한다.

 

DMA를 사용하지 않고 작성했지만 DMA를 사용하여 코드를 변경해볼 생각이다.

Posted by DDTXRX
,