STM32WB55는 무선 관련 스텍이 별도의 코어에서 수행되고 필요에 따라서 원하는 무선 프로파일을 다운로드 해서 사용할 수 있는 구조이다. nRF5시리즈의 SoftStack과 유사한 구조 이다. 차이점이라면 별도의 코어로 동작하기 때문에 장단점이 있을 수 있겠다.
Zigbee 스택을 이용해서 무선으로 데이터 전송하는 테스트를 해 보자.
우선 Zigbee중 FFD(풀스택)을 다운로드 해서 테스트 해보면 좋을것 같다.
무선 스텍은 STM32WB_Copro_Wireless_Binaries 폴더에 있다.
소프트에어 스택 다운로드 방법은 STM32CubeProgrammer 를 이용하여 다운로드 하면 된다. 아래 그림과 같은 순서로 다운로드 하면된다. 주의 사항으로는 Start address 를 스택별, STM32WB 메모리 사양별로 다르게 지정해 주어야 한다.
Zigbee 예제를 이용해서 프로그램을 작성하려면 ST에서 제공하는 STM32_WPAN 라이브러리 폴더를 추가 해야 한다.
그리고 APP쪽에서 각 어플리케이션에 맞는 app_zigbee.c 를 추가해서 수정하면 된다.
Zigbee네트웍 연결
app_zigbee.c 코드에 Zigbee관련 처리 함수가 제공된다.
Zigbee 데이터 송수신을 위해 Zigbee 네트웍에 조인 해야 하는 APP_ZIGBEE_NwkFrom() 함수에서 처리 할 수 있다.
static void APP_ZIGBEE_NwkForm(void)
{
if ((zigbee_app_info.join_status != ZB_STATUS_SUCCESS) && (HAL_GetTick() >= zigbee_app_info.join_delay))
{
struct ZbStartupT config;
enum ZbStatusCodeT status;
/* Configure Zigbee Logging */
ZbSetLogging(zigbee_app_info.zb, ZB_LOG_MASK_LEVEL_5, NULL);
/* Attempt to join a zigbee network */
ZbStartupConfigGetProDefaults(&config);
/* Set the centralized network */
APP_DBG("Network config : APP_STARTUP_CENTRALIZED_END_DEVICE");
config.startupControl = zigbee_app_info.startupControl;
/* Using the default HA preconfigured Link Key */
memcpy(config.security.preconfiguredLinkKey, sec_key_ha, ZB_SEC_KEYSIZE);
config.channelList.count = 1;
config.channelList.list[0].page = 0;
config.channelList.list[0].channelMask = 1 << CHANNEL; /*Channel in use */
/* Add End device configuration */
config.capability &= ~(MCP_ASSOC_CAP_RXONIDLE | MCP_ASSOC_CAP_DEV_TYPE | MCP_ASSOC_CAP_ALT_COORD);
config.endDeviceTimeout=ZED_SLEEP_TIME_30S;
/* Using ZbStartupWait (blocking) */
status = ZbStartupWait(zigbee_app_info.zb, &config);
APP_DBG("ZbStartup Callback (status = 0x%02x)", status);
zigbee_app_info.join_status = status;
if (status == ZB_STATUS_SUCCESS) {
/* Enabling Stop mode */
UTIL_LPM_SetStopMode(1U << CFG_LPM_APP, UTIL_LPM_ENABLE);
UTIL_LPM_SetOffMode(1U << CFG_LPM_APP, UTIL_LPM_DISABLE);
/* USER CODE BEGIN 0 */
zigbee_app_info.join_delay = 0U;
zigbee_app_info.init_after_join = true;
gZigbeeStatus = 1;
//Led1Off();
Led1Toggle();
//BSP_LED_On(LED_BLUE);
}
데이터 수신 콜백 함수
app_zigbee.c 에서 콜백 함수로 등록 하면 된다.
zigbee로 데이터를 받느면 custom_ls_set_cb() 함수가 수행되고 여기서 받은 데이터를 처리 하면 된다.
static void APP_ZIGBEE_ConfigEndpoints(void)
{
struct ZbApsmeAddEndpointReqT req;
struct ZbApsmeAddEndpointConfT conf;
APP_DBG("APP_ZIGBEE_ConfigEndpoints");
memset(&req, 0, sizeof(req));
req.profileId = ZCL_PROFILE_HOME_AUTOMATION;
req.deviceId = ZCL_DEVICE_ONOFF_SWITCH;
/* Endpoint: SW1_ENDPOINT */
req.endpoint = SW1_ENDPOINT;
ZbZclAddEndpoint(zigbee_app_info.zb, &req, &conf);
assert(conf.status == ZB_STATUS_SUCCESS);
/* Custom long string cluster server */
zigbee_app_info.custom_ls_server = ZbZcl_custom_ls_ServerAlloc(zigbee_app_info.zb, \
SW1_ENDPOINT, &custom_ls_server_cb, &zigbee_app_info);
ZbZclClusterEndpointRegister(zigbee_app_info.custom_ls_server);
} /* config_endpoints */
static enum ZclStatusCodeT custom_ls_set_cb(struct ZbZclClusterT *clusterPtr, \
struct set_custom_ls_command_req_t *cmd_req, \
struct ZbZclAddrInfoT *src_info, void *arg)
{
//char buf[64];
char *msg = "";
/* We display the message received here */
//수신 데이터 처리
printf(cmd_req->string);
printf("\r\n");
#if 1
if(memcmp((char*)&cmd_req->string[0],(char*)&msg[0],30)!=0)
{
rsp.one = ZCL_CUSTOM_LS_MISMATCH;
}
else
{
rsp.one = ZCL_CUSTOM_LS_MATCH;
}
/* Send the response */
ZbZcl_custom_ls_ServerSendCommandRsp(clusterPtr, src_info, &rsp);
#endif
BSP_LED_Toggle(LED_RED);
return ZCL_STATUS_SUCCESS;
}
데이터 송신
ZbZclSet_custom_ls_ClientCommand() 함수를 이용하여 데이터를 전송할 수 있다.
int SendSensorMsg(char *msg)
{
struct ZbApsAddrT dst;
memset(&dst, 0, sizeof(dst));
dst.mode = ZB_APSDE_ADDRMODE_SHORT; /* for unicast */
dst.endpoint = SW1_ENDPOINT;
dst.nwkAddr = 0x0000; /* Coordinator short address */
Led1Toggle();
if (ZbZclSet_custom_ls_ClientCommand(zigbee_app_info.custom_ls_client,
&dst,msg, custom_ls_client_cb, NULL) != ZCL_STATUS_SUCCESS)
{
APP_DBG("Error, ZbZclSet_custom_ls_ClientCommand failed (SW1_ENDPOINT)");
Led1Toggle();
return 3;
}
else
{
gSendCount++;
}
return 0;
}
APP에서 사용자 인터페이스 처리는 app_entry.c 파일에 설정 할 수 있다.
스위치 입력에 따른 인터럽시 Zigbee 데이터 전송하는 코드를 작성했다.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch (GPIO_Pin)
{
case GPIO_PIN_4:
SendSensorMsg("STM32WB55 Zigbee Data");
break;
default:
break;
}
}