收到MM32W373PSB蓝牙开发板已有段时间,今天周末,来体验一下它的自拍杆功能。MM32W373PSB的应用广泛,可以Beacon、无线键盘、鼠标、工业应用:工业遥控、遥测、警报系统、门禁系统、数据采集和传输系统、便捷式医疗设备、可穿戴的运动和健身设备。MM32W373PSB集成了32位ARM Cortex-M3处理器内核,最高工作频率可达96MHz,ARM Cortex-M3处理器是最新一代的嵌入式ARM处理器,它为实现MCU的需要提供了低成本的平台、缩减的引脚数目、降低的系统功耗,同时提供卓越的计算性能和先进的中断系统响应。
       本次体验的功能比较简单,将开发板上电,然后打开手机蓝牙,搜索并连接上“MindMotion-Shutter”蓝牙设备,然后打开手机的照相机,放在离开发板有一定距离的地方,然后通过按下按键K4来抓拍美丽的瞬间。主要的几个源文件与调用函数简单的罗列一下:
#include "sys.h"
  • #include "delay.h"
  • #include "uart.h"
  • #include "spi.h"
  • #include "RF_IRQ.h"
  • #include <string.h>
  • #include "HAL_conf.h"
  • #include "mg_api.h"
  • #include "mg_test_api.h"
  • #include "iwdg.h"
  • #include "RF_Callback.h"
  • extern void Key_Shutter_Init(void);
  • unsigned char *ble_mac_addr;
  • u8 value_t[2];
  • unsigned char *get_local_addr(void) //used for ble pairing case
  • {
  •   return ble_mac_addr;
  • }
  • void  BLE_SV()
  • {
  •   unsigned char *BLE_SV = get_ble_version();
  • }
  • u8 ADV_Data[] = {'T', 'E', 'S', 'T'};
  • unsigned long i;
  • int main(void)
  • {
  •   unsigned long temp = 0x800000;
  •   while (temp--);
  •   SPIM_Init(0x06);
  •   IRQ_RF();
  •   SYSTick_Configuration();
  •   uart_initwBaudRate();
  •   SetBleIntRunningMode();
  •   radio_initBle(TXPWR_3DBM, &ble_mac_addr);
  •   IWDG_Init(4, 625);
  •   Key_Shutter_Init();
  •   value_t[0] = 0xc0;
  •   value_t[1] = *(u8 *)0x1FFFF820;    //Read FT value(FT value:The RF module is
  •   calibrated at the factory to prevent frequency deviation. The user can call the
  •   FT value in the program)
  •   ble_run_interrupt_start(80);          //320*0.625=200 ms
  •   while (1)
  •   {
  •   }
  • }
  • 复制代码
           官方底层协议栈提供了封装好的库函数,用户直接包含头文件,调用库函数即可
    #ifndef _MG_API_H_
  • #define _MG_API_H_
  • //TX power
  • #define TXPWR_3DBM 0x48
  • #define TXPWR_0DBM 0x43
  • #define        TXPWR__3DBM         64
  • #define        TXPWR__6DBM         61
  • #define        TXPWR__8DBM         58
  • #define        TXPWR__15DBM 48
  • // ATT Error Codes
  • #define ATT_ERR_INVALID_HANDLE           0x01
  • #define ATT_ERR_READ_NOT_PERMITTED       0x02
  • #define ATT_ERR_WRITE_NOT_PERMITTED      0x03
  • #define ATT_ERR_INVALID_PDU              0x04
  • #define ATT_ERR_INSUFFICIENT_AUTHEN      0x05
  • #define ATT_ERR_UNSUPPORTED_REQ          0x06
  • #define ATT_ERR_INVALID_OFFSET           0x07
  • #define ATT_ERR_INSUFFICIENT_AUTHOR      0x08
  • #define ATT_ERR_PREPARE_QUEUE_FULL       0x09
  • #define ATT_ERR_ATTR_NOT_FOUND           0x0a
  • #define ATT_ERR_ATTR_NOT_LONG            0x0b
  • #define ATT_ERR_INSUFFICIENT_KEY_SIZE    0x0c
  • #define ATT_ERR_INVALID_VALUE_SIZE       0x0d
  • #define ATT_ERR_UNLIKELY                 0x0e
  • #define ATT_ERR_INSUFFICIENT_ENCRYPT     0x0f
  • #define ATT_ERR_UNSUPPORTED_GRP_TYPE     0x10
  • #define ATT_ERR_INSUFFICIENT_RESOURCES   0x11
  • //adv header type
  • #define ADV_HDR_TYPE_PUBLIC_IND         0x00
  • #define ADV_HDR_TYPE_RANDOM_IND         0x80
  • #define ADV_HDR_TYPE_PUBLIC_NONCONN_IND  0x02
  • #define ADV_HDR_TYPE_RANDOM_NONCONN_IND  0x82
  • //Function: radio_initBle
  • //Parameters: txpwr - input, txpower;   addr - output, BLE device address
  • //return: None
  • void radio_initBle(unsigned char txpwr, unsigned char** addr/*out*/);  //init ble mode, should be called first after spi initialization
  • //Function: radio_initBle_TO
  • //Parameters: txpwr - input, txpower;   addr - output, BLE device address;   ms_timeout - timeout for BLE initialization, recommend value 10~50
  • //return: 0 - fail;  none 0 - success
  • unsigned char radio_initBle_TO(unsigned char txpwr, unsigned char** addr, unsigned short ms_timeout);
  • //Function: radio_initBle_recover
  • //Parameters: txpwr - input, txpower;   addr - output, BLE device address
  • //return: None
  • void radio_initBle_recover(unsigned char txpwr, unsigned char** addr);
  • //Function: radio_setCal_nonBlocking
  • //Parameters: nonblocking - 0: blocking;  1: non blocking
  • //return: none
  • void radio_setCal_nonBlocking(unsigned nonblocking);
  • //Function: radio_standby
  • //this function is to set rf to standby mode, I ~ 3uA
  • //Parameters: none
  • //return: None
  • //called in UsrProcCallback or when ble_run_interrupt_McuCanSleep()>0
  • void radio_standby(void);
  • //Function: radio_resume
  • //this function is to recover rf from standby mode
  • //Parameters: none
  • //return: None
  • void radio_resume(void);
  •    
  • //Function: radio_setXtal
  • //this function is to config the params of xtal
  • //Parameters: xoib:0~f, xocc:0
  • //return: None
  • void radio_setXtal(unsigned char xoib, unsigned char xocc);
  • //Function: radio_setRxGain
  • //this function is to config the params of RX
  • //Parameters: lna_gain:0,5,6,7, preambe_th: 0x20 when lna_gain=0, 0x38 when lna_gain=5,6,7
  • //return: 0-input param error, 1-ok
  • unsigned char radio_setRxGain(unsigned char lna_gain, unsigned char preamble_th);
  • //Function: ble_run
  • //Parameters: interv_adv - advertise packet interval, unit 0.625ms
  • //return: None
  • //Remarks: never reurn!!!
  • void ble_run(unsigned short interv_adv);
  • //Function: ble_set_adv_data
  • //Parameters: adv - advertise packet payload; len - payload len
  • //return: None
  • void ble_set_adv_data(unsigned char* adv, unsigned char len);
  • //Function: ble_set_adv_rsp_data
  • //Parameters: rsp - advertise response payload; len - payload len
  • //return: None
  • void ble_set_adv_rsp_data(unsigned char* rsp, unsigned char len);
  • //Function: ble_set_name
  • //this function IS available when using default scan response data
  • //Parameters: name - device name; len - name len
  • //return: None
  • void ble_set_name(unsigned char* name,unsigned char len);
  • //Function: ble_set_adv_type
  • //Parameters: type - advertisement type, 0-adv_ind, 2-adv_nonconn_ind. default 0x80
  • //                   addr type,      0x80 - RANDOM, 0x00 - PUBLIC
  • //return: None
  • void ble_set_adv_type(unsigned char type);
  • //Function: ble_set_interval
  • //Parameters: interval - advertisement interval, unit 0.625ms
  • //return: None
  • void ble_set_interval(unsigned short interval);
  • //Function: ble_set_wakeupdly
  • //Parameters: counter - wake up delay time, unit 16uS
  • //return: 1
  • unsigned char ble_set_wakeupdly(unsigned short counter);
  • //Function: ble_set_adv_enableFlag
  • //this function is to enable/disable ble adv
  • //Parameters: sEnableFlag - 0 to disable adv, 1 to enable adv
  • //return: None
  • void ble_set_adv_enableFlag(char sEnableFlag);
  • //Function: ble_set_role
  • //this function is to set ble role to peripheral(0) or central(1), by default ble role is peripheral(0)
  • //Parameters: role_new - 0 peripheral, 1 central
  • //            scan_window - scan window for central rol. range: 0x0004~0x4000 (2.5ms ~ 10.24s)
  • //return: 0 - fail, 1 - success
  • unsigned char ble_set_role(unsigned char role_new, unsigned short scan_window);
  • //Function: ble_disconnect
  • //this function is to disconnected the ble connection
  • //Parameters: none
  • //return: None
  • void ble_disconnect(void);
  • unsigned char* GetFirmwareInfo(void); //such as "FVxx.2.0.2mmx"
  • unsigned char* get_ble_version(void); //such as "MG_BLE_LIB_V1.0"
  • unsigned char GetRssiData(void); //only valid after receive a packet
  • void att_notFd(unsigned char pdu_type, unsigned char attOpcode, unsigned short attHd );
  • void att_ErrorFd_eCode(unsigned char pdu_type, unsigned char attOpcode, unsigned short attHd, unsigned char errorCode);
  • void att_server_rdByGrTypeRspDeviceInfo(unsigned char pdu_type);
  • void att_server_rdByGrTypeRspPrimaryService(unsigned char pdu_type, unsigned short start_hd, unsigned short end_hd, unsigned char*uuid, unsigned char uuidlen);
  • void att_server_rd( unsigned char pdu_type, unsigned char attOpcode, unsigned short att_hd, unsigned char* attValue, unsigned char datalen );
  • void ser_write_rsp_pkt(unsigned char pdu_type);
  • unsigned char sconn_notifydata(unsigned char* data, unsigned char len);//returns data size has been sent, ******* user's safe API *********
  • unsigned char sconn_indicationdata(unsigned char* data, unsigned char len);
  • 复制代码
    void SIG_ConnParaUpdateReq(unsigned short IntervalMin, unsigned short IntervalMax, unsigned short slaveLatency, unsigned short TimeoutMultiplier);
  • unsigned short sconn_GetConnInterval(void);//get current used interval in the unit of 1.25ms
  • //Get current (or the latest) connected master device's MAC
  • //returns mac(6 Bytes, Little-Endian format) and the type(MacType, 0 means public type, others mean random type)
  • unsigned char* GetMasterDeviceMac(unsigned char* MacType);
  • //PAIR APIs
  • void SetLePinCode(unsigned char *PinCode/*6 0~9 digitals*/);
  • //Get current connected device's long term KEY's info(EDIV)
  • //returns u8* EDivData /*2 Bytes*/ (encrypted)
  • //newFlag: 1 means new paired device's info, 0 means old paired device's info.
  • //Remarks:
  • //  1. This function shall be invoked when [StartEncryption == 1].
  • //  2. This function is ONLY supported in pairing cases.
  • unsigned char* GetLTKInfo(unsigned char* newFlag);
  • //security manager module request for pair
  • //Remarks:
  • //  1. This function shall be invoked when [connected status == 1].
  • //  2. This function is ONLY supported in pairing cases.
  • void s_llSmSecurityReq(void);
  • //return:
  • // OTA_OK             0
  • // OTA_SN_ERROR       1
  • // OTA_CHECKSUM_ERROR 2
  • // OTA_FORMAT_ERROR   3
  • // OTA_UNKNOWN_ERROR  255
  • unsigned char OTA_Proc(unsigned char *data, unsigned short len);
  • //interrupt running mode APIs
  • //Function: SetBleIntRunningMode
  • //this function SHOULD be invoked before init the ble
  • //Parameters: None
  • //return: None
  • void SetBleIntRunningMode(void);
  • //Function: ble_run_interrupt_start
  • //   this function SHOULD be invoked to start the interrupt running mode in the main routine.
  • //   ble_run(0) function SHOULD ONLY be invoked in the ble irq interrupt service subroutine.
  • //Parameters:  interv_adv - advertise packet interval, unit 0.625ms
  • //return: None
  • void ble_run_interrupt_start(unsigned short interv_adv);
  • //Function: ble_nMsRoutine
  • //this function SHOULD be invoked every 1ms tick, one can invoke this function inside the systick routine
  • //Parameters: None
  • //return: None
  • void ble_nMsRoutine(void);
  • //Function: ble_run_interrupt_McuCanSleep
  • //this function CAN be invoked at main task, one can invoke this function to detect the BLE status then goto MCU sleep.
  • //Before doing so, one SHOULD configure the BLE irq down wakeup pin's function enabled.  
  • //Parameters: None
  • //return: None-zero means MCU can enter into stop/sleep mode.
  • unsigned char ble_run_interrupt_McuCanSleep(void);
  • //debug APIs
  • //Parameters: isFixCh37Flag - input, 1-adv on ch37 only, 0-adv on ch37,38,39. default:0
  • void SetFixAdvChannel(unsigned char isFixCh37Flag);
  • 复制代码
         BLE库以系统中断服务程序方式运行, 适合于实现用户某功能需要占用较长 CPU 时间但可以被打断的应用场景。常需要用到两个中断服务程序,一个是IRQ中断pin对应的GPIO中断, 一个是实现SysTick对应的中断。IRQ对应的中断服务程序用于运行蓝牙协议,需要有较高的中断优先级(针对其他用户中断来说)。关于开发板的工作状态可通过AT指令切换,其实质通过USE_AT_CMD的宏来进行模式切换
    //function list
  • AT_CMD_FUNC at_func_list[] =
  • {
  •   {atcmd_SetName, "SETNAME="},
  •   {atcmd_SetAdvInt, "SETINTERVAL="},
  •   {atcmd_SendData, "BLESEND="},
  •   {atcmd_LowPower, "LOWPOWER="},
  •   {atcmd_SetBaud, "SETBAUD="},
  •   {atcmd_SetAdvFlag, "SETADVFLAG="},
  •   {atcmd_DisconnecteBle, "DISCON"},
  •   {atcmd_Minfo, "MINFO"},
  •   {atcmd_Help, "HELP"},
  • };
  • 复制代码
         MM32W373PSB内置嵌套的向量式中断控制器,能够处理多达68个可屏蔽中断通道(不包括16个Cortex-M3的中断线)和16个可编程优先级。外部中断/事件控制器包含21个边沿检测器,用于产生中断/事件请求。每个中断线都可以独立地配置它的触发事件(上升沿或下降沿或双边沿),并能够单独地被屏蔽;有一个挂起寄存器维持所有中断请求的状态。EXTI可以检测到脉冲宽度小于内部APB2的时钟周期。多达40个通用I/O口连接到16个外部中断线。
         控制模块系统时钟的选择是在启动时进行,复位时内部48MHz的振荡器被选为默认的CPU时钟,随后可以选择外部的16MHz时钟;当检测到外部时钟失效时,它将被隔离,系统将自动地切换到内部的振荡器,如果使能了中断,软件可以接收到相应的中断。同样,在需要时可以采取对PLL时钟完全的中断管理(如当一个间接使用的外部振荡器失效时)。多个预分频器用于配置AHB的频率、高速APB(APB2和APB1)区域,AHB和高速APB的最高频率是96MHz。时钟树如下图所示:
    时钟树.png
        蓝牙ATT服务特征值在“app_hogp.c”文件中添加,包括以小端模式存储的128位uuid。
    const BLE_CHAR AttCharList[] = {
  • // ======  gatt =====  Do NOT Change!!
  •     {TYPE_CHAR,0x03,ATT_CHAR_PROP_RD, 0x04,0,0x00,0x2a,UUID16_FORMAT},//name
  •     //05-06 reserved
  • // ======  device info =====    Do NOT Change if using the default!!!  
  •     {TYPE_CHAR,0x08,ATT_CHAR_PROP_RD, 0x09,0,0x29,0x2a,UUID16_FORMAT},//manufacture
  •     {TYPE_CHAR,0x0a,ATT_CHAR_PROP_RD, 0x0b,0,0x26,0x2a,UUID16_FORMAT},//firmware version
  •     {TYPE_CHAR,0x0c,ATT_CHAR_PROP_RD, 0x0d,0,0x50,0x2a,UUID16_FORMAT},//PnPID
  •     {TYPE_CHAR,0x0e,ATT_CHAR_PROP_RD, 0x0f,0,0x28,0x2a,UUID16_FORMAT},//sw version   
  •    
  •     // ======  HID =====
  •     //    {TYPE_INC, 0x1a,},//include, hard code!!!
  •     {TYPE_INC, 0x001a,0x2b,0x00, 0x2d,0x00, 0x0a,0xa0}, //hard code uuid-0aa0, I just share the memory
  •     {TYPE_CHAR,0x1B,ATT_CHAR_PROP_RD|ATT_CHAR_PROP_W_NORSP,0x1c,0, 0x4e,0x2a,UUID16_FORMAT},//protocol mode
  •     {TYPE_CHAR,0x1d,ATT_CHAR_PROP_W|ATT_CHAR_PROP_RD|ATT_CHAR_PROP_NTF, 0x1e,0,0x4d,0x2a,UUID16_FORMAT},//report
  •     {TYPE_CFG, 0x1f,ATT_CHAR_PROP_RD|ATT_CHAR_PROP_W},//cfg
  •     {TYPE_RpRef,0x20,ATT_CHAR_PROP_RD},//Report Reference
  •    
  •     {TYPE_CHAR,0x21,ATT_CHAR_PROP_RD, 0x22,0,0x4b,0x2a,UUID16_FORMAT},//report map
  •     {TYPE_xRpRef,0x23,ATT_CHAR_PROP_RD},//External Report Reference
  •    
  •     {TYPE_CHAR,0x24,ATT_CHAR_PROP_W|ATT_CHAR_PROP_RD|ATT_CHAR_PROP_NTF,0x25,0,0x33,0x2a,UUID16_FORMAT},//boot mouse input report
  •     {TYPE_CFG, 0x26,ATT_CHAR_PROP_RD|ATT_CHAR_PROP_W},//cfg
  •    
  •     {TYPE_CHAR,0x27,ATT_CHAR_PROP_RD,                      0x28,0,0x4a,0x2a,UUID16_FORMAT},//hid info
  •     {TYPE_CHAR,0x29,ATT_CHAR_PROP_W_NORSP,                 0x2a,0,0x4c,0x2a,UUID16_FORMAT},//hid control point
  •     // ======  0xa00a  ======    include uuid
  •     {TYPE_CHAR,0x2c,ATT_CHAR_PROP_RD, 0x2d,0,0x0b,0x0a,UUID16_FORMAT},//
  •    
  •     // ======  battery service  ======   
  •     {TYPE_CHAR,0x2f,ATT_CHAR_PROP_RD|ATT_CHAR_PROP_NTF,    0x30,0,0x19,0x29,UUID16_FORMAT},//battery level
  •     {TYPE_CFG, 0x31,ATT_CHAR_PROP_RD|ATT_CHAR_PROP_W},//cfg
  •    
  •     // ======  scan prameter service  ======        
  •     {TYPE_CHAR,0x33,ATT_CHAR_PROP_W_NORSP,    0x34,0,0x4f,0x2a,UUID16_FORMAT},//Scan Interval Window
  •     {TYPE_CHAR,0x35,ATT_CHAR_PROP_NTF,    0x36,0,0x31,0x2a,UUID16_FORMAT},//Scan Refresh
  •     {TYPE_CFG, 0x37,ATT_CHAR_PROP_RD|ATT_CHAR_PROP_W},//cfg
  • };
  • 复制代码
    HID的规范协议数据结构
    const u8 Hid_map[]= {
  •     //first Id
  •     0x05, 0x01, //standard keyboard    Usage Page(global)Generic Desktop Controls
  •     0x09, 0x06, //Usage (local) Keyboard
  •     0xA1, 0x01, //collection((Application)
  •        
  •     0x85, 0x01, //report ID
  •     0x05, 0x07, //Keyboard/Keypad
  •     0x19, 0xE0, //Usage Minimum
  •     0x29, 0xE7, //Usage Maximum
  •     0x15, 0,      //Logical Minimum
  •     0x25, 1,      //Logical Maximum
  •    
  •     0x75, 1,       //Report Size(1 bit)
  •     0x95, 8,       //Report Count(8)
  •     0x81, 2,       //input(2) - variable absolute data
  •    
  •     0x95, 1,       //Report Count(1)
  •     0x75, 0x08, //Report Size(8 bit)
  •     0x81, 3,      //input(3) - variable absolute constant, for OEM data usage
  •    
  •     0x95, 5,    //Report Count(5)
  •     0x75, 1,    //Report Size(1 bit)
  •     5, 8,          //Usage Page(global)LED
  •     0x19, 1,    //Usage Minimum
  •     0x29, 5,    //Usage Maximum       
  •     0x91, 2,    //output(2) - variable absolute data
  •    
  •     0x95, 1,    //Report Count(1)
  •     0x75, 3,    //Report Size(3 bit)
  •     0x91, 3,    //output(3) - variable absolute constant
  •    
  •     0x95, 6,     //Report Count(6)
  •     0x75, 8,     //Report Size(8 bit)
  •     0x15, 0,     //Logical Minimum
  •     0x25, 0xff, //Logical Maximum
  •     5, 7,           //Keyboard/Keypad
  •     0x19, 0,     //Usage Minimum
  •     0x29, 0xff, //Usage Maximum
  •     0x81, 0,    //input(0) - array absolute data
  •     0xc0,        //END collection
  •    
  •     // Second ID
  •     0x05, 0x0c, //Consumer
  •     0x09, 0x01, //Consumer Control
  •     0xA1, 0x01, //collection
  •     0x85, 0x02,//report ID
  •    
  •     0x15, 0x00,//Logical Minimum
  •     0x25, 0x01,//Logical Maximum
  •     0x75, 0x01,//Report Size(1 bit)
  •     0x95, 0x1e,//Report Count(30)
  •    
  •     //first item start
  •     0x09, 0x30, //power   
  •     0x09, 0xb0, //play
  •     0x09, 0xb1, //pause
  •     0x09, 0xb2, //record
  •     0x09, 0xb3, //FF
  •     0x09, 0xb4, //FB   
  •     0x09, 0xb5, //next     
  •     0x09, 0xb6, //pre
  •    
  •     0x09, 0xb8, //reject
  •     0x09, 0xb9, //random play   
  •     0x09, 0xe2, //Mute   
  •     0x09, 0xe9, //V+
  •     0x09, 0xea, //V-
  •     0x09, 0x95, //help   
  •     0x0a, 0x24, 0x02, //AC back
  •     0x0a, 0x25, 0x02, //AC forward
  •    
  •     0x0a, 0x26, 0x02, //AC stop
  •     0x0a, 0x27, 0x02, //AC refresh
  •     0x0a, 0x21, 0x02, //AC search
  •     0x0a, 0x2a, 0x02, //AC bookmarks
  •     0x0a, 0x23, 0x02, //AC Home
  •     0x0a, 0x8a, 0x01, //AL email reader   
  •     0x0a, 0x83, 0x01, //AL consumer Contrl Configuration
  •     0x0a, 0x94, 0x01, //AL browser
  •    
  •     0x0a, 0x92, 0x01, //AL calculater
  •     0x0a, 0x09, 0x02, //AC property
  •     0x0a, 0x7f, 0x02, //AC view clock
  •     0x0a, 0x33, 0x02, //scroll up
  •     0x0a, 0x34, 0x02, //scroll down
  •     0x0a, 0x1F, 0x02, //AC Find
  •    
  •     //end
  •     0x81, 0x02,  //input(2) - variable absolute data
  •     0x95, 0x01,  //Report Count(30)
  •     0x75, 0x02,  //Report Size(2 bit)
  •     0x81, 0x03,  //input(3) - variable absolute constant
  •     0xc0,            //end collection   
  • };
  • 复制代码
         手机拍照功能控制
    /***********************************************************************
  • **function: NotifyApplePhoto
  • **@brief    This function is apple photo hid photo capture, hard code
  • **
  • **@param    None.
  • **
  • **@return
  • ************************************************************************/
  • u8 NotifyApplePhoto(void)//apple photo hid photo capture, hard code
  • {
  •     u8 Keyarray[5] = {2,0,8,0,0}; //VolUp,hard code
  •     sconn_notifydata(Keyarray,5);
  •     Keyarray[2] = 0;
  •     sconn_notifydata(Keyarray,5);
  •     return 1;
  • }
  • /*******************************************************************
  • **function: NotifyKey
  • **@brief    This function is hid standard keyboard key, hardcode
  • **
  • **@param    KeyIdx
  • **
  • **@return                None.
  • ********************************************************************/
  • u8 NotifyKey(u8 KeyIdx)//hid standard keyboard key, hardcode
  • {
  •     u8 Keyarray[9] = {1,0,0,0,0,0,0,0,0};//0xa1
  •     Keyarray[3] = KeyIdx;
  •     sconn_notifydata(Keyarray,9);
  •     Keyarray[3] = 0;
  •     sconn_notifydata(Keyarray,9);
  •     return 1;
  • }
  • /***************************************************************
  • **function: gatt_user_send_notify_data_callback
  • **@brief    This callback function can be used to actively send data to the Bluetooth module
  • **          The protocol stack will callback (asynchronously) this function when the system allows it. It must not block! !!
  • **@param    None.
  • **
  • **@return   None.
  • ****************************************************************/
  • void gatt_user_send_notify_data_callback(void)
  • {
  •         if(key_shutter==TRUE)
  •         {
  •               key_shutter=FALSE;
  •               NotifyKey(0x28);
  •         NotifyApplePhoto();       
  •         }
  • }
  • 复制代码
        根据原理图,我们可以知道K4连接到MCU的GPIOB11。
    原理图.png
          工程编译完成后下载,自动重启
    编译下载ok.png
          然后打开手机蓝牙,搜索到“MindMotion-Shutter”,并建立连接
    连接蓝牙.jpg
          接着打开手机的相机应用,放在距离开发板10米以内的地方,此时再通过按下开发板中的K4键,即能完成拍照功能。
    照片.jpg

           此次分享就到这里,后续再扩展其它功能啦,感谢各位网友来访,谢谢上海灵动微电子的赞助,面包社区提供的平台。
    DS_MM32W3xxB_nc_V1.10_SC.pdf (1.28 MB, 下载次数: 3)