找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1985|回复: 0
收起左侧

STC12单片机硬件SPI实现NRF24L01的发送/接收/中断接收

[复制链接]
ID:912806 发表于 2021-8-29 21:23 | 显示全部楼层 |阅读模式
今天解决了一个之前困扰很久的1E状态的问题, 把RX, TX和EXIT+RX的模式都跑通了.

代码基于HML_FwLib_STC12, 在仓库的examples里, 链接地址
使用的是STC12的硬件SPI的方式, 不是软件模拟的SPI, 主体代码如下, 将 CURRENT_MODE 改成不同的值, 会分别启动到RX, TX和EXTI RX这三种模式, 运行时需要两块NRF24L01配合测试.
  1. /*****************************************************************************/
  2. /**
  3. * \file        spi_nrf24l01_tx.c
  4. * \date        
  5. * \brief       Example code of SPI driving NRF24L01 module in TX mode
  6. * \note        Pin connection:
  7. *              P1_4(SS, Ignored) => CSN,
  8. *              P1_5(MOSI)        => MOSI,
  9. *              P1_6(MISO)        => MISO,
  10. *              P1_7(SPCLK)       => CLK,
  11. *              P3_2(INT0)        => IRQ,
  12. *              P3_7(IO)          => CE,
  13. *
  14. * \version     v0.1
  15. * \ingroup     example
  16. * \remarks     test-board: Minimum System; test-MCU: STC12C5AF56S2
  17. ******************************************************************************/

  18. /*****************************************************************************
  19. *                             header file                                   *
  20. *****************************************************************************/
  21. #include "hml/hml.h"
  22. #include <stdio.h>

  23. /**********  SPI(nRF24L01) commands  ***********/
  24. //
  25. #define NRF24_CMD_REGISTER_R     0x00 // Register read
  26. #define NRF24_CMD_REGISTER_W     0x20 // Register write
  27. #define NRF24_CMD_ACTIVATE       0x50 // (De)Activates R_RX_PL_WID, W_ACK_PAYLOAD, W_TX_PAYLOAD_NOACK features
  28. #define NRF24_CMD_RX_PLOAD_WID_R 0x60 // Read RX-payload width for the top R_RX_PAYLOAD in the RX FIFO.
  29. #define NRF24_CMD_RX_PLOAD_R     0x61 // Read RX payload
  30. #define NRF24_CMD_TX_PLOAD_W     0xA0 // Write TX payload
  31. #define NRF24_CMD_ACK_PAYLOAD_W  0xA8 // Write ACK payload
  32. #define NRF24_CMD_TX_PAYLOAD_NOACK_W 0xB0 //Write TX payload and disable AUTOACK
  33. #define NRF24_CMD_FLUSH_TX       0xE1 // Flush TX FIFO
  34. #define NRF24_CMD_FLUSH_RX       0xE2 // Flush RX FIFO
  35. #define NRF24_CMD_REUSE_TX_PL    0xE3 // Reuse TX payload
  36. #define NRF24_CMD_LOCK_UNLOCK    0x50 // Lock/unlock exclusive features
  37. #define NRF24_CMD_NOP            0xFF // No operation (used for reading status register)


  38. // SPI(nRF24L01) register address definitions
  39. #define NRF24_REG_CONFIG         0x00 // Configuration register
  40. #define NRF24_REG_EN_AA          0x01 // Enable "Auto acknowledgment"
  41. #define NRF24_REG_EN_RXADDR      0x02 // Enable RX addresses
  42. #define NRF24_REG_SETUP_AW       0x03 // Setup of address widths
  43. #define NRF24_REG_SETUP_RETR     0x04 // Setup of automatic re-transmit
  44. #define NRF24_REG_RF_CH          0x05 // RF channel
  45. #define NRF24_REG_RF_SETUP       0x06 // RF setup
  46. #define NRF24_REG_STATUS         0x07 // Status register
  47. #define NRF24_REG_OBSERVE_TX     0x08 // Transmit observe register
  48. #define NRF24_REG_RPD            0x09 // Received power detector
  49. #define NRF24_REG_RX_ADDR_P0     0x0A // Receive address data pipe 0
  50. #define NRF24_REG_RX_ADDR_P1     0x0B // Receive address data pipe 1
  51. #define NRF24_REG_RX_ADDR_P2     0x0C // Receive address data pipe 2
  52. #define NRF24_REG_RX_ADDR_P3     0x0D // Receive address data pipe 3
  53. #define NRF24_REG_RX_ADDR_P4     0x0E // Receive address data pipe 4
  54. #define NRF24_REG_RX_ADDR_P5     0x0F // Receive address data pipe 5
  55. #define NRF24_REG_TX_ADDR        0x10 // Transmit address
  56. #define NRF24_REG_RX_PW_P0       0x11 // Number of bytes in RX payload in data pipe 0
  57. #define NRF24_REG_RX_PW_P1       0x12 // Number of bytes in RX payload in data pipe 1
  58. #define NRF24_REG_RX_PW_P2       0x13 // Number of bytes in RX payload in data pipe 2
  59. #define NRF24_REG_RX_PW_P3       0x14 // Number of bytes in RX payload in data pipe 3
  60. #define NRF24_REG_RX_PW_P4       0x15 // Number of bytes in RX payload in data pipe 4
  61. #define NRF24_REG_RX_PW_P5       0x16 // Number of bytes in RX payload in data pipe 5
  62. #define NRF24_REG_FIFO_STATUS    0x17 // FIFO status register
  63. #define NRF24_REG_DYNPD          0x1C // Enable dynamic payload length
  64. #define NRF24_REG_FEATURE        0x1D // Feature register

  65. // Register bits definitions
  66. #define NRF24_CONFIG_PRIM_RX     0x01 // PRIM_RX bit in CONFIG register
  67. #define NRF24_CONFIG_PWR_UP      0x02 // PWR_UP bit in CONFIG register
  68. #define NRF24_FEATURE_EN_DYN_ACK 0x01 // EN_DYN_ACK bit in FEATURE register
  69. #define NRF24_FEATURE_EN_ACK_PAY 0x02 // EN_ACK_PAY bit in FEATURE register
  70. #define NRF24_FEATURE_EN_DPL     0x04 // EN_DPL bit in FEATURE register
  71. #define NRF24_FLAG_RX_DREADY     0x40 // RX_DR bit (data ready RX FIFO interrupt)
  72. #define NRF24_FLAG_TX_DSENT      0x20 // TX_DS bit (data sent TX FIFO interrupt)
  73. #define NRF24_FLAG_MAX_RT        0x10 // MAX_RT bit (maximum number of TX re-transmits interrupt)

  74. // Register masks definitions
  75. #define NRF24_MASK_REG_MAP       0x1F // Mask bits[4:0] for CMD_RREG and CMD_WREG commands
  76. #define NRF24_MASK_CRC           0x0C // Mask for CRC bits [3:2] in CONFIG register
  77. #define NRF24_MASK_STATUS_IRQ    0x70 // Mask for all IRQ bits in STATUS register
  78. #define NRF24_MASK_RF_PWR        0x06 // Mask RF_PWR[2:1] bits in RF_SETUP register
  79. #define NRF24_MASK_RX_P_NO       0x0E // Mask RX_P_NO[3:1] bits in STATUS register
  80. #define NRF24_MASK_DATARATE      0x28 // Mask RD_DR_[5,3] bits in RF_SETUP register
  81. #define NRF24_MASK_EN_RX         0x3F // Mask ERX_P[5:0] bits in EN_RXADDR register
  82. #define NRF24_MASK_RX_PW         0x3F // Mask [5:0] bits in RX_PW_Px register
  83. #define NRF24_MASK_RETR_ARD      0xF0 // Mask for ARD[7:4] bits in SETUP_RETR register
  84. #define NRF24_MASK_RETR_ARC      0x0F // Mask for ARC[3:0] bits in SETUP_RETR register
  85. #define NRF24_MASK_RXFIFO        0x03 // Mask for RX FIFO status bits [1:0] in FIFO_STATUS register
  86. #define NRF24_MASK_TXFIFO        0x30 // Mask for TX FIFO status bits [5:4] in FIFO_STATUS register
  87. #define NRF24_MASK_PLOS_CNT      0xF0 // Mask for PLOS_CNT[7:4] bits in OBSERVE_TX register
  88. #define NRF24_MASK_ARC_CNT       0x0F // Mask for ARC_CNT[3:0] bits in OBSERVE_TX register

  89. #define NRF24_ADDR_WIDTH         5    // RX/TX address width
  90. #define NRF24_PLOAD_WIDTH        32   // Payload width
  91. #define NRF24_TEST_ADDR          "nRF24"

  92. typedef enum
  93. {
  94.     NRF24_MODE_RX = 0x00,
  95.     NRF24_MODE_TX = 0x01,
  96.     NRF24_MODE_IT = 0x02
  97. } NRF24_MODE;

  98. const uint8_t TX_ADDRESS[NRF24_ADDR_WIDTH] = {0x32,0x4E,0x6F,0x64,0x65};
  99. const uint8_t RX_ADDRESS[NRF24_ADDR_WIDTH] = {0x32,0x4E,0x6F,0x64,0x22};
  100. const NRF24_MODE CURRENT_MODE = NRF24_MODE_IT;
  101. uint8_t rx_buf[NRF24_PLOAD_WIDTH];

  102. #define NRF_CSN  P1_4
  103. #define NRF_MOSI P1_5
  104. #define NRF_MISO P1_6
  105. #define NRF_SCK  P1_7
  106. #define NRF_IRQ  P3_2
  107. #define NRF_CE   P3_7


  108. uint8_t NRF24L01_Write_Reg(uint8_t reg,uint8_t value)
  109. {
  110.         uint8_t status;

  111.         NRF_CSN = 0;
  112.           status = SPI_RW(reg);
  113.         SPI_RW(value);
  114.         NRF_CSN = 1;
  115.         return status;
  116. }

  117. uint8_t NRF24L01_Read_Reg(uint8_t reg)
  118. {
  119.     uint8_t value;
  120.     NRF_CSN = 0;
  121.     SPI_RW(reg);
  122.     value = SPI_RW(NRF24_CMD_NOP);
  123.     NRF_CSN = 1;
  124.     return value;
  125. }

  126. uint8_t NRF24L01_Read_To_Buf(uint8_t reg, uint8_t *pBuf, uint8_t len)
  127. {
  128.     uint8_t status, u8_ctr;
  129.     NRF_CSN = 0;
  130.     status = SPI_RW(reg);
  131.     for (u8_ctr = 0; u8_ctr < len; u8_ctr++)
  132.         pBuf[u8_ctr] = SPI_RW(NRF24_CMD_NOP);
  133.     NRF_CSN = 1;
  134.     return status;
  135. }

  136. uint8_t NRF24L01_Write_From_Buf(uint8_t reg, const uint8_t *pBuf, uint8_t len)
  137. {
  138.     uint8_t status, u8_ctr;
  139.     NRF_CSN = 0;
  140.     status = SPI_RW(reg);
  141.     for (u8_ctr = 0; u8_ctr < len; u8_ctr++)
  142.         SPI_RW(*pBuf++);
  143.     NRF_CSN = 1;
  144.     return status;
  145. }

  146. /**
  147. * Flush the RX FIFO
  148. */
  149. void NRF24L01_FlushRX(void)
  150. {
  151.         NRF24L01_Write_Reg(NRF24_CMD_FLUSH_RX, NRF24_CMD_NOP);
  152. }

  153. /**
  154. * Flush the TX FIFO
  155. */
  156. void NRF24L01_FlushTX(void)
  157. {
  158.         NRF24L01_Write_Reg(NRF24_CMD_FLUSH_TX, NRF24_CMD_NOP);
  159. }

  160. /**
  161. * Clear IRQ bit of the STATUS register
  162. *   reg - NRF24_FLAG_RX_DREADY
  163. *         NRF24_FLAG_TX_DSENT
  164. *         NRF24_FLAG_MAX_RT
  165. */
  166. void NRF24L01_ClearIRQFlag(uint8_t reg)
  167. {
  168.   NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_STATUS, reg);
  169. }

  170. /**
  171. * Clear RX_DR, TX_DS and MAX_RT bits of the STATUS register
  172. */
  173. void NRF24L01_ClearIRQFlags(void)
  174. {
  175.         uint8_t reg;
  176.         reg  = NRF24L01_Read_Reg(NRF24_REG_STATUS);
  177.         reg |= NRF24_MASK_STATUS_IRQ;
  178.         NRF24L01_Write_Reg(NRF24_REG_STATUS, reg);
  179. }

  180. uint8_t NRF24L01_RxPacket(uint8_t *rxbuf)
  181. {
  182.     while(NRF_IRQ);

  183.     uint8_t state = NRF24L01_Read_Reg(NRF24_REG_STATUS);
  184.     printf_tiny("Interrupted, state: %x\r\n", state);
  185.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_STATUS, state);
  186.     if (state & NRF24_FLAG_RX_DREADY)
  187.     {
  188.         NRF24L01_Read_To_Buf(NRF24_CMD_RX_PLOAD_R, rxbuf, NRF24_PLOAD_WIDTH);
  189.         NRF24L01_FlushRX();
  190.     }
  191.     return state;
  192. }

  193. uint8_t NRF24L01_TxPacket(uint8_t *txbuf)
  194. {
  195.     uint8_t state;
  196.     NRF_CE = 0;
  197.     NRF24L01_Write_From_Buf(NRF24_CMD_TX_PLOAD_W, txbuf, NRF24_PLOAD_WIDTH);
  198.     NRF_CE = 1;
  199.     while (NRF_IRQ == 1);
  200.     state = NRF24L01_Read_Reg(NRF24_REG_STATUS);
  201.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_STATUS, state);
  202.     if (state & NRF24_FLAG_MAX_RT)
  203.     {
  204.         NRF24L01_FlushTX();
  205.         NRF24L01_ClearIRQFlag(NRF24_FLAG_MAX_RT);
  206.     }
  207.     if (state & NRF24_FLAG_TX_DSENT)
  208.     {
  209.         NRF24L01_ClearIRQFlag(NRF24_FLAG_TX_DSENT);
  210.     }
  211.     return state;
  212. }

  213. uint8_t NRF24L01_Check(void)
  214. {
  215.         uint8_t i;
  216.         uint8_t *ptr = (uint8_t *)NRF24_TEST_ADDR;
  217.         NRF24L01_Write_From_Buf(NRF24_CMD_REGISTER_W | NRF24_REG_TX_ADDR, ptr, NRF24_ADDR_WIDTH);
  218.         NRF24L01_Read_To_Buf(NRF24_CMD_REGISTER_R | NRF24_REG_TX_ADDR, rx_buf, NRF24_ADDR_WIDTH);
  219.         for (i = 0; i < NRF24_ADDR_WIDTH; i++) {
  220.                 if (rx_buf[i] != *ptr++) return 1;
  221.         }
  222.         return 0;
  223. }

  224. void NRF24L01_init(NRF24_MODE mode)
  225. {
  226.     NRF_CE = 0;
  227.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_RX_PW_P0, NRF24_PLOAD_WIDTH);
  228.     NRF24L01_Write_From_Buf(NRF24_CMD_REGISTER_W + NRF24_REG_TX_ADDR, (uint8_t *)TX_ADDRESS, NRF24_ADDR_WIDTH);
  229.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_EN_AA, 0x3f);
  230.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_EN_RXADDR, 0x3f);
  231.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_SETUP_RETR, 0x0a);
  232.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_RF_CH, 40);
  233.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_RF_SETUP, 0x07);
  234.     switch (mode)
  235.     {
  236.         case NRF24_MODE_RX:
  237.         case NRF24_MODE_IT:
  238.             NRF24L01_Write_From_Buf(NRF24_CMD_REGISTER_W + NRF24_REG_RX_ADDR_P0, (uint8_t *)RX_ADDRESS, NRF24_ADDR_WIDTH);
  239.             NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_CONFIG, 0x0F);
  240.             break;
  241.         case NRF24_MODE_TX:
  242.         default:
  243.             NRF24L01_Write_From_Buf(NRF24_CMD_REGISTER_W + NRF24_REG_RX_ADDR_P0, (uint8_t *)TX_ADDRESS, NRF24_ADDR_WIDTH);
  244.             NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_CONFIG, 0x0E);
  245.             break;
  246.     }
  247.     NRF_CE = 1;
  248. }

  249. void NRF24L01_printBuf(void)
  250. {
  251.     for (uint8_t i = 0; i < NRF24_PLOAD_WIDTH; i++)
  252.     {
  253.         printf_tiny("%x ", rx_buf[i]);
  254.     }
  255.     printf_tiny("\r\n");
  256. }

  257. void NRF24L01_irqHandler(void) __interrupt IE0_VECTOR
  258. {
  259.     uint8_t state = NRF24L01_Read_Reg(NRF24_REG_STATUS);
  260.     printf_tiny("Interrupted, state: %x\r\n", state);
  261.     NRF24L01_Write_Reg(NRF24_CMD_REGISTER_W + NRF24_REG_STATUS, state);
  262.     if (state & NRF24_FLAG_RX_DREADY)
  263.     {
  264.         NRF24L01_Read_To_Buf(NRF24_CMD_RX_PLOAD_R, rx_buf, NRF24_PLOAD_WIDTH);
  265.         NRF24L01_FlushRX();
  266.         NRF24L01_printBuf();
  267.     }
  268. }

  269. void EXTI_init(void)
  270. {
  271.     EXTI_configTypeDef ec;

  272.     ec.mode     = EXTI_mode_lowLevel;
  273.     ec.priority = IntPriority_High;
  274.     EXTI_config(PERIPH_EXTI_0, &ec);
  275.     EXTI_cmd(PERIPH_EXTI_0, ENABLE);
  276.     UTIL_setInterrupts(ENABLE);
  277. }

  278. void SPI_init(void)
  279. {
  280.     SPI_configTypeDef sc;
  281.     sc.baudRatePrescaler = SPI_BaudRatePrescaler_4;
  282.     sc.cpha = SPI_CPHA_1Edge;
  283.     sc.cpol = SPI_CPOL_low;
  284.     sc.firstBit = SPI_FirstBit_MSB;
  285.     sc.pinmap = SPI_pinmap_P1;
  286.     sc.nss = SPI_NSS_Soft;
  287.     sc.mode = SPI_Mode_Master;
  288.     SPI_config(&sc);
  289.     SPI_cmd(ENABLE);
  290. }

  291. void main(void)
  292. {
  293.     UTIL_enablePrintf();
  294.     SPI_init();

  295.     while (NRF24L01_Check())
  296.     {
  297.         printf_tiny("Check failed, waiting retry\r\n");
  298.         sleep(500);
  299.     }

  300.     NRF24L01_init(CURRENT_MODE);

  301.     if (CURRENT_MODE == NRF24_MODE_RX)
  302.     {
  303.         while (true)
  304.         {
  305.             uint8_t sta = NRF24L01_RxPacket(rx_buf);
  306.             printf_tiny("RX stat: %x\r\n", sta);
  307.             NRF24L01_printBuf();
  308.         }
  309.     }
  310.     else if (CURRENT_MODE == NRF24_MODE_IT)
  311.     {
  312.         EXTI_init();
  313.         while(true);
  314.     }
  315.     else
  316.     {
  317.         uint8_t tmp[] = {
  318.             0x1F, 0x80, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
  319.             0x21, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x28,
  320.             0x31, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x38,
  321.             0x41, 0x12, 0x13, 0x14, 0x15, 0x16, 0x37, 0x48};
  322.         while (true)
  323.         {
  324.             uint8_t sta = NRF24L01_TxPacket(tmp);
  325.             tmp[1] = sta;
  326.             printf_tiny("TX stat: %x\r\n", sta);
  327.             sleep(500);
  328.         }
  329.     }
  330. }
复制代码



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表