sylar^z

  • 2019-08-17
  • 发表了主题帖: 基于F103与X-NUCLEO-IKS01A3之高低温度报警功能

    本帖最后由 sylar^z 于 2019-8-17 22:07 编辑     本次高低温度报警设计基于F103核心板与X-NUCLEO-IKS01A3传感器开发板。唤醒功能通过X-NUCLEO-IKS01A3上的STTS751传感器来实现。     STTS751是一款低压数字温度传感器。供电电压2.25V-3.6V,遵循SMBus 2.0通讯协议,可以通过标准I2C进行通讯。STTS751带高温限值、低温限值及高温极限值报警。因原理相同,本次测试中只使用了高温限值报警及低温限值报警功能。     在之前移植完驱动的程序(参看《 基于STM8S-DISCOVERY的X-NUCLEO-IKS01A3传感器驱动移植》)基础上进行功能添加。        首先对之前的程序作了一些改动,使能了STTS751传感器,并设置了检测STTS751的INT的中断的引脚PB7。接着就是添加报警功能。在完成对STTS751的初始化之后,设置STTS751的高低温限值来启用报警功能,并配置相应的参数及中断输出。然后是检测唤醒中断及事件处理(在OLED屏显示高温报警或低温报警)。        X-NUCLEO-IKS01A3上的STTS751_INT_PIN 1.设置STTS751的输出频率 2.设置高温限值报警、低温限值参数 因为1℃在高8为的bit0,所以设置报警的温度需要乘以256。读取显示温度时则需要除以256来得到真实温度。 3.设置唤醒中断通过INT1输出     INT pin同时绑定高温限值报警、低温限值报警及高温极限值报警使用。当检测到中断后,通过读取对应的事件状态寄存器来确定事件源。     中断使能标志位为MASK1。   相关代码:     //使能STTS751温度报警功能   if (EnvFuncDrv[FunctionIndex[ENV_TEMPERATURE]]->SetOutputDataRate(&stts751_obj_0, 4.0f) != BSP_ERROR_NONE)   {     return BSP_ERROR_COMPONENT_FAILURE;   }   if (STTS751_TEMP_SetLowTemperatureThreshold(&stts751_obj_0, LOW_TEMPERATURE_THRESHOLD) != BSP_ERROR_NONE)   {     return BSP_ERROR_COMPONENT_FAILURE;   }   if (STTS751_TEMP_SetHighTemperatureThreshold(&stts751_obj_0, HIGH_TEMPERATURE_THRESHOLD) != BSP_ERROR_NONE)   {     return BSP_ERROR_COMPONENT_FAILURE;   }   if (STTS751_TEMP_SetEventPin(&stts751_obj_0, 1U) != BSP_ERROR_NONE)   {     return BSP_ERROR_COMPONENT_FAILURE;   }   if (STTS751_TEMP_GetTemperatureLimitStatus(&stts751_obj_0, &HighLimit, &LowLimit, &ThermLimit) != BSP_ERROR_NONE)   {     ret = BSP_ERROR_COMPONENT_FAILURE;   }   4.事件确认及处理     检测STATUS寄存器中的THIGH、TLOW与THRM标志位,为1,则表示检测到有报警。执行报警处理,在OLED屏显示是高温报警还是低温报警。   每次报警产生后    INT引脚变低电平。在通过SMBus/I2C通讯产生ARA后变回的高电平。这个机制比较适合做LED灯等的闪烁提示。       相关代码: 程序中温度的采集周期为250ms,因此报警时做了一个200ms显示,50ms不显示的闪烁提示功能。     if (STTS751_TEMP_Get_DRDY_Status(&stts751_obj_0, &Status) != BSP_ERROR_NONE)   {     ret = BSP_ERROR_COMPONENT_FAILURE;   }   else   {     ret = BSP_ERROR_NONE;   }     if (EnvFuncDrv[FunctionIndex[ENV_TEMPERATURE]]->GetValue(&stts751_obj_0, &Value) != BSP_ERROR_NONE)   {     ret = BSP_ERROR_COMPONENT_FAILURE;   }   else   {     ret = BSP_ERROR_NONE;     temperature = (int32_t)(Value * 10);     OLED_show_envValue(1, &temperature);   }     if(TempLimitEventDetected)   {     TempLimitEventDetected = 0;         if (STTS751_TEMP_GetTemperatureLimitStatus(&stts751_obj_0, &HighLimit, &LowLimit, &ThermLimit) == BSP_ERROR_NONE)     {       if(HighLimit != 0U)       {         OLED_ShowStr(1, 6, "HighLimit", 1);       }       else if(LowLimit != 0U)       {         OLED_ShowStr(1, 6, "LowLimit", 1);       }             TempLimitTick = HAL_GetTick();     }   }   else if((HAL_GetTick() - TempLimitTick) > 200)   {     TempLimitTick = HAL_GetTick();     OLED_ShowStr(1, 6, "         ", 1);   }   效果图: 设置的高低温报警限值分别是28和32度。   附源码: STTS751:  

  • 2019-08-14
  • 加入了学习《利用PIC?/AVR? Curiosity Nano 开发板快速实现原型开发(英文)》,观看 利用PIC?/AVR? Curiosity Nano 开发板快速实现原型开发(英文)

  • 回复了主题帖: 《我的python世界》电子书

    下来看看

  • 2019-08-11
  • 发表了主题帖: 基于F103与X-NUCLEO-IKS01A3的计步手环之温度湿度气压检测功能

    本帖最后由 sylar^z 于 2019-8-12 00:21 编辑   本次计步手环设计基于F103核心板与X-NUCLEO-IKS01A3传感器开发板。温度湿度检测功能通过X-NUCLEO-IKS01A3上的HTS221传感器来实现。气压检测通过X-NUCLEO-IKS01A3上的LPS22HH传感器来实现。     HTS221是一种超紧凑型传感器,用于相对湿度和温度检测。HTS221供电电压1.7-3.6V,采样频率1Hz-12.5Hz,湿度精度:±3.5%rh,20至+80%rh,温度精度:±0.5°C,15至+40°C。可以通过常用的SPI与I2C进行通讯。       LPS22HH是一种超小型压阻式绝对压力传感器,可作为数字输出气压计使用。LPS22HH供电电压1.7-3.6V,绝对压力检测范围260至1260 hpa,绝对压力精度0.5 hpa。可以通过常用的SPI与I2C进行通讯。     计步手环使用HTS221实现温湿度检测功能及LPS22HH实现气压检测功能。在之前添加计步功能的程序(参看《 基于F103与X-NUCLEO-IKS01A3的计步手环之唤醒功能》)基础上进行功能添加。       首先对之前的程序作了一些改动,开启HTS221传感器与LPS22HH传感器,并通过SysTick产生一个1S的事件标志。每1S采集一次温度数据、湿度数据及气压数据,并用最近的三个数据进行均值滤波,来产生一个相对稳定的温度、湿度及气压数值。同时,还增加了按键事件检测及应用,包括单击、双击及长按事件。目前使用单击来切换显示页面。循环显示 计步——温度——湿度——气压界面。     //环境传感器数据采集   if(currData.env_data_get_flag)   {     currData.env_data_get_flag = 0;         if(0 == HTS221_Get_HUM(&currData.humidity[currData.humidityPos]))     {       currData.oledShowData.humidity = 0;       for(uint16_t i = 0; i < DATA_MEAN_NUM; i++)       {         currData.oledShowData.humidity += currData.humidity;       }       currData.oledShowData.humidity /= DATA_MEAN_NUM;     }         if(0 == HTS221_Get_TEMP(&currData.temperature[currData.temperaturePos]))     {       currData.oledShowData.temperature = 0;       for(uint16_t i = 0; i < DATA_MEAN_NUM; i++)       {         currData.oledShowData.temperature += currData.temperature;       }       currData.oledShowData.temperature /= DATA_MEAN_NUM;     }         if(0 == LPS22HH_Get_PRESS(&currData.pressure[currData.pressurePos]))     {       currData.oledShowData.pressure = 0;       for(uint16_t i = 0; i < DATA_MEAN_NUM; i++)       {         currData.oledShowData.pressure += currData.pressure;       }       currData.oledShowData.pressure /= DATA_MEAN_NUM;     }   }   //按键事件检测   if(KeyEventDetected)   {     KeyEventDetected = 0;     if(0 == KeyPressed)     {       if(KEY_PRESSED_GRADE_UNKNOW == keyPressedGrade)       {         if((HAL_GetTick() - keyPressedTick) > KEY_PRESSED_DELAY)         {           keyPressedGrade = KEY_PRESSED_GRADE_TAP;         }       }       else       {         keyPressedGrade = KEY_PRESSED_GRADE_UNKNOW;       }     }       }   else if(KeyPressed)   {     if(HAL_GPIO_ReadPin(USER_KEY_GPIO_Port, USER_KEY_Pin) == (uint32_t)GPIO_PIN_RESET)     {       if(KEY_PRESSED_GRADE_UNKNOW == keyPressedGrade)       {         if(keyPressedTick < (keyPressedTickLast + KEY_PRESSED_D_TAP_DELAY))         {           keyPressedGrade = KEY_PRESSED_GRADE_D_TAP;         }         else if((HAL_GetTick() - keyPressedTick) > KEY_PRESSED_L_TAP_DELAY)         {           keyPressedGrade = KEY_PRESSED_GRADE_L_TAP;           keyPressedTickLast = 0;         }       }     }   } //按键处理函数 void key_process(uint8_t currGrade) {   static emKeyPressedGrade keyPressedGradeOld = KEY_PRESSED_GRADE_UNKNOW;     if(keyPressedGradeOld == currGrade)   {     return;   }     keyPressedGradeOld = currGrade;   switch(currGrade)   {     case KEY_PRESSED_GRADE_TAP:       currData.oledShowData.currPage++;       if(currData.oledShowData.currPage >= HMI_PAGE_UNKNOW)       {         currData.oledShowData.currPage = HMI_PAGE_TEMPERATURE;       }       keyPressedGrade = KEY_PRESSED_GRADE_UNKNOW;       break;     case KEY_PRESSED_GRADE_D_TAP:       break;     case KEY_PRESSED_GRADE_L_TAP:       break;     default:       break;   } }   第一张是按键位置图。平时屏幕是关闭显示的,程序设计了6秒无动作自动关闭显示,节能。只要轻轻敲击一下,即可唤醒屏幕。   计步界面显示效果:   温度显示界面   湿度显示界面   气压显示界面   附源代码: HTS221手册: LPS22HH手册:        

  • 发表了主题帖: 基于F103与X-NUCLEO-IKS01A3的计步手环之唤醒功能

    本帖最后由 sylar^z 于 2019-8-11 21:19 编辑     本次计步手环设计基于F103核心板与X-NUCLEO-IKS01A3传感器开发板。唤醒功能通过X-NUCLEO-IKS01A3上的LIS2DW12传感器来实现。     LIS2DW12是一款高性能超低功耗三轴加速度计。供电电压1.62V-3.6V,可以通过常用的SPI与I2C进行通讯。LIS2DW12带有静止检测、运动检测功能。     计步手环使用LIS2DW12的运动检测来实现唤醒功能。在之前添加计步功能的程序(参看《 基于F103与X-NUCLEO-IKS01A3的计步手环之计步功能》)基础上进行功能添加。LIS2DW12传感器在(灵敏度可通过设置调整)受到震动后通过INT引脚输出高电平信号,通知F103核心板执行唤醒动作。实际操作时只要轻点X-NUCLEO-IKS01A3,产生震动效果就可触发唤醒功能。      首先对之前的程序作了一些改动,使能了LIS2DW12传感器,并增加了一个检测LIS2DW12的INT1的中断的引脚PB11。接着就是添加唤醒功能。在完成对LIS2DW12的初始化之后,需要使能LIS2DW12的唤醒功能,并配置相应的参数及中断输出。然后是检测唤醒中断及事件处理(这里是点亮OLED屏)。   1.设置LIS2DW12的输出频率、运行模式选择及满量程设置 运行可选模式如下: 根据选择的模式,对以下三个寄存器进行配置。   2.设置唤醒参数     3.设置唤醒中断通过INT1输出     INT1 pin可以绑定多个功能或状态同时使用。当检测到中断后,通过读取对应的事件状态寄存器来确定事件源。  唤醒中断为INT1_WU。 使能LIS2DW12的唤醒功能,并配置相应的参数及中断输出 /**  * @brief  Enable wake up detection  * @param  pObj the device pObj  * @retval 0 in case of success, an error code otherwise  */ int32_t LIS2DW12_ACC_Enable_Wake_Up_Detection(LIS2DW12_Object_t *pObj) {   int32_t ret = LIS2DW12_OK;   lis2dw12_ctrl4_int1_pad_ctrl_t val;   /* Output Data Rate selection */   if (LIS2DW12_ACC_SetOutputDataRate(pObj, 200.0f) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   /* Full scale selection */   if (LIS2DW12_ACC_SetFullScale(pObj, 2) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   /* WAKE_DUR setting */   if (lis2dw12_wkup_dur_set(&(pObj->Ctx), 0x00) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   /* Set wake up threshold. */   if (lis2dw12_wkup_threshold_set(&(pObj->Ctx), 0xf) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   if (lis2dw12_pin_int1_route_get(&(pObj->Ctx), &val) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   val.int1_wu = PROPERTY_ENABLE;   if (lis2dw12_pin_int1_route_set(&(pObj->Ctx), &val) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   return ret; } 4.事件确认及处理     检测STATUS寄存器中的WU_IA标志位,为1,则表示检测到有唤醒行为。执行唤醒后的动作,点亮OLED屏显示当前步数。 获取状态寄存器的操作代码 /**  * @brief  Get the status of all hardware events  * @param  pObj the device pObj  * @param  Status the status of all hardware events  * @retval 0 in case of success, an error code otherwise  */ int32_t LIS2DW12_ACC_Get_Event_Status(LIS2DW12_Object_t *pObj, LIS2DW12_Event_Status_t *Status) {   lis2dw12_status_t status_reg;   lis2dw12_ctrl4_int1_pad_ctrl_t ctrl4_int1_reg;   lis2dw12_ctrl5_int2_pad_ctrl_t ctrl5_int2_reg;   (void)memset((void *)Status, 0x0, sizeof(LIS2DW12_Event_Status_t));   if (lis2dw12_read_reg(&(pObj->Ctx), LIS2DW12_STATUS, (uint8_t *)&status_reg, 1) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   if (lis2dw12_read_reg(&(pObj->Ctx), LIS2DW12_CTRL4_INT1_PAD_CTRL, (uint8_t *)&ctrl4_int1_reg, 1) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   if (lis2dw12_read_reg(&(pObj->Ctx), LIS2DW12_CTRL5_INT2_PAD_CTRL, (uint8_t *)&ctrl5_int2_reg, 1) != LIS2DW12_OK)   {     return LIS2DW12_ERROR;   }   if (ctrl4_int1_reg.int1_wu == 1U)   {     if (status_reg.wu_ia == 1U)     {       Status->WakeUpStatus = 1;     }   }   if (ctrl4_int1_reg.int1_6d == 1U)   {     if (status_reg._6d_ia == 1U)     {       Status->D6DOrientationStatus = 1;     }   }   if (ctrl5_int2_reg.int2_sleep_chg == 1U)   {     if (status_reg.sleep_state == 1U)     {       Status->SleepStatus = 1;     }   }   return LIS2DW12_OK; }   附源码: LIS2DW12手册:

  • 2019-08-10
  • 发表了主题帖: 基于F103与X-NUCLEO-IKS01A3的计步手环之计步功能

    本帖最后由 sylar^z 于 2019-8-11 21:21 编辑     本次计步手环设计基于F103核心板与X-NUCLEO-IKS01A3传感器开发板。计步功能通过X-NUCLEO-IKS01A3上的LSM6DSO传感器来实现。     LSM6DSO是一款6轴传感器,包含3轴加速度与3轴陀螺仪。供电电压1.7V-3.6V,可以通过常用的SPI与I2C进行通讯。LSM6DSO带有丰富的运动检测功能,包含计步器、自由落体、唤醒、6d/4d方向、点击和双击等。     计步手环使用LSM6DSO的计步检测来实现计步功能。在正常移植X-NUCLEO-IKS01A3的驱动的程序(可参看《基于F103与X-NUCLEO-IKS01A3的计步手环之驱动移植》)上进行功能添加。      首先对之前的程序作了一些改动,让多传感器可以同时工作,并增加了一个检测LSM6DSO的INT1的中断的引脚PB7。接着就是添加计步功能。在完成对LSM6DSO的初始化之后,需要使能LSM6DSO的计步功能,并配置相应的参数及中断输出,以及清除当前步数。然后是检测步行及计算步数。   1.设置LSM6DSO的输出频率与满量程值   2.启用计步算法,设置模式。 可选模式如下: 根据选择的模式,会对一下三个寄存器进行配置,达到计步模式设置。   3.设置计步中断通过INT1输出     INT1 pin可以绑定多个功能或状态同时使用。当检测到中断后,通过读取对应的事件状态寄存器来确定事件源。     计步中断属于INT1_EMB_FUNC这个分类 使能LSM6DSO的计步功能,并配置相应的参数及中断输出 /**  * @brief  Enable pedometer  * @param  pObj the device pObj  * @retval 0 in case of success, an error code otherwise  */ int32_t LSM6DSO_ACC_Enable_Pedometer(LSM6DSO_Object_t *pObj) {     lsm6dso_pin_int1_route_t val;   /* Output Data Rate selection */   if (LSM6DSO_ACC_SetOutputDataRate(pObj, 26.0f) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   /* Full scale selection */   if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   /* Enable pedometer algorithm. */   if (lsm6dso_pedo_sens_set(&(pObj->Ctx), LSM6DSO_PEDO_BASE_MODE) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   /* Enable step detector on INT1 pin */   if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   val.emb_func_int1.int1_step_detector = PROPERTY_ENABLE;   if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), &val) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   return LSM6DSO_OK; }   4.事件确认及处理     检测EMB_FUNC_SRC中的STEP_DETECTED标志位,为1,则表示检测到有步行行为。计步数量加1。 /**  * @brief  Get the status of all hardware events  * @param  pObj the device pObj  * @param  Status the status of all hardware events  * @retval 0 in case of success, an error code otherwise  */ int32_t LSM6DSO_ACC_Get_Event_Status(LSM6DSO_Object_t *pObj, LSM6DSO_Event_Status_t *Status) {   uint8_t tilt_ia;   lsm6dso_wake_up_src_t wake_up_src;   lsm6dso_tap_src_t tap_src;   lsm6dso_d6d_src_t d6d_src;   lsm6dso_emb_func_src_t func_src;   lsm6dso_md1_cfg_t md1_cfg;   lsm6dso_md2_cfg_t md2_cfg;   lsm6dso_emb_func_int1_t int1_ctrl;   lsm6dso_emb_func_int2_t int2_ctrl;   (void)memset((void *)Status, 0x0, sizeof(LSM6DSO_Event_Status_t));   if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_WAKE_UP_SRC, (uint8_t *)&wake_up_src, 1) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_TAP_SRC, (uint8_t *)&tap_src, 1) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_D6D_SRC, (uint8_t *)&d6d_src, 1) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_mem_bank_set(&(pObj->Ctx), LSM6DSO_EMBEDDED_FUNC_BANK) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_EMB_FUNC_SRC, (uint8_t *)&func_src, 1) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_EMB_FUNC_INT1, (uint8_t *)&int1_ctrl, 1) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_EMB_FUNC_INT2, (uint8_t *)&int2_ctrl, 1) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_mem_bank_set(&(pObj->Ctx), LSM6DSO_USER_BANK) != 0)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_MD1_CFG, (uint8_t *)&md1_cfg, 1) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_MD2_CFG, (uint8_t *)&md2_cfg, 1) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if (lsm6dso_tilt_flag_data_ready_get(&(pObj->Ctx), &tilt_ia) != LSM6DSO_OK)   {     return LSM6DSO_ERROR;   }   if ((md1_cfg.int1_ff == 1U) || (md2_cfg.int2_ff == 1U))   {     if (wake_up_src.ff_ia == 1U)     {       Status->FreeFallStatus = 1;     }   }   if ((md1_cfg.int1_wu == 1U) || (md2_cfg.int2_wu == 1U))   {     if (wake_up_src.wu_ia == 1U)     {       Status->WakeUpStatus = 1;     }   }   if ((md1_cfg.int1_single_tap == 1U) || (md2_cfg.int2_single_tap == 1U))   {     if (tap_src.single_tap == 1U)     {       Status->TapStatus = 1;     }   }   if ((md1_cfg.int1_double_tap == 1U) || (md2_cfg.int2_double_tap == 1U))   {     if (tap_src.double_tap == 1U)     {       Status->DoubleTapStatus = 1;     }   }   if ((md1_cfg.int1_6d == 1U) || (md2_cfg.int2_6d == 1U))   {     if (d6d_src.d6d_ia == 1U)     {       Status->D6DOrientationStatus = 1;     }   }   if (int1_ctrl.int1_step_detector == 1U)   {     if (func_src.step_detected == 1U)     {       Status->StepStatus = 1;     }   }   if ((int1_ctrl.int1_tilt == 1U) || (int2_ctrl.int2_tilt == 1U))   {     if (tilt_ia == 1U)     {       Status->TiltStatus = 1;     }   }   return LSM6DSO_OK; }   附源码: LSM6DSO手册:    

  • 发表了主题帖: 基于F103与X-NUCLEO-IKS01A3的计步手环之驱动移植

    本次移植X-NUCLEO-IKS01A3传感器驱动是基于CORE-STM32F103C8开发板的。驱动移植与之前的NUCLEO-STM32L011K4差不多,主要是硬件配置的差异。驱动移植使用了官方的en.x-cube-mems1.zip资源包。传感器功能通过编译选项逐个开启,开启标志位于iks01a3_conf.h文件中。为了便于查看数据,接入了OLED显示屏,用来显示采集到的传感器数据。     有了之前NUCLEO-ST,M32L011K4和STM8S-DISCOVERY的调试经验。在调试过程中,未发现异常情况,比较顺利。    考虑之后用这款CORE-STM32F103C8做计步手环,所以给几个板子一起凹了一个造型。       CORE-STM32F103C8开发板   通过CubeMX配置引脚功能及初始化。主要配置就是I2C(PB8、PB9)。   驱动HTS221,采集数据。   驱动LPS22HH,采集数据。   驱动STTS751,采集数据。   驱动LSM6DSO,采集数据。   驱动LIS2DW12,采集数据。   驱动LIS2MDL,采集数据。   附源码:

  • 2019-08-06
  • 回复了主题帖: 下载有礼|ADI 《新概念模拟电路》全五册

    参与活动  

  • 2019-08-02
  • 回复了主题帖: 基于STM8S-DISCOVERY的X-NUCLEO-IKS01A3传感器驱动移植

    yang_alex 发表于 2019-7-30 19:29 在SMBus基础上又发展出一个PMBus.
    度了一个,PMBus是数字电源管理协议。PMBus用了指令的通讯形式,总线更像一个载体。

  • 2019-07-31
  • 加入了学习《PMBus 简介》,观看 1.2 TI PMBus 简介课程(一)

  • 加入了学习《PMBus 简介》,观看 1.1 TI PMBus 简介课程

  • 2019-07-30
  • 回复了主题帖: 基于STM8S-DISCOVERY的X-NUCLEO-IKS01A3传感器驱动移植

    I2C与SMBus之间的差异    电气特性差异: 1. 逻辑电平定义        I2C的Hi/Lo逻辑电平有两种认定法:相对认定与绝对认定,相对认定是依据Vdd的电压来决定,Hi为0.7Vdd,Lo为0.3Vdd,绝对认定则与TTL 准位认定相同,直接指定Hi/Li电压,Hi为3.0V,Lo为1.5V。相对的SMBus只有绝对认定,且电平与I2C有异,Hi为2.1V,Lo为0.8V,与I2C不全然吻合但也算部分交集。        SMBus后来增订一套更低电压的电平认定,Hi为1.4V,Lo为0.6V,这是为了让运用SMBus的装置能更省成本的作法。   2. 限流        由于SMBus一开始就是运用在笔记本电脑内,所以省电的表现优于I2C,只需100uA就能维持工作,I2C却要到3mA同样的低用电特性也反应在漏电流(Leakage Current)的要求上,I2C最大的漏电流为10uA,SMBus为1uA,但是1uA似乎过度严苛,使运用SMBus的装置在验证测试时耗费过多的成本与心力,因此之后的SMBus 1.1版放宽了漏电流上限,最高可至5uA   3. 其他相关限制        I2C有线路电容的限制,SMBus却没有,但也有相类似的配套规范,即是电平下拉时的电流限制,当SMBus的集电极开路Pin导通而使线路接地时,流经接地的电流不能高于350uA,另上电流(即相同的集电极开路Pin开路时)也一样有规范,最小不低于100uA,最高也是不破350uA的。   时序差别 1. 运作频率        I2C此方面相当宽裕,最低频可至0Hz(直流状态,等于时间暂停),高可至100kHz(Standard Mode)、400kHz(Fast Mode)、乃至3.4MHz(High Speed Mode),相对的SMBus就很局限,最慢不慢于10kHz,最快不快于100kHz。很明显的,I2C与SMBus的交集运作频率即是10kHz〜100kHz间。   2. 数据保持时间(Data Hold Time)        SMBus在数据传输后还有数据保持时间的要求,SMBus 规定SMBCLK线路的电平下降后,SMBDAT上的数据必须持续保留300nS,但I2C 却没有对此有相同的强制要求。   3. 恢复时间        SMBus对接口被重置(Reset)后的恢复时间(Timeout)也有要求,一般而言是35mS,I2C这方面亦无约束,可以任意延长时间。相同的SMBus也要求无论是在主控端(Master)或受控端(Slave),其频率处于Lo电平时的最长持续时间不得超越限制,以免因为长时间处在Lo准位,而致收发两端时序脱轨(失去同步,造成后续误动作)。   4. [已妥]与[未妥]机制的强制性差别        I2C并没有强制规定接收端非要做出响应,而SMBus上是不允许接收端在接收地址信息后却不发出回应,每次都要回应。

  • 发表了主题帖: 基于STM8S-DISCOVERY的X-NUCLEO-IKS01A3传感器驱动移植

    本帖最后由 sylar^z 于 2019-7-30 17:43 编辑   本次移植X-NUCLEO-IKS01A3传感器驱动是基于STM8S-DISCOVERY开发板的,使用了官方的en.x-cube-mems1.zip资源包。传感器功能通过编译选项逐个开启,开启标志位于iks01a3_conf.h文件中。为了便于查看数据,接入了OLED显示屏,用来显示采集到的传感器数据。        本次在STM8S-DISCOVERY上移植驱动采用模拟I2C用于通讯。模拟I2C使用了PC6作为SDA,PC7作为SCL。这两个引脚与一组电源和地相邻,便于接线。 在调试过程中,LSM6DSO、LIS2DW12、LIS2MDL、HTS221、LPS22HH五个传感器都比较顺利的调通,得到了传感器数据。而STTS751传感器移植无法通讯,在主芯片发送地址信息后,始终都是NACK。   之前查看了STTS751的手册, STTS751使用的SMBus协议。SMBus协议是Intel与Duracell共同制订笔记本电脑所用的智能型电池时所研发的接口,参考自I2C,与I2C有交集的部分,也有部分区别,在一般情况下,可以使用I2C协议的接口来进行通讯。区别说明参看2楼。        1. 首先怀疑的是时序问题,通过逻辑分析仪分析发现当前的频率大于160多K了,超过了SMBus的10K-100K的范围。调整了一下延时,频率调整到90K左右,还是无法通讯。        2. 对比模拟I2C与硬件I2C,发现模拟I2C的时序不是准确频率的时序,会时快时慢。由于STM8S-DISCOVERY频率较低。所以将模拟IIC移植到之前已调试过的NUCLEO-L011K4上,同样无法通讯。使用systick定时产生中断,模拟10K的I2C信号进行对比(同时测试了模拟引脚片上上拉和不上拉)。两者时序基本相同,仍然无法通讯。时序对比图如下:           3. 然后考虑是否是I2C信号通过ST2378E后电平信号不能完全满足SMBus协议。就直接将模拟I2C连接到I2C1(JP7/JP8的I2C_SDA/I2C_SCL)上,通讯成功,可以采集数据了。 说明:红色效方块是JP7/JP8的跳线帽;长方形小方框是I2C及电源地的接口;   这一点非常奇怪,上面2中的对比试验,所有接线都是相同的,都在同样的两个引脚输出。唯一的区别就是一个使用硬件I2C,一个使用模拟I2C。硬件I2C可以通讯,而模拟I2C不行。     接下去上图:            驱动HTS221,采集数据。     驱动LPS22HH,采集数据。       驱动STTS751,采集数据。       驱动LSM6DSO,采集数据。     驱动LIS2DW12,采集数据。       驱动LIS2MDL,采集数据。     源码:   

  • 2019-07-27
  • 回复了主题帖: 基于NUCLEO-L011K4的X-NUCLEO-IKS01A3传感器驱动移植

    dcexpert 发表于 2019-7-25 11:12 I2C不响应有时是因为I2C总线出错了,需要重新初始化。
    应该不是I2C出错。因为我先复位了一次NUCLEO-L011K4及重新下载了一次程序,仍然无法读取传感器的数据。整体断电后才恢复正常。

  • 回复了主题帖: 颁奖:“拆”泰克为工程师而创的新示波器,抽好礼

    nmg 发表于 2019-7-27 11:39 填表为准,如果奖品不是自己需要的,可兑换E金币
    好的,已兑换金币

  • 2019-07-26
  • 回复了主题帖: 颁奖:“拆”泰克为工程师而创的新示波器,抽好礼

    信息确认,感谢泰克,感谢eeworld!!! 其实想要那本书。。。

  • 2019-07-24
  • 发表了主题帖: 基于NUCLEO-L011K4的X-NUCLEO-IKS01A3传感器驱动移植

    本帖最后由 sylar^z 于 2019-7-24 18:22 编辑     本次移植X-NUCLEO-IKS01A3传感器驱动是基于NUCLEO-L011K4开发板的,使用了官方的en.x-cube-mems1.zip资源包。由于NUCLEO-L011K4只有16K ROM,所以传感器功能只能通过编译选项逐个开启,开启标志位于iks01a3_conf.h文件中。为了便于查看数据,接入了OLED显示屏,用来显示采集到的传感器数据。     在调试过程中,发现X-NUCLEO-IKS01A3震动后有时会不响应(I2C通讯不回),重新启动L011K4后依然不响应,直到给IKS01A3重新上电才正常。不知其他网友有没有遇到这样的情况。       NUCLEO-L011K4开发板     通过CubeMX配置引脚功能及初始化。     驱动HTS221,采集数据。     驱动LPS22HH,采集数据。     驱动STTS751,采集数据。     驱动LSM6DSO,采集数据。     驱动LIS2DW12,采集数据。     驱动LIS2MDL,采集数据。   源码:    

  • 2019-07-22
  • 点评了资料: 电流有效值计算

  • 点评了资料: Proteus教程中文版,值得你学习

  • 点评了资料: 优化输电线路 精确测量电压驻波比(VSWR)

最近访客

< 1/1 >

统计信息

已有10人来访过

  • 芯币:264
  • 好友:1
  • 主题:9
  • 回复:37
  • 课时:--
  • 资源:--

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言