这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【FRDM-MCXW71测评】5、成果贴:蓝牙测试

共1条 1/1 1 跳转至

【FRDM-MCXW71测评】5、成果贴:蓝牙测试

高工
2025-05-22 22:45:19     打赏

        我们进一步进行无线控制,依然是这几个模式,只不过这一次通过蓝牙方式进行。

        先说说遇到的坑吧,首先是蓝牙调试,FRDM-MCXW71是一个双核工作的,虽然板子就一个天线接口:

        image.png

        也就是说我们目前调试M33核是一个主核,无线十一个专用的核,用于独立的内存,初始化状态下这个专有核是没有内容的,并不支持直接编辑,通过对无线板块的测试了解,可以看到专有核需要下载单独的固件,这一部分可以参考另一位网友的的下载过程,https://forum.eepw.com.cn/thread/391830/1

        固件问题解决后,在测试demo的时候,我是通过nRF Connect进行的搜索,居然搜不到,我直接通过手机蓝牙也没有搜到,无奈只能用NXP iot Toolbox这个官方软件了。

        终于可以通信,接下来我们将通过wireless_uart例程了解蓝牙通信的过程,整体的流程是就与GATT协议的,在进行功能的启动后主要也是进行Callback处理,我们的主要处理也是在wireless_uart.c中进行。

        我们先看一下wireless_uart例程,以下是串口打印的内容:

image.png

        前一天晚上一直通过软件无法发现,官方软件都没有发现,原来是出在了这里,正常情况下例程初始状态是出于主机模式下的,通过SW2按键可以开启搜索,不过我们要让BLE出于从机,需要通过SW2+SW4组合键进行切换,这样就能让app发现了,通过NXP iot Toolbox的wireless_uart模块可以发现一个叫NXP_WU设备了,终于通了,接下来我们就在例程的继承下实现上面相同的LED控制,注意LED_B由于需要状态显示,我们不控制他,前期的时候也有RGB的控制,所以默认情况下连接上后是不启动的,只有收到1-3才会控制模式的开始,其他情况直接关闭。在测试例程的时候发现,手机app不能发送hex数据,1-3对应的是“1”-“3”。

        咱们回到例程的程序中去,在main.c中实现的,添加定时器的初始化片段,我尝试通过初始化工具添加,会造成未知的错误,不好解决,这也是固件中的例程与初始化工具的不兼容,不知道为什么固件中的例程都是不适用初始化工具实现的,尤其是外设的使用,先添加定时器功能并启用:

#define DEMO_LPTMR_BASE    LPTMR0
#define LPTMR_USEC_COUNT   1000000
#define DEMO_LPTMR_IRQn    LPTMR0_IRQn
#define LPTMR_LED_HANDLER  LPTMR0_IRQHandler
#define LPTMR_SOURCE_CLOCK (CLOCK_GetFreq(kCLOCK_ScgSircClk))

LPTMR_GetDefaultConfig(&lptmrConfig);
LPTMR_Init(DEMO_LPTMR_BASE, &lptmrConfig);
LPTMR_SetTimerPeriod(DEMO_LPTMR_BASE, USEC_TO_COUNT(LPTMR_USEC_COUNT, LPTMR_SOURCE_CLOCK));
LPTMR_EnableInterrupts(DEMO_LPTMR_BASE, kLPTMR_TimerInterruptEnable);
EnableIRQ(DEMO_LPTMR_IRQn);
LPTMR_StartTimer(DEMO_LPTMR_BASE);

        然后LED的控制放到中断中,本例程的定时器中断放在fsl_adapter_timer.c中:

static void HAL_TimerInterruptHandle(uint8_t instance)
{
    hal_timer_handle_struct_t *halTimerState = (hal_timer_handle_struct_t *)s_timerHandle[instance];
    uint32_t lptmrIntFlag;

    if (NULL == halTimerState)
    {
        return;
    }

    lptmrIntFlag = LPTMR_GetStatusFlags(s_LptmrBase[instance]);
    LPTMR_ClearStatusFlags(s_LptmrBase[instance], (uint32_t)kLPTMR_TimerCompareFlag);
    LED_TimeCnt++;
      if(LED_TimeCnt >= 50)
      {
          LED_TimeCnt = 0;
          if(LED_Mode != LED_Modeing){
              GPIO_PortSet(GPIOA, 1U << 19U);
              GPIO_PortSet(GPIOA, 1U << 20U);
              GPIO_PortSet(GPIOA, 1U << 21U);
              LED_Modeing = LED_Mode;
          }
          switch(LED_Modeing){
          case 1:
              GPIO_PortToggle(GPIOA, 1U << 19U);
              break;
          case 2:
              GPIO_PortToggle(GPIOA, 1U << 20U);
              break;
          case 3:
              GPIO_PortToggle(GPIOA, 1U << 21U);
              break;
          default:
              break;
          }

      }

    if (0U != lptmrIntFlag)
    {
        if (halTimerState->callback != NULL)
        {
            halTimerState->callback(halTimerState->callbackParam);
        }
    }
}

void PWT_LPTMR0_IRQHandler(void);
void PWT_LPTMR0_IRQHandler(void)
{
    HAL_TimerInterruptHandle(0);
    SDK_ISR_EXIT_BARRIER;
}

        接下来就是重点的蓝牙接口的回调函数了,蓝牙的处理都在wireless_uart.c中,这里面有蓝牙信息处理的回调函数——static void BleApp_GattServerCallback(deviceId_t deviceId,gattServerEvent_t *pServerEven),我们主要在这里进行数据处理。我们这次用的是一个蓝牙+串口的一个透传函数,用的就是BleApp_ReceivedUartStream这个函数,我们对LED的模式处理就加载这里,通过获取蓝牙服务的数据和长度进行判断,以下是蓝牙服务的结构体gattServerEvent_t:

typedef struct {
    gattServerEventType_t eventType;    /*!< Event type. */
    union {
        gattServerMtuChangedEvent_t                 mtuChangedEvent;        /*!< For event type gEvtMtuChanged_c: the new value of the ATT_MTU. */
        gattServerAttributeWrittenEvent_t           attributeWrittenEvent;  /*!< For event types gEvtAttributeWritten_c, gEvtAttributeWrittenWithoutResponse_c: handle and value of the attempted write. */
        gattServerCccdWrittenEvent_t                charCccdWrittenEvent;   /*!< For event type gEvtCharacteristicCccdWritten_c: handle and value of the CCCD. */
        gattServerProcedureError_t                  procedureError;         /*!< For event type gEvtError_c: error that terminated a Server-initiated procedure. */
        gattServerLongCharacteristicWrittenEvent_t  longCharWrittenEvent;   /*!< For event type gEvtLongCharacteristicWritten_c: handle and value. */
        gattServerAttributeReadEvent_t              attributeReadEvent;     /*!< For event types gEvtAttributeRead_c: handle of the attempted read. */
        gattServerInvalidPdu_t                      attributeOpCode;        /*!< For event type gEvtInvalidPduReceived_c: the ATT PDU that generated the error */
    } eventData;                            /*!< Event data : selected according to event type. */
} gattServerEvent_t;

        对应于`gattServerEvent_t`中的`gattServerAttributeWrittenEvent_t`事件,`aValue`和`cValueLength`字段的处理,本文采用了一种简化的方法。具体而言,该方法针对接收到的单一字符串执行单一状态的处理逻辑,例如,将字符串“1”映射为蓝灯闪烁状态。通过扩展字符串的长度,我们同样具备修改通信协议的能力。根据控制对象实现命令的控制:

void RGB_Command(void)
{
    if (command_uart == '1' && command_lenght <= 2)
    {
        LED_Mode = command_uart-48;
    }
    else if (command_uart == '2' && command_lenght <= 2)
    {
        LED_Mode = command_uart-48;
    }
    else if (command_uart == '3' && command_lenght <= 2)
    {
        LED_Mode = command_uart-48;
    }
    else
    {
        LED_Mode = command_uart
    }
}

        接下来就是把他们放到各自的位置,首先是创建一个`aValue`和`cValueLength`字段对应的变量:

uint8_t command_uart;
uint8_t command_lenght;

        并与蓝牙服务字段关联:

image.png

        然后将RGB_Command(void)放入处理程序位置,在BleApp_ReceivedUartStream中:

image.png

        综合效果如下:

【综合测试(蓝牙)】 https://www.bilibili.com/video/BV19vJnzmETP/?share_source=copy_web&vd_source=b04da51472e5874aa452f4a273672c46









关键词: FRDM-MCXW71     蓝牙     测试    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]