本次体验的功能比较简单,将开发板上电,然后打开手机蓝牙,搜索并连接上“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);
- //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"},
- };
控制模块系统时钟的选择是在启动时进行,复位时内部48MHz的振荡器被选为默认的CPU时钟,随后可以选择外部的16MHz时钟;当检测到外部时钟失效时,它将被隔离,系统将自动地切换到内部的振荡器,如果使能了中断,软件可以接收到相应的中断。同样,在需要时可以采取对PLL时钟完全的中断管理(如当一个间接使用的外部振荡器失效时)。多个预分频器用于配置AHB的频率、高速APB(APB2和APB1)区域,AHB和高速APB的最高频率是96MHz。时钟树如下图所示:
蓝牙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
- };
- 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();
- }
- }
工程编译完成后下载,自动重启
然后打开手机蓝牙,搜索到“MindMotion-Shutter”,并建立连接
接着打开手机的相机应用,放在距离开发板10米以内的地方,此时再通过按下开发板中的K4键,即能完成拍照功能。
此次分享就到这里,后续再扩展其它功能啦,感谢各位网友来访,谢谢上海灵动微电子的赞助,面包社区提供的平台。