/************************************************************************************************* **Filename: **Version : **Author : **Date : **Description: ** *************************************************************************************************/ #include "mcu_bsp.h" #include "lsm6d.h" #include "lis2dh.h" #include "ota.h" #include "gpadc.h" #include "delay.h" #include "cjson.h" #include #include #include #include "crc16.h" #include "common.h" #include "wdt.h" #include "DebugLog.h" #include "softtimer.h" #include "app_timer.h" #include "SYD_ble_service_service.h" /*---------------------------------------------------------------*/ //变量定义 Tx_Buffer_t dtts_tx_buffer; // 存放发送给主机的数据 static struct gap_ble_addr dev_addr; static uint8_t work_led_count = 6; /* 设置配置数组 */ static uint8_t Device_Name_Array[Device_Name_Len]= {Device_Name}; /* this is for change the byte to char*/ static char hex[] = "0123456789ABCDEF"; /**< GATT属性列表头,传入到协议栈中进行初始化*/ static struct gap_att_report_handle *g_report; /* connection*/ uint8_t connect_flag=0; uint8_t Adv_State = 0; /* 延迟状态 */ static uint8_t latency_state = 0; /* SPP延时计数*/ static uint16_t spp_delay_cnt=0; uint8_t update_latency_mode=0; /* 设置启动发送功能,允许将数据notify到服务*/ uint8_t start_tx = 0; uint8_t syd_nosleep_control=0; int batteryPercentage =0; /**< 剩余电量百分比*/ /* adv data array*/ uint8_t ADV_DATA[] = { 0x02, /**< length*/ 0x01, /**< AD Type: Flags*/ 0x05, /**< LE Limited Discoverable Mode & BR/EDR Not Supported*/ 0X0B, /**< length*/ 0XFF, /**< AD Type: MANUFACTURER SPECIFIC DATA*/ 0X4C, /**< Company Identifier (0x00)*/ 0X76, /**< Company Identifier (0x00)*/ 0X42, /**< Company Identifier (0x00)*/ 0X75, /**< Company Identifier (0x42)*/ 0X00, /**< for mac*/ 0X00, /**< for mac*/ 0X00, /**< for mac*/ 0X00, /**< for mac*/ 0X00, /**< for mac*/ 0X00, /**< for mac*/ Device_Name_Len+1, /**< length*/ 0x09, /**< AD Type: Complete local name*/ Device_Name /**< Device name*/ }; /* scan data array*/ uint8_t SCAN_DATA[]= { 0X05, /**< length*/ 0X03, /**< AD Type: MANUFACTURER SPECIFIC DATA*/ 0X16, /**< Company Identifier (0x00)*/ 0X18, /**< Company Identifier (0x00)*/ 0XE0, 0XFF, 0X04, 0X16, 0X04, 0X2A, 0X01, /**< 0X01 踏频,0x02 码表,0x03 灯,04电池,05电显*/ }; /*---------------------------------------------------------------*/ //外部变量调用声明 extern PAS_SENSOR_t PAS; static void ble_init(); void ble_evt_callback(struct gap_ble_evt *p_evt); static void ble_gatt_write(struct gap_att_write_evt evt); static void ble_gatt_read(struct gap_att_read_evt evt); static void setup_adv_data(); uint8_t str_cmp(uint8_t *p1,uint8_t *p2,uint8_t len); void nvic_priority(void); void rtc_event_handler(void); void ota_manage(void); void BLSetConnectionUpdate(uint8_t target); static void timer_event_handler(); static void timer_1_callback(void); uint8_t BLE_SendRPPData(uint8_t *buf, uint8_t len); void pack_timer_event(); static void send_to_master(void); void Connection_latency(void); void cal_battery_value(uint16_t adc); uint8_t BLE_NotifyBatteryLevel(); uint8_t get_battery_value(); static void rf_stop(void); static void PowerDown(void); void gpio_init(void); void Charge_State_Judge(void); void LED_State_Indicator(void); void syd_nosleep(bool en,SYD_NOSLEEP_CONTROL condit); void JsProtocol_Report(int16_t MasterValue,int16_t SlaveValue,int16_t FunCodeValue, char* Key1,int16_t Value1,char* Key2,int16_t Value2); /*---------------------------------------------------------------*/ //主函数 int main() { __disable_irq(); /* 蓝牙初始化,系统主时钟初始化64M,32K时钟初始化为LPO */ ble_init(); /*把串口优先级设置到最高*/ nvic_priority(); /* 根据需要重新设置系统主时钟为64M并校准*/ MCUClockSwitch(SYSTEM_CLOCK_64M_RCOSC); RCOSCCalibration(); #ifdef USER_32K_CLOCK_RCOSC ClockSwitch(SYSTEM_32K_CLOCK_RCOSC); GAPBBDelayMS(500); //内部晶振首次校准的时候必须使用等待硬件复位完成 LPOCalibration(); //这是内部RC32k晶振的校准函数,经过该函数后定时器能够得到一个比较准确的值 #else ClockSwitch(SYSTEM_32K_CLOCK_XOSC); #endif #ifdef _SYD_RTT_DEBUG_ DebugLogInit(); /**< 调试日志*/ #endif UartEn(false); #if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_))) dbg_printf("SYD8811 GPIO test demo %s:%s\r\n", __DATE__ , __TIME__); #endif gpio_init(); /* software:timr0 blelib:timer3 */ SYD_Timer_Init(EVT_NUM, syd_sysTimer); Timer_Evt_List(); Timer_Evt_Start(EVT_1S_WORK); Timer_Evt_Start(EVT_1S_OTA); Timer_Evt_Start(EVT_300MS_PACK); /*5 seconds wdt*/ #ifdef _WDT_ wdt_enable(128*5); #endif BSP_MCU_Config(); Lsm6dso_Init(); Timer2_Enable(); Lis2dh_Init(); StartAdv(); //开始广播 Adv_State = 1; __enable_irq(); while(1) { ble_sched_execute(); /*协议栈任务轮训*/ timer_event_handler(); Charge_State_Judge(); if(start_tx & 0x01) { send_to_master(); } if(!(syd_nosleep_control & SYD_NOSLEEP_SW)) { SystemSleep(); //浅度休眠,定时器中断唤醒 } if(PAS.sleepState == 1) { PowerDown(); } } } /*---------------------------------------------------------------*/ //充电状态检测 //高电平:非充电状态/充满 //低电平:正在充电 //注意: IO口输入反向 void Charge_State_Judge(void) { if((GPIO_Pin_Read(U32BIT(CHARGE_STATE_PIN)) & U32BIT(CHARGE_STATE_PIN))!= 0) { PAS.chargeState = 1; } else { PAS.chargeState = 0; } } /********************************************************************* * Function : gpio_init * Param in : none * Param out: none * Return : none * Describe : 初始化IO参数 */ void gpio_init(void) { uint8_t i; uint32_t io_input=0,io_pull=0,io_output=0,io_outlow=0,io_invert=0; #ifdef USER_32K_CLOCK_RCOSC /* 如果使用内部时钟,时钟引脚上拉*/ PIN_CONFIG->PAD_INPUT_PULL_UP[0] = 0xff; //pull up #else /* 如果使用外部时钟,时钟引脚下拉*/ PIN_CONFIG->PAD_INPUT_PULL_UP[0] = 0xfc; //pull up gpio 0 1 32K xosc #endif /* 配置其他GPIO的引脚,这里需要注意IO和PAD的关系*/ PIN_CONFIG->PAD_INPUT_PULL_UP[1] = 0xff; //pull up PIN_CONFIG->PAD_INPUT_PULL_UP[2] = 0xff; //pull up PIN_CONFIG->PAD_INPUT_PULL_UP[3] = 0xc7; //pull up pin29/pin28 SWD pen21/reset PIN_CONFIG->PAD_INPUT_PULL_UP[4] = 0xff; //pull up for(i=0;i<32;i++) { switch(i) { /* 外部时钟I0配置*/ #ifndef USER_32K_CLOCK_RCOSC case GPIO_0: case GPIO_1: break; #endif case PEN_PIN: io_output |=U32BIT(i); io_outlow &=~U32BIT(i); //输出高 break; case LIS2D_INT2: io_input |=U32BIT(i); io_pull |=U32BIT(i); io_invert |=U32BIT(i); break; /**< RESET IO*/ case GPIO_21: io_input |=U32BIT(i); io_pull |=U32BIT(i); break; /**< 默认上拉输入*/ default: io_input |=U32BIT(i); io_pull |=U32BIT(i); break; } } /* 设置GPIO21为IO口模式,而不是复位管脚*/ BBRFWrite(0x7f, 0x00); BBRFWrite(0x1a, 0x40); /* 默认输出IO配置*/ GPIO_Set_Output(io_output); PIN_Pullup_Disable(T_QFN_48, io_output); /* 默认输出高电平IO配置*/ GPIO_Pin_Set(io_output & (~io_outlow)); /* 默认输出低电平IO配置*/ GPIO_Pin_Clear(io_outlow); /* 默认IO设置是上拉输入*/ GPIO_Set_Input(io_input,io_invert); PIN_Pullup_Enable(T_QFN_48,io_pull); } /********************************************************************* * Function : PowerDown * Param in : none * Param out: none * Return : none * Describe : PowerDown */ static void PowerDown(void) { struct gap_wakeup_config pw_cfg; __disable_irq(); #ifdef _WDT_ wdt_disable(); #endif LED_ON(); delay_ms(300); LED_OFF(); Lsm6dso_Disable(); PEN_DISABLE(); pw_cfg.wakeup_type = POWERDOWN_WAKEUP; pw_cfg.wdt_wakeup_en = (bool)false; pw_cfg.rtc_wakeup_en = (bool)false; pw_cfg.timer_wakeup_en = (bool)false; pw_cfg.gpi_wakeup_en = (bool)true; if(PAS.transpModes == 1) { pw_cfg.gpi_wakeup_cfg = U32BIT(CHARGE_STATE_PIN); //中断唤醒pin } else { pw_cfg.gpi_wakeup_cfg = U32BIT(LIS2D_INT2); //中断唤醒pin } WakeupConfig(&pw_cfg); SystemPowerDown(); delay_ms(5); __enable_irq(); } /********************************************************************* * Function : work_timer_event * Param in : none * Param out: none * Return : none * Describe : work_timer_event */ static void work_timer_event(void) { /*****************判断是否进入POWERDOWN状态***********************/ if(connect_flag == 1) { if(PAS.RPM == 0) { PAS.sleepCnt++; if((PAS.sleepCnt >= WORK_SLEEP_TIME)&&(PAS.sleepFlag==0)&&(ota_state == 0)) { PAS.sleepCnt = 0; PAS.sleepFlag = 1; DisConnect(); //不要重复断开连接,否则软件定时器会死机 } } else { PAS.sleepCnt=0; } } else { Timer2_Disable(); dtts_tx_buffer.header = dtts_tx_buffer.tail; if((GPIO_Pin_Read(U32BIT(LIS2D_INT2)) & U32BIT(LIS2D_INT2))!= 0) { PAS.sleepCnt = 0; } else { PAS.sleepCnt++; } if((PAS.sleepCnt >= WORK_SLEEP_TIME)&&(ota_state == 0)) { PAS.sleepFlag = 1; //准备休眠 关广播 } if((PAS.sleepFlag == 1)&&(Adv_State==0)) { PAS.sleepState = 1; } } } /********************************************************************* * Function : LED_State_Indicator * Param in : none * Param out: none * Return : none * Describe : get LED_State_Indicator value */ void LED_State_Indicator(void) { /*****************工作状态指示灯***********************/ if(PAS.chargeState == 1) { LED_ON(); work_led_count = 0; } else { if(work_led_count > 0) { work_led_count--; LED_TURN(); if(work_led_count==0) { LED_OFF(); } } else { LED_OFF(); } } } /********************************************************************* * Function : get_battery_value * Param in : none * Param out: none * Return : none * Describe : get battery value */ uint8_t get_battery_value() { GPADC_channel_sel(ADCGP_CH); GPADC_start(cal_battery_value); syd_nosleep((bool)true,SYD_NOSLEEP_ADC); if(connect_flag) { BLE_NotifyBatteryLevel(); } return 1; } /********************************************************************* * Function : 计算电池的值 * Param in : none * Param out: none * Return : none * Describe : calculate the battery value */ void cal_battery_value(uint16_t adc) { static uint8_t count,batteryPercenttemp[2]; #if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_))) dbg_printf("battery adc:%04x ",adc); #endif if(0xffff != adc) { float batteryVoltage=0.0; batteryVoltage=(float)adc*3.6/1024; /* 转换为电池电压*/ batteryVoltage = batteryVoltage*4/3+0.04; #if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_))) dbg_printf("pin_vol:%4.3f ",batteryVoltage); #endif batteryPercentage = (batteryVoltage*1000-3000)/11.5+0.5; if(batteryPercentage<0)batteryPercentage=0; if(batteryPercentage>100)batteryPercentage=100; // lvbu_pas_sensor.batt_level=batteryPercentage; count++; if(count>=2)count=0; batteryPercenttemp[count]=batteryPercentage; if((batteryPercenttemp[0] == batteryPercenttemp[1])||(PAS.batt_level == 0)) { PAS.batt_level = batteryPercentage; } #ifdef BATTERY_low_PROTECT if(batteryVoltage<3.0)Battery_low=1; else Battery_low=0; #endif #if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_))) dbg_printf("bat_vol:%4.3f level:%d\r\n",batteryVoltage,batteryPercentage); #endif } else { #if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_))) dbg_printf("battery adc Err \r\n"); #endif } syd_nosleep((bool)false,SYD_NOSLEEP_ADC); } /********************************************************************* * Function : syd_nosleep * Param in : none * Param out: none * Return : none * Describe : don't into sleep when read adc */ void syd_nosleep(bool en,SYD_NOSLEEP_CONTROL condit) { if(en) { syd_nosleep_control |=SYD_NOSLEEP_SW | condit; } else { syd_nosleep_control &=~condit; if(!(syd_nosleep_control & 0xFFFE)) syd_nosleep_control &=~SYD_NOSLEEP_SW; } } /********************************************************************* * Function : BLE_NotifyBatteryLevel * Param in : none * Param out: none * Return : none * Describe : notify the battery level */ uint8_t BLE_NotifyBatteryLevel() { struct gap_att_report report; report.primary =BLE_DTTS; report.uuid = BLE_BATTERY_LEVEL_UUID; report.hdl = BLE_BATTERY_LEVEL_VALUE_HANDLE; report.value = BLE_GATT_NOTIFICATION; return GATTDataSend(BLE_GATT_NOTIFICATION, &report, 1, &PAS.batt_level); } /********************************************************************* * Function : ble_init * Param in : none * Param out: none * Return : none * Describe : BLE初始化 */ static void ble_init() { struct gap_evt_callback evt; struct smp_pairing_req sec_params; struct gap_wakeup_config pw_cfg; BleInit(); SetWinWideMinusCnt(1); GetGATTReportHandle(&g_report); /* security parameters */ sec_params.io = IO_NO_INPUT_OUTPUT; sec_params.oob = OOB_AUTH_NOT_PRESENT; sec_params.flags = AUTHREQ_BONDING; sec_params.mitm = 0; sec_params.max_enc_sz = 16; sec_params.init_key = 0; sec_params.rsp_key = (SMP_KEY_MASTER_IDEN |SMP_KEY_ADDR_INFO); SetSecParams(&sec_params); evt.evt_mask=(GAP_EVT_CONNECTION_SLEEP|GAP_EVT_CONNECTION_INTERVAL); evt.p_callback=&ble_evt_callback; SetEvtCallback(&evt); /* Bond Manager (MAX:10) */ SetBondManagerIndex(0x00); setup_adv_data(); /* 当POWERDOWN_WAKEUP时, PW_CTRL->DSLP_LPO_EN = true,这些中断源才能唤醒并复位运行, 如果是false就只有pin能唤醒并复位运行 */ pw_cfg.wakeup_type = SLEEP_WAKEUP; pw_cfg.wdt_wakeup_en = (bool)false; pw_cfg.rtc_wakeup_en = (bool)false; pw_cfg.timer_wakeup_en = (bool)true; pw_cfg.gpi_wakeup_en = (bool)false; pw_cfg.gpi_wakeup_cfg = U32BIT(LIS2D_INT2); //中断唤醒pin WakeupConfig(&pw_cfg); } /********************************************************************* * Function : ble_evt_callback * Param in : none * Param out: none * Return : none * Describe : handle the ble event */ void ble_evt_callback(struct gap_ble_evt *p_evt) { if(p_evt->evt_code == GAP_EVT_ATT_WRITE) { ble_gatt_write(p_evt->evt.att_write_evt); } else if(p_evt->evt_code == GAP_EVT_ATT_READ) { ble_gatt_read(p_evt->evt.att_read_evt); } else if(p_evt->evt_code == GAP_EVT_CONNECTED) { connect_flag = 1; PAS.sleepCnt = 0; PAS.sleepFlag = 0; update_latency_mode = 0; Timer_Evt_Start(EVT_2S); //修改连接参数 Timer2_Enable(); #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGHEXDUMP("Connected addr:",p_evt->evt.bond_dev_evt.addr,sizeof(p_evt->evt.bond_dev_evt.addr)); #endif #ifdef _OTA_ ota_variable_clear(true); #endif } else if(p_evt->evt_code == GAP_EVT_DISCONNECTED) { #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF("Disconnected,reson:0x%02x\r\n", p_evt->evt.disconn_evt.reason); #endif start_tx &= ~0x01; //清零 connect_flag = 0; PAS.sleepCnt = 0; #ifdef _OTA_ if(Timer_Get_State(EVT_1S_OTA) && (ota_state!=3)) { Timer_Evt_Stop(EVT_1S_OTA); } #endif /* 成功断开连接之后功耗会加大10ua, 同时启动广播*/ if((PAS.sleepFlag == 0)||(PAS.chargeState == 1)) { setup_adv_data(); StartAdv(); Adv_State = 1; #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("restart adv @ disc!\r\n")); #endif } else { rf_stop(); Adv_State = 0; #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("stop adv @ disc!\r\n")); #endif } } else if(p_evt->evt_code == GAP_EVT_ATT_HANDLE_CONFIGURE) { #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("GAP_EVT_ATT_HANDLE_CONFIGURE= %2x,%2x,%2x\r\n"), p_evt->evt.att_handle_config_evt.uuid, p_evt->evt.att_handle_config_evt.hdl, p_evt->evt.att_handle_config_evt.value); #endif if(p_evt->evt.att_handle_config_evt.uuid == BLE_DTTS) { if(p_evt->evt.att_handle_config_evt.value == BLE_GATT_NOTIFICATION) { switch (p_evt->evt.att_handle_config_evt.hdl) { case (BLE_RPP_VALUE_HANDLE+1): { start_tx |= 0x01; dtts_tx_buffer.header = dtts_tx_buffer.tail; #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("RPP notify Enabled!\r\n")); #endif } break; case (BLE_CTL_VALUE_HANDLE+1): { start_tx |= 0x02; dtts_tx_buffer.header = dtts_tx_buffer.tail; #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("CTL notify Enabled!\r\n")); #endif } break; case (BLE_BATTERY_LEVEL_VALUE_HANDLE+1): { start_tx |= 0x03; dtts_tx_buffer.header = dtts_tx_buffer.tail; #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("BAT notify Enabled!\r\n")); #endif } break; default: break; } } else { switch (p_evt->evt.att_handle_config_evt.hdl) { case (BLE_RPP_VALUE_HANDLE+1): { start_tx &= ~0x01; /* 允许硬件自由控制32Mhz晶振,休眠的时候功耗很低*/ UartEn(false); #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("RPP notify Disabled!\r\n")); #endif } break; case (BLE_CTL_VALUE_HANDLE+1): { start_tx &= ~0x02; #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("CTL notify Disabled!\r\n")); #endif } break; case (BLE_BATTERY_LEVEL_VALUE_HANDLE+1): { start_tx &= ~0x03; #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("BAT notify Disabled!\r\n")); #endif } break; default: break; } } } } else if(p_evt->evt_code == GAP_EVT_L2CAP_UPDATE_RSP) { switch(p_evt->evt.l2cap_update_rsp_evt.result) { case CONN_PARAMS_ACCEPTED: #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("update rsp ACCEPTED\r\n")); { struct gap_link_params link_app; GetLinkParameters(&link_app); #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("interval:%x latency:%x\r\n",link_app.interval,link_app.latency); #endif } #endif break; case CONN_PARAMS_REJECTED: #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) //DBGPRINTF(("update rsp REJECTED\r\n")); #endif break; case CONN_PARAM_SMART_TIMEROUT: #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) //DBGPRINTF(("update rsp TIMEROUT\r\n")); #endif break; case CONN_PARAM_SMART_SUCCEED: #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) //DBGPRINTF(("update rsp SUCCEED\r\n")); #endif break; case CONN_PARAM_LATENCY_ENABLE: #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) // DBGPRINTF(("Enable latency\r\n")); #endif break; case CONN_PARAM_LATENCY_DISABLE: #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) // DBGPRINTF(("Disable latency\r\n")); #endif break; } } else if(p_evt->evt_code == GAP_EVT_CONN_UPDATE_COMP) { struct gap_link_params link; GetLinkParameters(&link); #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF("CONN_UPDATE_COMP: %d, %d, %d\r\n", link.interval, link.latency, link.svto); #endif } else if(p_evt->evt_code == GAP_EVT_ADV_END) { #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("GAP_EVT_ADV_END\r\n")); #endif if((PAS.sleepFlag == 0)||(PAS.chargeState == 1)) { StartAdv(); Adv_State = 1; } else { rf_stop(); Adv_State = 0; } #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("restart adv\r\n")); #endif } } /********************************************************************* * Function : * Param in : none * Param out: none * Return : none * Describe : */ static void rf_stop(void) { RFSleep(); } /********************************************************************* * Function : 发送指令 * Param in : none * Param out: none * Return : none * Describe : */ uint8_t BLE_SendCMDData(uint8_t *buf, uint8_t len) { struct gap_att_report report; report.primary = BLE_DTTS; report.uuid = BLE_CTL_UUID; report.hdl = BLE_CTL_VALUE_HANDLE; report.value = BLE_GATT_NOTIFICATION; return GATTDataSend(BLE_GATT_NOTIFICATION, &report, len, buf); } /********************************************************************* * Function : ble_gatt_write * Param in : none * Param out: none * Return : none * Describe : GATT属性写入处理 */ static void ble_gatt_write(struct gap_att_write_evt evt) { if(evt.uuid == BLE_SPP_UUID) { } else if(evt.uuid ==BLE_CTL_UUID) { #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGHEXDUMP("BLE_CTL_UUID:",evt.data, evt.sz); #endif if(evt.sz >= 2&& evt.data[0] == '@' && evt.data[evt.sz-1] == '#') { /* 测试指令 */ if((evt.sz == 6) && str_cmp(evt.data, (uint8_t *)"@TEST#", 6)) { #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("@OK#\r\n"); #endif } else if((evt.sz == 5) && str_cmp(evt.data, (uint8_t *)"@OFF#", 5)) { uint8_t data[6]="@OK#\r\n"; BLE_SendCMDData(data,6); PAS.transpModes = 1; //运输模式 PAS.sleepCnt = WORK_SLEEP_TIME; //运输模式,加快进入深度休眠模式 } else if((evt.sz == 5) && str_cmp(evt.data, (uint8_t *)"@CAL#", 5)) { PAS.adjustFlag = 1; #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF("PAS.adjustFlag = %d\r\n",PAS.adjustFlag); #endif } } else { #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("@ERROR cmd#\r\n"); #endif } } else if(evt.uuid== BLE_OTA_Read_Write_UUID) { #ifdef _OTA_ ota_cmd(evt.data, evt.sz); #endif } } /********************************************************************* * Function : ble_gatt_read * Param in : none * Param out: none * Return : none * Describe : GATT属性读取处理 */ static void ble_gatt_read(struct gap_att_read_evt evt) { /* 设备名称*/ if(evt.uuid == BLE_DEVICE_NAME_UUID) { uint8_t gatt_buf_sz = sizeof(Device_Name_Array); SetGATTReadRsp(gatt_buf_sz, Device_Name_Array); } /* 制造商名称*/ else if(evt.uuid == BLE_MANUFACTURER_NAME_STRING_UUID) { SetGATTReadRsp(Manufacturer_Size, (uint8_t *)Manufacturer_Name); } /* 产品型号*/ else if(evt.uuid == BLE_MODEL_NUMBER_STRING_UUID) { SetGATTReadRsp(Model_Size, (uint8_t *)Model_Number); } /* 产品串号*/ else if(evt.uuid == BLE_SERIAL_NUMBER_STRING_UUID) { SetGATTReadRsp(Serial_Size, (uint8_t *)Serial_Number); } /* 硬件版本号*/ else if(evt.uuid == BLE_HARDWARE_REVISION_STRING_UUID) { SetGATTReadRsp(Hardware_Size, (uint8_t *)Hardware_Vesion); } /* 软件版本号*/ else if(evt.uuid == BLE_SOFTWARE_REVISION_STRING_UUID) { SetGATTReadRsp(Software_Size, (uint8_t *)Software_Vesion); } /* 电池电量*/ else if(evt.uuid == BLE_BATTERY_LEVEL_UUID) { // SetGATTReadRsp(1, (uint8_t *) &AD_Value.PowerScale); } /* OTA*/ else if(evt.uuid == BLE_OTA_Read_Write_UUID) { #ifdef _OTA_ uint8_t sz=0; uint8_t rsp[sizeof(struct hci_evt)]= {0}; ota_rsp(rsp, &sz); SetGATTReadRsp(sz, rsp); #endif } } /********************************************************************* * Function : setup_adv_data * Param in : none * Param out: none * Return : none * Describe : 设置广播数据 */ static void setup_adv_data() { struct gap_adv_params adv_params; adv_params.type = ADV_IND; /**< advertising channel : 37 & 38 & 39*/ adv_params.channel = 0x07; /**< advertising interval : 1000ms (1600 * 0.625ms),这里需要注意的问题 就是设置的interval要是100的整数倍数,这样时间才会比较准确,默认1600*/ adv_params.interval = 80; adv_params.timeout = ADV_TIMEOUT; /**< timeout : 30s*/ /* 设置广播的参数*/ SetAdvParams(&adv_params); /* 获取蓝牙的地址 */ GetDevAddr(&dev_addr); ADV_DATA[9] = dev_addr.addr[5]; ADV_DATA[10] = dev_addr.addr[4]; ADV_DATA[11] = dev_addr.addr[3]; ADV_DATA[12] = dev_addr.addr[2]; ADV_DATA[13] = dev_addr.addr[1]; ADV_DATA[14] = dev_addr.addr[0]; /*the mac last 4 char to the adv name*/ ADV_DATA[25] = hex[(dev_addr.addr[1]>>4)&0X0F]; ADV_DATA[26] = hex[dev_addr.addr[1]&0X0F]; ADV_DATA[27] = hex[(dev_addr.addr[0]>>4)&0X0F]; ADV_DATA[28] = hex[dev_addr.addr[0]&0X0F]; Device_Name_Array[8] = ADV_DATA[25]; Device_Name_Array[9] = ADV_DATA[26]; Device_Name_Array[10]= ADV_DATA[27]; Device_Name_Array[11]= ADV_DATA[28]; /* set the adv data and scan data*/ SetAdvData(ADV_DATA, sizeof(ADV_DATA), SCAN_DATA, sizeof(SCAN_DATA)); *(uint8_t *)0x40020014 = 0x01; /*< 设置ADV_PITV为1,降低功耗*/ } /********************************************************************* * Function : nvic_priority * Param in : none * Param out: none * Return : none * Describe : config teh nvic priority */ void nvic_priority(void) { NVIC_SetPriority(LLC_IRQn, 2); NVIC_SetPriority(RTC_IRQn, 2); NVIC_SetPriority(SW_IRQn, 2); NVIC_SetPriority(I2C0_IRQn, 2); NVIC_SetPriority(I2C1_IRQn, 2); NVIC_SetPriority(UART0_IRQn, 2); NVIC_SetPriority(UART1_IRQn, 2); NVIC_SetPriority(TIMER0_IRQn, 3); NVIC_SetPriority(TIMER1_IRQn, 2); NVIC_SetPriority(TIMER2_IRQn, 2); NVIC_SetPriority(TIMER3_IRQn, 2); NVIC_SetPriority(GPIO_IRQn, 2); NVIC_SetPriority(HID_IRQn, 2); NVIC_SetPriority(SPIM_IRQn, 2); NVIC_SetPriority(CAP_IRQn, 0); NVIC_SetPriority(GPADC_IRQn, 2); NVIC_SetPriority(LLC2_IRQn, 2); NVIC_SetPriority(ISO7816_IRQn, 2); NVIC_SetPriority(IR_Tx_IRQn, 2); NVIC_SetPriority(TOUCH_IRQn, 2); NVIC_SetPriority(HPWM_IRQn, 2); NVIC_SetPriority(HTIMER_IRQn, 2); NVIC_SetPriority(IR_Rx_IRQn, 2); } /********************************************************************* * Function : RTC事件处理 * Param in : none * Param out: none * Return : none * Describe : rtc时钟定时事件处理 */ void rtc_event_handler(void) { /* 实时时钟处理*/ if(RTC_EVT) { #ifdef RTCEVT_185S if(RTC_EVT & RTCEVT_185S) { #ifdef USER_32K_CLOCK_RCOSC LPOCalibration(); #endif #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) DBGPRINTF(("RTCEVT_185S\r\n")); #endif RTC_EVT_Clr(RTCEVT_185S); } #endif } } /************************************************************************************************* * Function Name: * Description : 设置连接延迟 * Arguments : * Return Value : *************************************************************************************************/ void Connection_latency(void) { update_latency_mode++; if(update_latency_mode>=3) { latency_state=0; /* low energy connect setting*/ BLSetConnectionUpdate(1); Timer_Evt_Stop(EVT_2S); } } /********************************************************************* * Function : timer_event_handler * Param in : none * Param out: none * Return : none * Describe : 定时器事件处理 */ static void timer_event_handler() { /* 定时器事件处理*/ if(TIMER_EVT) { #ifdef EVT_1S_OTA if(TIMER_EVT&EVT_1S_OTA) { ota_manage(); /**< ota 过程管理 操作屏幕等*/ Timer_Evt_Clr(EVT_1S_OTA); } #endif #ifdef EVT_2S if(TIMER_EVT&EVT_2S) { Connection_latency(); /**< 连接参数相关设置*/ Timer_Evt_Clr(EVT_2S); } #endif #ifdef EVT_1S_WORK if(TIMER_EVT&EVT_1S_WORK) { work_timer_event(); Timer_Evt_Clr(EVT_1S_WORK); } #endif #ifdef EVT_300MS_PACK if(TIMER_EVT&EVT_300MS_PACK) { LED_State_Indicator(); #ifdef _WDT_ wdt_clear(); #endif Timer_Evt_Clr(EVT_300MS_PACK); } #endif #ifdef EVT_20S_BATTERY if(TIMER_EVT&EVT_20S_BATTERY) { Timer_Evt_Clr(EVT_20S_BATTERY); } #endif } } /********************************************************************* * Function : BLSetConnectionUpdate * Param in : uint8_t target * 0:ota * 1:low energy * Param out: none * Return : none * Describe : 更新连接参数 */ void BLSetConnectionUpdate(uint8_t target) { struct gap_smart_update_params smart_params; switch(target) { /* 0:ota */ case 0: /* connection parameters */ smart_params.updateitv_target=0x0010; /**< target connection interval (value * 1.25ms = 75 ms)*/ smart_params.updatesvto=0x00c8; /**< supervisory timeout (400 * 10 ms = 4s)*/ smart_params.updatelatency=0x0000; break; /* 1:low energy */ case 1: /* connection parameters */ smart_params.updateitv_target=16; /**< target connection interval (value * 1.25ms = 75 ms)*/ smart_params.updatesvto=400; /**< supervisory timeout (value * 10 ms = 4s)*/ smart_params.updatelatency=1; break; } smart_params.updatectrl=SMART_CONTROL_LATENCY | SMART_CONTROL_UPDATE; smart_params.updateadj_num=MAX_UPDATE_ADJ_NUM; gap_s_smart_update_latency(&smart_params); #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("smart_params interval:%x latency:%x svto:%x\r\n",smart_params.updateitv_target, smart_params.updatelatency,smart_params.updatesvto); #endif } /********************************************************************* * Function : ota_manage * Param in : none * Param out: none * Return : none * Describe : manage the ota operation */ void ota_manage(void) { #ifdef _OTA_ if(ota_state) { switch(ota_state) { case 1 : #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("start FwErase\r\n"); #endif CmdFwErase(); #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("OTA start\r\n"); #endif ota_state =2; ota_writecnt=0; break; case 2 : ota_writecnt++; if(ota_writecnt>0x20) { #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("OTA faile\r\n"); #endif Timer_Evt_Stop(EVT_1S_OTA); } break; case 3 : ota_state=0; Timer_Evt_Stop(EVT_1S_OTA); #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("OTA finish\r\n"); #endif delay_ms(1000); #if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) dbg_printf("Start Reset 1000s\r\n"); #endif SystemReset(); break; default : break; } } #endif } /************************************************************************************************* * Function Name: * Description : * Arguments : 将缓冲区数据发送到主机 * Return Value : *************************************************************************************************/ static void send_to_master(void) { uint32_t len, header, tail; header = dtts_tx_buffer.header; tail = dtts_tx_buffer.tail; /*有数据,处理数据*/ if(header != tail) { if(latency_state==0) { latency_state = 1; spp_delay_cnt = 0; timer_1_enable(32768/200, timer_1_callback); //5MS定时中断 } } else { return; } //caculate len if(header >= tail) { len = header - tail; } else { len = header + MAX_RX_LENGTH - tail; } /* len bigger then 20, send data immediately*/ if(len>=PDULENTH) { for(; len>=PDULENTH; len-=PDULENTH) { uint8_t send_data[PDULENTH], i; spp_delay_cnt = 0; //memcpy PDULENTH byte for(i=0; i= MAX_RX_LENGTH) { tail = 0; } } //send if(BLE_SendRPPData(send_data, PDULENTH)) { dtts_tx_buffer.tail = tail; } else { break; } } // if(len >= 1) // { // uint8_t send_data[PDULENTH], i; // // for(i=0; i< len; i++) // { // send_data[i] = dtts_tx_buffer.data[tail++]; // if(tail >= MAX_RX_LENGTH) // { // tail = 0; // } // } // //send // if(BLE_SendRPPData(send_data, len)) // { // dtts_tx_buffer.tail = tail; // } // } } else if(len >= 1) { if(spp_delay_cnt >= 3) { uint8_t send_data[PDULENTH],i; //memcpy len byte for(i=0; i= MAX_RX_LENGTH) { tail = 0; } } //send if(BLE_SendRPPData(send_data, len)) { dtts_tx_buffer.tail = tail; } spp_delay_cnt = 0; } } } /************************************************************************************************* * Function Name: * Description : * Arguments : 将串口数据发送到BLE服务 * Return Value : *************************************************************************************************/ uint8_t BLE_SendRPPData(uint8_t *buf, uint8_t len) { if(start_tx & 0x01) { struct gap_att_report report; report.primary = BLE_DTTS; report.uuid = BLE_RPP_UUID; report.hdl = BLE_RPP_VALUE_HANDLE; report.value = BLE_GATT_NOTIFICATION; return GATTDataSend(BLE_GATT_NOTIFICATION, &report, len, buf); } return 0; } /************************************************************************************************* * Function Name: * Description : * Arguments : 定时器1的回调处理 * Return Value : *************************************************************************************************/ static void timer_1_callback(void) { spp_delay_cnt++; /* 经过三次回调,spp缓冲区无数据后停止定时器*/ if((dtts_tx_buffer.header == dtts_tx_buffer.tail) && (spp_delay_cnt > 3)) { latency_state = 0; timer_1_disable(); } } /************************************************************************************************* * Function Name: * Description : json 数据上报 * Arguments : * Return Value : *************************************************************************************************/ void JsProtocol_Report(int16_t MasterValue,int16_t SlaveValue,int16_t FunCodeValue, char* Key1,int16_t Value1,char* Key2,int16_t Value2) { int i=0; cJSON* JsFrameTx_Report=NULL; //new一个响应的的json主体 cJSON* JsTx_Data=NULL; //new一个响应的的json主体 int16_t TxJs_Len; //保存json包长度 char* Tx_Pack; char* pReport_Dfu; int16_t pStr_Response_Index=0; int16_t CRC16_Data; /* 响应json包*/ JsFrameTx_Report=cJSON_CreateObject(); //!!!申请内存,创建帧json cJSON_AddNumberToObject(JsFrameTx_Report,"M",MasterValue); //pack:主机 cJSON_AddNumberToObject(JsFrameTx_Report,"S",SlaveValue); //pack:从机 cJSON_AddNumberToObject(JsFrameTx_Report,"F",FunCodeValue); //pack:功能码 JsTx_Data=cJSON_CreateObject(); //!!!申请内存,创建数据json cJSON_AddItemToObject(JsFrameTx_Report, "D",JsTx_Data); //pack:数据数组 cJSON_AddNumberToObject(JsTx_Data,Key1,Value1); //pack:数据 cJSON_AddNumberToObject(JsTx_Data,Key2,Value2); //pack:数据 /* change json to char */ Tx_Pack=cJSON_Print(JsFrameTx_Report); //!!!申请内存(json转char) cJSON_Minify(Tx_Pack); //瘦身 TxJs_Len=stringLength(Tx_Pack); //计算json长度 /* DFU pack */ pReport_Dfu=(char*)malloc(TxJs_Len*sizeof(char)+5); //!!!申请内存pStr1 pReport_Dfu[pStr_Response_Index++]=0x7f; pReport_Dfu[pStr_Response_Index++]=LSB_16(TxJs_Len); //pack:json长度低 pReport_Dfu[pStr_Response_Index++]=MSB_16(TxJs_Len); //pack:json长度高 memcpy(&pReport_Dfu[pStr_Response_Index],Tx_Pack,TxJs_Len); pStr_Response_Index+=TxJs_Len; CRC16_Data = crc16_ccitt( (uint8_t*)pReport_Dfu, pStr_Response_Index ); pReport_Dfu[pStr_Response_Index++] = LSB_16(CRC16_Data); pReport_Dfu[pStr_Response_Index++] = MSB_16(CRC16_Data); for(i=0; i= MAX_RX_LENGTH) { dtts_tx_buffer.header = 0; } } free(pReport_Dfu); //销毁内存!!! cJSON_free(Tx_Pack); //销毁链表!!! cJSON_Delete(JsFrameTx_Report); //销毁内存!!! } /************************************************************************************************* * Function Name: * Description : * Arguments : 打包数据并发送事件 * Return Value : *************************************************************************************************/ void pack_timer_event() { if(start_tx & 0x01) { /* 打包数据到缓冲区 */ JsProtocol_Report(3,0,4,"41",PAS.RPM,"50",PAS.batt_level); } } /*---------------------------------------------------------------*/