我想要将usbd_cdc_acm中的usbd_user_ev_handlercdc_acm_user_ev_handler嵌入到light_switch_client当中,来代替原来light_switch_client中的button_event_handler,从而实现我通过串口助手向usb发送简单的命令如'on', 'off'字符串,然后通过此来发送generic_onoff_client_set等操作而不是通过按钮

    现在我遇到的问题是,当我对串口发送任意字符时,开发板会出现如下的状况
    然后卡住

      相关代码如下:

      static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                          app_usbd_cdc_acm_user_event_t event)
      {
          app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
      
          switch (event)
          {
              case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
              {
                  /*Set up the first transfer*/
                  ret_code_t ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                         m_cdc_data_array,
                                                         1);
                  UNUSED_VARIABLE(ret);
                  //ret = app_timer_stop(m_blink_cdc);
                  //APP_ERROR_CHECK(ret);
                  //bsp_board_led_on(LED_CDC_ACM_CONN);
                  //NRF_LOG_INFO("CDC ACM port opened");
                  break;
              }
      
              case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
                  //NRF_LOG_INFO("CDC ACM port closed");
                  //if (m_usb_connected)
                  //{
                  //    ret_code_t ret = app_timer_start(m_blink_cdc,
                  //                                     APP_TIMER_TICKS(LED_BLINK_INTERVAL),
                  //                                     (void *) LED_CDC_ACM_CONN);
                  //    APP_ERROR_CHECK(ret);
                  //}
                  break;
      
              case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
                  break;
      
              case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
              {
                  generic_onoff_set_params_t set_params;
                  model_transition_t transition_params;
                  static uint8_t tid = 0;
      
                  set_params.tid = tid++;
                  if (tid % 2 == 0) set_params.on_off = APP_STATE_OFF;
                  else set_params.on_off = APP_STATE_ON;
                  transition_params.delay_ms = APP_ONOFF_DELAY_MS;
                  transition_params.transition_time_ms = APP_ONOFF_TRANSITION_TIME_MS;
      
                  (void)access_model_reliable_cancel(m_clients[0].model_handle);
                  (void)generic_onoff_client_set(&m_clients[0], &set_params, &transition_params);
                  hal_led_pin_set(BSP_LED_0, set_params.on_off);
                  //ret_code_t ret;
                  //static uint8_t index = 0;
                  //index++;
      
                  //do
                  //{
                  //    if ((m_cdc_data_array[index - 1] == '\n') ||
                  //        (m_cdc_data_array[index - 1] == '\r') ||
                  //        (index >= (244)))
                  //    {
                  //        if (index > 1)
                  //        {
                  //            uint16_t length = (uint16_t)index;
      
                  //            if (length + sizeof(ENDLINE_STRING) < 244)
                  //            {
                  //                memcpy(m_cdc_data_array + length, ENDLINE_STRING, sizeof(ENDLINE_STRING));
                  //                length += sizeof(ENDLINE_STRING);
                  //            }
      
                  //            generic_onoff_set_params_t set_params;
                  //            model_transition_t transition_params;
                  //            static uint8_t tid = 0;
      
                  //            if (m_cdc_data_array[0] == 'o' &&  m_cdc_data_array[1] == "n") {
                  //                set_params.on_off = APP_STATE_ON;
                  //            } else {
                  //                set_params.on_off = APP_STATE_OFF;
                  //            }
                              
                  //            set_params.tid = tid++;
                  //            transition_params.delay_ms = APP_ONOFF_DELAY_MS;
                  //            transition_params.transition_time_ms = APP_ONOFF_TRANSITION_TIME_MS;
                              
                  //            (void)access_model_reliable_cancel(m_clients[0].model_handle);
                  //            (void)generic_onoff_client_set(&m_clients[0], &set_params, &transition_params);
                  //            hal_led_pin_set(BSP_LED_0, set_params.on_off);
                  //        }
      
                  //        index = 0;
                  //    }
      
                  //    /*Get amount of data transferred*/
                  //    //size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
                  //    //NRF_LOG_DEBUG("RX: size: %lu char: %c", size, m_cdc_data_array[index - 1]);
      
                  //    /* Fetch data until internal buffer is empty */
                  //    ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                  //                                &m_cdc_data_array[index],
                  //                                1);
                  //    if (ret == NRF_SUCCESS)
                  //    {
                  //        index++;
                  //    }
                  //}
                  //while (ret == NRF_SUCCESS);
      
                  //break;
              }
              default:
                  break;
          }
      }
      static void usbd_user_ev_handler(app_usbd_event_type_t event)
      {
          switch (event)
          {
              case APP_USBD_EVT_DRV_SUSPEND:
                  break;
      
              case APP_USBD_EVT_DRV_RESUME:
                  break;
      
              case APP_USBD_EVT_STARTED:
                  break;
      
              case APP_USBD_EVT_STOPPED:
                  app_usbd_disable();
                  break;
      
              case APP_USBD_EVT_POWER_DETECTED:
                  //NRF_LOG_INFO("USB power detected");
      
                  if (!nrf_drv_usbd_is_enabled())
                  {
                      app_usbd_enable();
                  }
                  break;
      
              case APP_USBD_EVT_POWER_REMOVED:
              {
                  //NRF_LOG_INFO("USB power removed");
                  //ret_code_t err_code = app_timer_stop(m_blink_cdc);
                  //APP_ERROR_CHECK(err_code);
                  //bsp_board_led_off(LED_CDC_ACM_CONN);
                  m_usb_connected = false;
                  app_usbd_stop();
              }
                  break;
      
              case APP_USBD_EVT_POWER_READY:
              {
                  //NRF_LOG_INFO("USB ready");
                  //ret_code_t err_code = app_timer_start(m_blink_cdc,
                  //                                      APP_TIMER_TICKS(LED_BLINK_INTERVAL),
                  //                                      (void *) LED_CDC_ACM_CONN);
                  //APP_ERROR_CHECK(err_code);
                  m_usb_connected = true;
                  app_usbd_start();
              }
                  break;
      
              default:
                  break;
          }
      }

        zqaking 你可以参考官方的cdc的示例工程,或者可以利用rtt实现输入或输出的功能

          case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:原来我引用的也是官方例程,之前也是卡起了,然后改成这样了。
          不过这样显然更不行,没有判断回车换行符,好像输入的时候一直卡在这里。因此我又改回原来的

          case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
                  {
                      ret_code_t ret;
                      static uint8_t index = 0;
                      static char StrTrue[] = "begin is ok\r\r\n";
                      static char StrFalse[] = "end is ok\r\r\n";
                      static char cmp[] = "on\r\r\n";
                      index++;
          
                      do
                      {
                          if ((m_cdc_data_array[index - 1] == '\n') ||
                              (m_cdc_data_array[index - 1] == '\r') ||
                              (index >= (244)))
                          {
                              if (index > 1)
                              {   
                                  generic_onoff_set_params_t set_params;
                                  model_transition_t transition_params;
                                  uint32_t status = NRF_SUCCESS;
                                  static uint8_t tid = 0;
          
                                  nrf_gpio_pin_toggle(BSP_LED_0);
                                  uint16_t length = (uint16_t)index;
                                  if (length + sizeof(ENDLINE_STRING) < 244)
                                  {
                                      memcpy(m_cdc_data_array + length, ENDLINE_STRING, sizeof(ENDLINE_STRING));
                                      length += sizeof(ENDLINE_STRING);
                                  }
                                  if (strcmp(m_cdc_data_array, cmp) == 0) 
                                      set_params.on_off = APP_STATE_ON;
                                  else
                                      set_params.on_off = APP_STATE_OFF;
          
                                  set_params.tid = tid++;
                                  transition_params.delay_ms = APP_ONOFF_DELAY_MS;
                                  transition_params.transition_time_ms = APP_ONOFF_TRANSITION_TIME_MS;
                                  
                                  //(void)access_model_reliable_cancel(m_clients[0].model_handle);
                                  app_usbd_cdc_acm_write(&m_app_cdc_acm, StrTrue, sizeof(StrTrue) / sizeof(StrTrue[0]));
                                  status = generic_onoff_client_set_unack(&m_clients[1], &set_params,
                                                              &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
                                  app_usbd_cdc_acm_write(&m_app_cdc_acm, StrFalse, sizeof(StrFalse) / sizeof(StrFalse[0]));
                              }
          
                              index = 0;
                          }
          
                          /*Get amount of data transferred*/
                          //size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
                          //NRF_LOG_DEBUG("RX: size: %lu char: %c", size, m_cdc_data_array[index - 1]);
          
                          /* Fetch data until internal buffer is empty */
                          ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                      &m_cdc_data_array[index],
                                                      1);
                          if (ret == NRF_SUCCESS)
                          {
                              index++;
                          }
                      }
                      while (ret == NRF_SUCCESS);
          
                      break;
                  }

          但这个的问题就是在配置app key成功后再通过generic_onoff_client_set_unack()就会卡起,其他情况正常。

            zqaking 你可以单步跳进generic_onoff_client_set_unack()这个函数看看吗?我一时半会也看不出什么问题

            Wireless-Tech
            抱歉,额。我通过另一种方式解决了这个问题。

            case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
                    {
                        ret_code_t ret;
                        static uint8_t index = 0;
                        index++;
            
                        do
                        {
                            if ((m_cdc_data_array[index - 1] == '\n') ||
                                (m_cdc_data_array[index - 1] == '\r') ||
                                (index >= (244)))
                            {
                                if (index > 1)
                                {   
                                    nrf_gpio_pin_toggle(BSP_LED_0);
                                    uint16_t length = (uint16_t)index;
                                    if (length + sizeof(ENDLINE_STRING) < 244)
                                    {
                                        memcpy(m_cdc_data_array + length, ENDLINE_STRING, sizeof(ENDLINE_STRING));
                                        length += sizeof(ENDLINE_STRING);
                                    }
                                    if (strcmp(m_cdc_data_array, "on\r\r\n") == 0) SetState = true;
                                    else SetState = false;
                                    DataChange = true;
                                }
            
                                index = 0;
                            }
                            /* Fetch data until internal buffer is empty */
                            ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                        &m_cdc_data_array[index],
                                                        1);
                            if (ret == NRF_SUCCESS)
                            {
                                index++;
                            }
                        }
                        while (ret == NRF_SUCCESS);
            
                        break;
                    }

            在这里我添加了一个DataChange变量来判断一次USB CDC ACM事件。然后自定义一个定时器对此的触发事件

            APP_TIMER_DEF(zqaking_timer_id);
            
            static void zqaking_app_timer_handler(void * p_unused)
            {   
                if (DataChange)
                {
                    //app_usbd_cdc_acm_write(&m_app_cdc_acm, my_data_buffer, my_data_buffer_lenght);
                    DataChange = false;
                    uint32_t status;
                    generic_onoff_set_params_t set_params;
                    model_transition_t transition_params;
                    static uint8_t tid = 0;
            
                    if (SetState) set_params.on_off = APP_STATE_ON;
                    else set_params.on_off = APP_STATE_OFF;
                    SetState = false;
            
                    set_params.tid = tid++;
                    transition_params.delay_ms = APP_ONOFF_DELAY_MS;
                    transition_params.transition_time_ms = APP_ONOFF_TRANSITION_TIME_MS;
                    
                    status = hx_model_client_opcode_tx_unreliable(&m_hx_model_client[0], (uint8_t *)str, (uint16_t)StrLen, APP_UNACK_MSG_REPEAT_COUNT);
                    if (status == NRF_SUCCESS) app_usbd_cdc_acm_write(&m_app_cdc_acm, str, StrLen);
            
                    status = generic_onoff_client_set_unack(&m_clients[1], &set_params,
                                                               &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
                }
            }
            
            static void start(void)
            {   ···
                ERROR_CHECK(app_timer_create(&zqaking_timer_id, APP_TIMER_MODE_REPEATED, zqaking_app_timer_handler));
                ERROR_CHECK(app_timer_start(zqaking_timer_id, 6000, NULL));
                ···
            };

              zqaking
              这样就能成功发送,之前不行的原因我觉得可能是USBmesh之间有时钟的冲突。因为我在这个过程中乱尝试的时候,添加的定时器是app_timer.ctimer2,然后也出现了相类似的情况也是卡住四个led灯全亮。后来才知道它和mesh使用的app_timer_mesh.c不能够兼容。不过我不太确定是否真的是这样

              另外说明一下

              ERROR_CHECK(app_timer_create(&zqaking_timer_id, APP_TIMER_MODE_REPEATED, zqaking_app_timer_handler));
              ERROR_CHECK(app_timer_start(zqaking_timer_id, 6000, NULL));

              我在使用app_timer_mesh本来使用了APP_TIMER_TICKS,但是好像没有成功,重新改为6000才好。不知道是不是两类定时器之间的差别

                Wireless-Tech
                还是感谢大佬让我看RTT内容,发现RTT中定时器才想到这个方法

                撰写回复...