北方

  • 2019-07-17
  • 发表了主题帖: 3、基于Nucleo-L476L的健康运动助手项目开发

    本帖最后由 北方 于 2019-7-17 16:57 编辑 1、简述-基于Nucleo-L476L的健康运动助手    基于Nucleo-L476L的健康运动助手是一个基于STM32L476L的便携运动健康电子助手的原型设计。实现以下功能:    启动后不读取传感器数据,降低功耗。当检测到运动数据后,启动计步器,开始计算运动步数,同时读取运动环境的温度和湿度,同时读取大气压,折算运动位置的海拔。在中止运动一段时间后,停止计数,并输出运动量。   2、采用的硬件     采用Nucleo-STM32L476和X-NUCLEO-IKS01A3。其中应用到的四种传感器有: LSM6DSO 用于计步器计数, LIS2DW12 用于从休眠中唤醒,进入传感器读取和计步器计数 LPS22HH   用于读取大气压数据 STTS751   用于读取环境温度   3、开发环境和工具 3.1 开发环境使用Arduino1.8.9 3.2 开发需要先安装以上4种传感器的arduino驱动程序,然后直接在程序中引用库就可以了。   4、实现代码 这个代码使用了2个标志位mems_event = 0 和 ped_event=0,分别启动中断,上升沿启动内部置位的变化。 同时设定了一个IDLEPERIOD,演示设置位10000ms,即10秒,之后就退出计数。   /** ****************************************************************************** * @brief Arduino test application for the STMicrolectronics X-NUCLEO-IKS01A3 ****************************************************************************** */ // Includes #include <LSM6DSOSensor.h> #include <LIS2DW12Sensor.h> #include <LPS22HHSensor.h> #include <STTS751Sensor.h> #ifdef ARDUINO_SAM_DUE #define DEV_I2C Wire1 #elif defined(ARDUINO_ARCH_STM32) #define DEV_I2C Wire #elif defined(ARDUINO_ARCH_AVR) #define DEV_I2C Wire #else #define DEV_I2C Wire #endif #define SerialPort Serial #define INT_1 4 #define IDLEPERIOD 10000 // Components LSM6DSOSensor *AccGyr; LIS2DW12Sensor *Acc2; LPS22HHSensor *Press; STTS751Sensor *Temp; //Interrupts. volatile int mems_event = 0; volatile int ped_event = 0; uint16_t step_count = 0; char report[256]; uint32_t previous_tick; void INT0Event_cb(); void INT1Event_cb(); void runningmode(); void setup() { // Led. pinMode(LED_BUILTIN, OUTPUT); // Initialize serial for output. SerialPort.begin(115200); // Initialize I2C bus. DEV_I2C.begin(); //Interrupts. attachInterrupt(A3, INT0Event_cb, RISING); attachInterrupt(INT_1, INT1Event_cb, RISING); //1. Using LSM6DSOSensor for Pedometer AccGyr = new LSM6DSOSensor (&DEV_I2C); AccGyr->Enable_X(); AccGyr->Enable_G(); AccGyr->Enable_Pedometer(); previous_tick = millis(); //2. Using LIS2DW12Sensor for wakeup detection Acc2 = new LIS2DW12Sensor (&DEV_I2C); Acc2->Enable_X(); Acc2->Enable_Wake_Up_Detection(); //3. Using LPS22HHSensor Press = new LPS22HHSensor(&DEV_I2C); Press->Enable(); //4. Using STTS751Sensor Temp = new STTS751Sensor (&DEV_I2C); Temp->Enable(); } void loop() { if (mems_event) { mems_event=0; LIS2DW12_Event_Status_t status; Acc2->Get_Event_Status(&status); if (status.WakeUpStatus) { // Output data. SerialPort.println("Wake up Detected!"); runningmode(); } } } void runningmode() { bool idel=1; while (idel){ if (ped_event) { ped_event=0; LSM6DSO_Event_Status_t status; AccGyr->Get_X_Event_Status(&status); if (status.StepStatus) { // New step detected, so print the step counter AccGyr->Get_Step_Count(&step_count); //snprintf(report, sizeof(report), "Step counter: %d", step_count); //SerialPort.println(report); } } // Print the step counter in any case every 3000 ms uint32_t current_tick = millis(); if((current_tick - previous_tick) >= IDLEPERIOD) { AccGyr->Get_Step_Count(&step_count); snprintf(report, sizeof(report), "Step counter: %d", step_count); SerialPort.println(report); previous_tick = millis(); // Read pressure and temperature. float pressure = 0, temperature2 = 0; Press->GetPressure(&pressure); //Read temperature float temperature = 0; Temp->GetTemperature(&temperature); SerialPort.print("| Pres[hPa]: "); SerialPort.print(pressure, 2); SerialPort.print(" | Temp[C]: "); SerialPort.print(temperature, 2); SerialPort.print("\n "); // Quit the while loop, idel=0; } } } void INT1Event_cb() { ped_event = 1; } void INT0Event_cb() { mems_event = 1; } 5、结果演示 5.1 初步显示计步器功能 5.2 综合计步器和环境温度和气压显示功能 显示唤醒后,开始计算运动步数,这里用手的摇动来显示结果,同时显示出环境温度和大气压。   6. 基于Nucleo-L476L的传感器数据读取的几点说明和建议 演示视频: 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-07-16
  • 发表了主题帖: 2、基于Nucleo-L476L的全部传感器数据读取和演示

    本帖最后由 北方 于 2019-7-16 15:52 编辑 1、基于Nucleo-L476L的全部传感器数据读取和演示主要是演示评测计划中全部传感器数据的读取和输出。 根据分析传感器的数据表,可以看出,这些传感器全部是 通过I2C总线读取和访问的。每个传感器具有一个唯一的地址码,再I2C读取的时候,指定地址码就可以唯一的访问这个传感器。传感器的地址码再开发板的反面完整地列出,详见上一帖的照片。 再这样的情况下,对于传感器数据的读取就变为对I2C的访问和读取,这样简化了设计,而且具有快速移植的特点。 2、开发环境和IDE 2.1 原计划中采用的arduino平台是一个快速开发和评测的工具,但是代码编译同样具有高效特点,因为,调用的编译器是GCC。对于代码的效率,重要的是代码逻辑的优化,那么同样具有复杂程序开发的能力。编译的hex可执行文件,可以直接写入flash,即使是工业化开发也没有问题。 2.2 再完成了arduino平台的开发后,其实同样的开发板移植到mbed平台也是非常迅速的,可以发现,很多代码都可以直接使用,适当调整一下格式就可以了。但是因为本次活动的先发先评的积分规则,如果同时进行评测mbed的平台会影响其他评测的计分,毕竟还有没有收到快递的。 2.3 使用Arduino-uno和使用Nucleo-Arduino开发的最大区别是标准arduino使用原生I2C库wire.h,使用更简单。而Nucleo-arduino重写了I2C的驱动,使用的是TwoWire类,用一个指针传递DEVICE_I2C,这样和STM的HAL等开发库的代码保持一致。所以,如果使用arduino-uno等均需要再wire部分进行调整。 3. 综合全部传感器数据读取的程序helloworld代码如下。因为是arduino代码,所以非常直观。 // Includes #include <LSM6DSOSensor.h> #include <LIS2DW12Sensor.h> #include <LIS2MDLSensor.h> #include <LPS22HHSensor.h> #include <STTS751Sensor.h> #include <HTS221Sensor.h> #ifdef ARDUINO_SAM_DUE #define DEV_I2C Wire1 #elif defined(ARDUINO_ARCH_STM32) #define DEV_I2C Wire #elif defined(ARDUINO_ARCH_AVR) #define DEV_I2C Wire #else #define DEV_I2C Wire #endif #define SerialPort Serial // Components LSM6DSOSensor *AccGyr; LIS2DW12Sensor *Acc2; LIS2MDLSensor *Mag; LPS22HHSensor *PressTemp; HTS221Sensor *HumTemp; STTS751Sensor *Temp3; void setup() { // Led. pinMode(LED_BUILTIN, OUTPUT); // Initialize serial for output. SerialPort.begin(115200); // Initialize I2C bus. DEV_I2C.begin(); AccGyr = new LSM6DSOSensor (&DEV_I2C); AccGyr->Enable_X(); AccGyr->Enable_G(); Acc2 = new LIS2DW12Sensor (&DEV_I2C); Acc2->Enable_X(); Mag = new LIS2MDLSensor (&DEV_I2C); Mag->Enable(); PressTemp = new LPS22HHSensor(&DEV_I2C); PressTemp->Enable(); HumTemp = new HTS221Sensor (&DEV_I2C); HumTemp->Enable(); Temp3 = new STTS751Sensor (&DEV_I2C); Temp3->Enable(); } void loop() { // Led blinking. digitalWrite(LED_BUILTIN, HIGH); delay(250); digitalWrite(LED_BUILTIN, LOW); delay(250); // Read humidity and temperature. float humidity = 0, temperature = 0; HumTemp->GetHumidity(&humidity); HumTemp->GetTemperature(&temperature); // Read pressure and temperature. float pressure = 0, temperature2 = 0; PressTemp->GetPressure(&pressure); PressTemp->GetTemperature(&temperature2); //Read temperature float temperature3 = 0; Temp3->GetTemperature(&temperature3); // Read accelerometer and gyroscope. int32_t accelerometer[3]; int32_t gyroscope[3]; memset(accelerometer, 0, 3); memset(gyroscope, 0, 3); AccGyr->Get_X_Axes(accelerometer); AccGyr->Get_G_Axes(gyroscope); //Read accelerometer int32_t accelerometer2[3]; memset(accelerometer2, 0, 3); Acc2->Get_X_Axes(accelerometer2); //Read magnetometer int32_t magnetometer[3]; memset(magnetometer, 0, 3); Mag->GetAxes(magnetometer); // Output data. SerialPort.print("| Hum[%]: "); SerialPort.print(humidity, 2); SerialPort.print(" | Temp[C]: "); SerialPort.print(temperature, 2); SerialPort.print(" | Pres[hPa]: "); SerialPort.print(pressure, 2); SerialPort.print(" | Temp2[C]: "); SerialPort.print(temperature2, 2); SerialPort.print(" | Temp3[C]: "); SerialPort.print(temperature3, 2); SerialPort.print(" | Acc[mg]: "); SerialPort.print(accelerometer[0]); SerialPort.print(" "); SerialPort.print(accelerometer[1]); SerialPort.print(" "); SerialPort.print(accelerometer[2]); SerialPort.print(" | Gyr[mdps]: "); SerialPort.print(gyroscope[0]); SerialPort.print(" "); SerialPort.print(gyroscope[1]); SerialPort.print(" "); SerialPort.print(gyroscope[2]); SerialPort.print(" | Acc2[mg]: "); SerialPort.print(accelerometer2[0]); SerialPort.print(" "); SerialPort.print(accelerometer2[1]); SerialPort.print(" "); SerialPort.print(accelerometer2[2]); SerialPort.print(" | Mag[mGauss]: "); SerialPort.print(magnetometer[0]); SerialPort.print(" "); SerialPort.print(magnetometer[1]); SerialPort.print(" "); SerialPort.print(magnetometer[2]); SerialPort.println(" |"); } 程序编译并上传到开发板,占用了38.180k内存(3%代码空间) 同时串口输出了全部的传感器数据,如下 4、演示视频 这个视频中,显示了变化的传感器数据读数,其中在转动和冲击时,x-y-z传感器和加速度传感器的数据都在实时地变化。 5、第一步基本数据读取和显示的评测任务完成。包括了以下的全部传感器。后续在一个演示程序中使用。 LSM6DSOSensor ; LIS2DW12Sensor ; LIS2MDLSensor ; LPS22HHSensor ; HTS221Sensor ; STTS751Sensor ; 参考的流程包括以下步骤, 导入传感器驱动, #include <LSM6DSOSensor.h> #include <LIS2DW12Sensor.h> #include <LIS2MDLSensor.h> #include <LPS22HHSensor.h> #include <STTS751Sensor.h> #include <HTS221Sensor.h>   创建传感器实例 LSM6DSOSensor *AccGyr; LIS2DW12Sensor *Acc2; LIS2MDLSensor *Mag; LPS22HHSensor *PressTemp; HTS221Sensor *HumTemp; STTS751Sensor *Temp3; // new instance   AccGyr = new LSM6DSOSensor (&DEV_I2C);   AccGyr->Enable_X();   AccGyr->Enable_G();   Acc2 = new LIS2DW12Sensor (&DEV_I2C);   Acc2->Enable_X();   Mag = new LIS2MDLSensor (&DEV_I2C);   Mag->Enable();   PressTemp = new LPS22HHSensor(&DEV_I2C);   PressTemp->Enable();   HumTemp = new HTS221Sensor (&DEV_I2C);   HumTemp->Enable();   Temp3 = new STTS751Sensor (&DEV_I2C);   Temp3->Enable(); 初始化I2C端口 #define DEV_I2C Wire   DEV_I2C.begin(); 逐个读取传感器数据并用串口以115200的波特率输出 float humidity = 0, temperature = 0;   HumTemp->GetHumidity(&humidity);   HumTemp->GetTemperature(&temperature);   // Read pressure and temperature.   float pressure = 0, temperature2 = 0;   PressTemp->GetPressure(&pressure);   PressTemp->GetTemperature(&temperature2);   //Read temperature   float temperature3 = 0;   Temp3->GetTemperature(&temperature3);   // Read accelerometer and gyroscope.   int32_t accelerometer[3];   int32_t gyroscope[3];   memset(accelerometer, 0, 3);   memset(gyroscope, 0, 3);   AccGyr->Get_X_Axes(accelerometer);   AccGyr->Get_G_Axes(gyroscope);   //Read accelerometer   int32_t accelerometer2[3];   memset(accelerometer2, 0, 3);   Acc2->Get_X_Axes(accelerometer2);   //Read magnetometer   int32_t magnetometer[3];   memset(magnetometer, 0, 3);   Mag->GetAxes(magnetometer);   此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-07-15
  • 发表了主题帖: 1、基于Nucleo-L476L的HTS221等全部传感器的驱动

    本帖最后由 北方 于 2019-7-16 14:51 编辑 1、基于Nucleo-STM32L476L的Arduino实现NUCLEO-IKS01A3的全部传感器驱动实现。     初始计划是采用MKR1000,但是在使用和下载的过程中,这个开发板给变砖了。 所以只好先拿出吃灰的Nucleo-STM32L476L先实现以下基本的arduino驱动。在完成这个基本评测后再移植到其他arduino开发板上使用。 针对不同的传感器,参照以下具体代码逐个说明和实现。       这个过程中首先需要使用开发板管理器安装arduino开发板, 这样就可以设置开发板了, 然后安装NUCLEO-IKS01A3的传感器驱动, 这样就可以再程序中直接使用驱动库了。 驱动和安装说明可以从如下链接获得,https://github.com/stm32duino/Arduino_Core_STM32 这个是官方的arduino驱动。 2、传感器驱动代码和说明 2.1 首先导入HTS221Sensor.h,这个是HTS221的驱动,设定I2C的引脚后就可以直接访问HTS221传感器,程序读取传感器的数据,转换后通过串口输出。 代码如下: #include <HTS221Sensor.h> #define I2C2_SCL PB10 #define I2C2_SDA PB11 // Components. HTS221Sensor *HumTemp; TwoWire *dev_i2c; void setup() { // Led. pinMode(LED_BUILTIN, OUTPUT); // Initialize serial for output. Serial.begin(9600); // Initialize I2C bus. dev_i2c = new TwoWire(I2C2_SDA, I2C2_SCL); dev_i2c->begin(); // Initlialize components. HumTemp = new HTS221Sensor (dev_i2c); HumTemp->Enable(); } void loop() { // Led blinking. digitalWrite(LED_BUILTIN, HIGH); delay(250); digitalWrite(LED_BUILTIN, LOW); delay(250); // Read humidity and temperature. float humidity, temperature; HumTemp->GetHumidity(&humidity); HumTemp->GetTemperature(&temperature); // Output data. Serial.print("Hum[%]: "); Serial.print(humidity, 2); Serial.print(" | Temp[C]: "); Serial.println(temperature, 2); } 输出结果如下, 因为本传感器只检查温度和湿度,所以使用照片显示结果,   2.2  3D加速度+3D陀螺仪    LSM6DS +Nucleo-STM32L476L读取传感器数据 首先导入驱动程序 #include <LSM6DSOSensor.h> 同上,先设定I2C的接口,然后把变化传感器数据输出到串口 代码如下: #include <LSM6DSOSensor.h> #ifdef ARDUINO_SAM_DUE #define DEV_I2C Wire1 #elif defined(ARDUINO_ARCH_STM32) #define DEV_I2C Wire #elif defined(ARDUINO_ARCH_AVR) #define DEV_I2C Wire #else #define DEV_I2C Wire #endif #define SerialPort Serial #define INT_1 4 LSM6DSOSensor *accGyr; //Interrupts. volatile int mems_event = 0; char report[256]; void INT1Event_cb(); void sendOrientation(); void setup() { // Led. pinMode(LED_BUILTIN, OUTPUT); // Initialize serial for output. SerialPort.begin(115200); // Initialize I2C bus. DEV_I2C.begin(); //Interrupts. attachInterrupt(INT_1, INT1Event_cb, RISING); accGyr = new LSM6DSOSensor (&DEV_I2C); accGyr->Enable_X(); accGyr->Enable_6D_Orientation(LSM6DSO_INT1_PIN); } void loop() { if (mems_event) { mems_event=0; LSM6DSO_Event_Status_t status; accGyr->Get_X_Event_Status(&status); if (status.D6DOrientationStatus) { sendOrientation(); // Led blinking. digitalWrite(LED_BUILTIN, HIGH); delay(100); digitalWrite(LED_BUILTIN, LOW); } } } void INT1Event_cb() { mems_event = 1; } void sendOrientation() { uint8_t xl = 0; uint8_t xh = 0; uint8_t yl = 0; uint8_t yh = 0; uint8_t zl = 0; uint8_t zh = 0; accGyr->Get_6D_Orientation_XL(&xl); accGyr->Get_6D_Orientation_XH(&xh); accGyr->Get_6D_Orientation_YL(&yl); accGyr->Get_6D_Orientation_YH(&yh); accGyr->Get_6D_Orientation_ZL(&zl); accGyr->Get_6D_Orientation_ZH(&zh); if ( xl == 0 && yl == 0 && zl == 0 && xh == 0 && yh == 1 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | * | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n |________________| \r\n" ); } else if ( xl == 1 && yl == 0 && zl == 0 && xh == 0 && yh == 0 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | * | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 0 && xh == 1 && yh == 0 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | * | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 1 && zl == 0 && xh == 0 && yh == 0 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | * | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 0 && xh == 0 && yh == 0 && zh == 1 ) { sprintf( report, "\r\n __*_____________ " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 1 && xh == 0 && yh == 0 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n |________________| " \ "\r\n * \r\n" ); } else { sprintf( report, "None of the 6D orientation axes is set in LSM6DSO - accelerometer.\r\n" ); } SerialPort.print(report); } 通过串口演示读取加速度计的变化位置, 主要代码 sprintf( report, "\r\n ________________ " \ "\r\n |________________| " \ "\r\n * \r\n" ); 2.3 3D磁力计    LIS2MD + Nucleo-STM32L476L 读取传感器数据 首先导入驱动程序 #include <LIS2DW12Sensor.h> 同上,先设定I2C的接口,然后把变化传感器数据输出到串口 代码类似上面,具体读取再后面的综合数据输出中展示。 2.4 3D加速度    LIS2DW12+Nucleo-STM32L476L 读取传感器数据 首先导入驱动程序 同上,先设定I2C的接口,然后把变化传感器数据输出到串口 代码如下: #include <LIS2DW12Sensor.h> #ifdef ARDUINO_SAM_DUE #define DEV_I2C Wire1 #elif defined(ARDUINO_ARCH_STM32) #define DEV_I2C Wire #elif defined(ARDUINO_ARCH_AVR) #define DEV_I2C Wire #else #define DEV_I2C Wire #endif #define SerialPort Serial // Components. LIS2DW12Sensor *accelero; //Interrupts. volatile int mems_event = 0; char report[256]; void INT1Event_cb(); void sendOrientation(); void setup() { // Led. pinMode(LED_BUILTIN, OUTPUT); // Initialize serial for output. SerialPort.begin(115200); // Initialize I2C bus. DEV_I2C.begin(); //Interrupts. attachInterrupt(A3, INT1Event_cb, RISING); // Initlialize components. accelero = new LIS2DW12Sensor(&DEV_I2C); accelero->Enable_X(); // Enable 6D Orientation. accelero->Enable_6D_Orientation(); } void loop() { if (mems_event) { mems_event = 0; LIS2DW12_Event_Status_t status; accelero->Get_Event_Status(&status); if (status.D6DOrientationStatus) { // Send 6D Orientation sendOrientation(); // Led blinking. digitalWrite(LED_BUILTIN, HIGH); delay(100); digitalWrite(LED_BUILTIN, LOW); } } } void INT1Event_cb() { mems_event = 1; } void sendOrientation() { uint8_t xl = 0; uint8_t xh = 0; uint8_t yl = 0; uint8_t yh = 0; uint8_t zl = 0; uint8_t zh = 0; accelero->Get_6D_Orientation_XL(&xl); accelero->Get_6D_Orientation_XH(&xh); accelero->Get_6D_Orientation_YL(&yl); accelero->Get_6D_Orientation_YH(&yh); accelero->Get_6D_Orientation_ZL(&zl); accelero->Get_6D_Orientation_ZH(&zh); if ( xl == 1 && yl == 0 && zl == 0 && xh == 0 && yh == 0 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | * | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 1 && zl == 0 && xh == 0 && yh == 0 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | * | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 0 && xh == 0 && yh == 1 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | * | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 0 && xh == 1 && yh == 0 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | * | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 0 && xh == 0 && yh == 0 && zh == 1 ) { sprintf( report, "\r\n __*_____________ " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 1 && xh == 0 && yh == 0 && zh == 0 ) { sprintf( report, "\r\n ________________ " \ "\r\n |________________| " \ "\r\n * \r\n" ); } else { sprintf( report, "None of the 6D orientation axes is set in LIS2DW12 - accelerometer.\r\n" ); } SerialPort.print(report); } 用图形的符号表示地磁的方向, 参见代码 sprintf( report, "\r\n ________________ " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | * | " \ "\r\n |________________| \r\n" );   2.5 气压传感器    LPS22HH   + Nucleo-STM32L476L读取传感器数据 首先导入驱动程序 同上,先设定I2C的接口,然后把变化传感器数据输出到串口 代码类似,具体参见下一贴。 2.6 温度传感器    STTS751+  Nucleo-STM32L476L读取传感器数据 首先导入驱动程序#include <STTS751Sensor.h> 在程序中,首先定义i2c的引脚和接线,然后读取传感器数据,并输出到串口。   实现代码如下, #include <STTS751Sensor.h> #ifdef ARDUINO_SAM_DUE #define DEV_I2C Wire1 #elif defined(ARDUINO_ARCH_STM32) #define DEV_I2C Wire #elif defined(ARDUINO_ARCH_AVR) #define DEV_I2C Wire #else #define DEV_I2C Wire #endif #define SerialPort Serial #define INT_1 A4 //Interrupts. volatile int mems_event = 0; uint8_t high = 0, low = 0; uint32_t previous_tick; float temperature = 0; STTS751Sensor *Temp; void INT1Event_cb() { mems_event = 1; } void setup() { // Led. pinMode(LED_BUILTIN, OUTPUT); // Initialize serial for output. SerialPort.begin(115200); // Initialize I2C bus. DEV_I2C.begin(); //Interrupts. attachInterrupt(INT_1, INT1Event_cb, FALLING); Temp = new STTS751Sensor(&DEV_I2C); Temp->Enable(); Temp->SetOutputDataRate(4.0f); Temp->SetLowTemperatureThreshold(22.0f); Temp->SetHighTemperatureThreshold(28.0f); Temp->SetEventPin(1); Temp->GetTemperatureLimitStatus(NULL, NULL, NULL); previous_tick=millis(); } void loop() { if (mems_event) { mems_event=0; uint8_t highTemp = 0, lowTemp = 0; Temp->GetTemperatureLimitStatus(&highTemp, &lowTemp, NULL); if (highTemp){ high = 1; low = 0; } if (lowTemp){ low = 1; high = 0; } Temp->GetTemperature(&temperature); // Led blinking. digitalWrite(LED_BUILTIN, HIGH); delay(100); digitalWrite(LED_BUILTIN, LOW); } uint32_t current_tick = millis(); if ((current_tick - previous_tick) >= 2000){ if (!high && !low){ Temp->GetTemperature(&temperature); } SerialPort.print("Temp[C]: "); SerialPort.print(temperature, 2); if (high){ SerialPort.println(" High temperature detected!(>28C) "); high = 0; } else if (low) { SerialPort.println(" Low temperature detected!(<22C) "); low = 0; } else { SerialPort.println(); } previous_tick = millis(); } } 程序下载和串口输出如下, 3、实现视频不单独演示,详见下一帖综合展示。       此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-07-11
  • 回复了主题帖: 颁奖:从终端到架构,TE Connectivity(TE)助你连接5G高速未来 看视频答题赢好礼!

    确认个人信息无误 ,兑换成E金币,谢谢

  • 2019-07-10
  • 发表了主题帖: 【沁恒试用】精简手机系统设计 #1

    本帖最后由 北方 于 2019-7-10 13:55 编辑 精简手机系统设计 1、概述 精简手机系统设计是基于8051单片机沁恒CH549L和安可信A9G数据通讯模块开放的精简手机。 2、实现的功能 能够实现精简通讯和实时位置追踪功能。   3、实现的逻辑和原理 3.1 采用CH549和安可信A9G数据通讯模块通过UART口进行数据通讯和连接,连接采用的是标准的AT命令。 在CH549的开发中,使用了touchKey,ADC, GPIO,UART等多个资源,经过选择和调试,项目能够完整运行。其中CH549提供了UART0,UART1,UART2和UART3均测试,其中UART2和ouchkey的ADC有冲突,UART1在touchkey init中也有冲突,需要调整。 开发板连接如下图   本项目选择了UART0,可以在一个端口同时被板载USB-ttl转换,从desktop上也可以获取at通讯的信号,如下图   3.2 项目初步调试的代码如下,大部分是touchkey范例的参照。 #include ".\Public\CH549.H" #include ".\Public\DEBUG.H" #include ".\TouchKey\TouchKey.H" #pragma NOAREGS UINT16 PowerValue[16]; volatile UINT16 Press_Flag = 0; UINT8C CPW_Table[16] = { 30,30,30,30, 30,30,30,30, 30,30,30,30, 30,30,30,30, }; UINT16 ABS(UINT16 a,UINT16 b) { if(a>b) { return (a-b); } else { return (b-a); } } void LED_Port_Init(void) { P2 |= (0xF<<2); //默认熄灭 P2_MOD_OC &= ~(0xF<<2); P2_DIR_PU |= (0xF<<2); } void LED_Control(UINT8 LEDx,UINT8 status) { if(LEDx>3) { return; } if(status) //点亮 { P2 &= ~(1<<(2+LEDx)); } else //熄灭 { P2 |= (1<<(2+LEDx)); } } //主函数 void main() { UINT8 ch; UINT16 value; UINT16 err; //触摸模拟变化差值 CfgFsys( ); //CH549时钟选择配置 mDelaymS(20); mInitSTDIO( ); //串口0初始化 printf("TouchKey demo start ...\n"); LED_Port_Init(); TouchKey_Init(); Press_Flag = 0; for(ch = 8; ch!=12; ch++) { PowerValue[ch] = TouchKeySelect( ch,CPW_Table[ch] ); printf("%d ",PowerValue[ch] ); } printf("\n"); while(1) { /* 按键检测 */ for(ch = 8; ch!=12; ch++) { value = TouchKeySelect( ch,CPW_Table[ch] ); err = ABS(PowerValue[ch],value); if( err > DOWM_THRESHOLD_VALUE ) { if((Press_Flag & (1<<ch)) == 0) { printf("ch %d pressed,value:%d\n",(UINT16)ch, value); /* 点灯处理 */ LED_Control(ch-8,1); } Press_Flag |= (1<<ch); } else if( err < UP_THRESHOLD_VALUE ) { if(Press_Flag & (1<<ch)) { Press_Flag &= ~(1<<ch); printf("ch %d up,value:%d\n",(UINT16)ch, value); LED_Control(ch-8,0); } } } } }   其中,这里对于GPIO的访问是直接调用ch549.h中对于sbit P2的定义访问寄存器的方法,效率很高。   3.3 预留三维运动传感器的连接接口继续开发。 4. 补充说明 4.1 开发工具,推荐的开发需要keil C51,这样可以按照手册的方法添加芯片库。用开源SDCC也可以,不过只能使用标准MCS51的外设,不推荐。 4.2 程序下载比上一次的CH554评测增加了一个板载开关ON/OFF,非常方便,避免了反复插拔USB线的可能,同时USB下载速度有了明显提高,这样从keil直接下载也没有很大区别了。这个WCHISPtools可以开放接口,作为第三方程序在keil中直接调用,进一步提高效率。   4.3 实时操作系统,采用FREERTOS需要8k左右的内存,更重要的是data数据区只有256字节,在运行中受限更明显,不宜采用。RTX tiny小于1k可以使用,不过调试使用需要更熟悉时钟,不如用轮询的polling方式更简单直接。自己直接算时钟周期,其实也效果不错。 4.4 引用范例的head文件要仔细对代码,尤其是复用的引脚和中断的配置,需要列表后使用,避免冲突。 4.5 安可信的A9G资料在参见https://wiki.ai-thinker.com/gprs/a9g/boards,CH549L的芯片原理连接如下图。 引脚配置使用时需要对照使用。   5、小结 本设计可以实现一个便携手机的功能。这个设计过程中, - 完整测试了多个适合8051的实时操作系统如RTX tiny, FreeRTOS,经测试均不适合本项目,也就没有采用。 - 在多个端口的同时使用中,多次发生重复定义和接口重复的过程,加深了对CH549L的了解。   此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-07-09
  • 回复了主题帖: 入围名单揭晓:ST传感器驱动移植大赛+骨传感器评测活动

    论坛中个人资料正确,能够在8月25日之前完成评测计划。

  • 2019-06-24
  • 回复了主题帖: 分高者胜:ST传感器闯天下之驱动移植大赛+骨振动传感器评测

    本帖最后由 北方 于 2019-6-24 13:28 编辑 (1)想要申请的板子: 运动和环境传感器开发板X-NUCLEO-IKS01A3 LIS25BA骨振动传感器的适配板相关资料 (2)预计移植的驱动:           3D加速度+3D陀螺仪    LSM6DS +MKR-1000 读取传感器数据           3D磁力计    LIS2MD + MKR-1000 读取传感器数据           3D加速度    LIS2DW12。+MKR-1000 读取传感器数据           气压传感器    LPS22HH   + MKR-1000 读取传感器数据           温度传感器    STTS751+  MKR-1000 读取传感器数据 骨导 传感器 LIS25BA + MKR-1000 读取传感器数据 并输出到串口。   再移植LSM6DS+ 沁源CH549 读取数据 (3)自拟评测项目: 因为CH549的资源有限,所以只能读取有限的外设,拟读取LSM6DS数据,并用http API上传到云端并在云端显示数据结果。 全部完成预计能达到85分。  

  • 回复了主题帖: “沁恒评估板诚芯送”活动答疑帖

    正在移植RTOS,没有历程自己搞。RTX和FreeRTOS选择测试中。 没有rtos,多外设访问就一团糟了。 申请助力。

  • 2019-06-11
  • 回复了主题帖: 【奖品已全部寄出,请注意查收】TouchGFX活动颁奖

    确认接受邮箱 yaof@chec.com.cn 谢谢  

  • 2019-06-10
  • 发表了主题帖: 精简手机系统设计

    精简手机系统设计 1、概述 精简手机系统设计是基于8051单片机和安可信A9G数据通讯模块开放的精简手机。 2、实现的功能 能够实现精简通讯和实时位置追踪功能。   3、实现的逻辑和原理 3.1 采用CH549和安可信A9G数据通讯模块 3.2 同时提供三维运动传感器的连接接口   4、小结 通过实现本设计,可以实现一个便携手机的功能。 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 回复了主题帖: 【物品已全部寄出,请注意查收】沁恒送福利,评估板诚芯送

    个人信息正确!

  • 2019-05-20
  • 发表了主题帖: 【 Linux Touch召集令】你若让出市场,为什么我不去抢地盘?

    本帖最后由 北方 于 2019-5-21 12:00 编辑 你若让出市场,为什么我不去抢地盘? 1. 概述     做一个自己的操作系统,一直是maker的大梦,现在给你机会了,你来不来?     前面的Ubuntu Touch在魅族上跑了一下就关了,因为安卓的地位太稳固了,即使搞出来也赢不了。     现在做一个自己的Linux Touch怎么样?把华为P系列玩坏怎么样?其实,钥匙就在大家的手中。     现在,开始在本坛子里征集自由的Linux Touch开发者,一起开发一个自由的不受限制的移动终端操作系统。     打算加入的,可以在下面跟帖。 2. 设计逻辑。2.1 安卓手机本身基于linux,但是在内存管理和释放上,做得不好。但是,因为积累和沉淀了巨大的APP应用程序,用户迁移难度大,也不愿意迁移。    其实,基于Linux的程序开发,现在的门槛已经降得很低了。如果用QT creator的话,菜鸟级的程序员用8个小时从零开始就能做一个类似wordpad的应用。如果用javascripte和electron的话,也是很容易搞得。更何况,对于数据控来说,直接用python和R开发是一个很开森的选择。 2.2 Linux Touch的硬件框架是基于核心MCU+DSP+GPU(对于ARM是mali),外设访问sensor,RF射频器件等等。所以,会玩树莓派就能搞手机。 2.3 Linux Touch驱动,基本上是这样的首先从rom加载uboot,然后用u-boot加载zImage等linux内核,最后用zImage加载操作系统。使用Debian或者Ubuntu都可以很好的完成这个工作。 2.4 如果,不够熟悉内核。那么,就准备好操作系统原型出来以后,开发自己的application,自己的墨迹天气,自己的记事本。 3. 开发计划 3.1 首先选定硬件开发平台,或者众创开发一个原型板。 3.2 移植embedded Debian到这个硬件平台上。 3.3 完善image,增加touch驱动、GUI驱动,Camera驱动,RF驱动,Sensor驱动,编写驱动接口并分享。 4. 然后是大家一起玩坏手机的时候。每人都有一个自己的Linux Touch。 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-05-16
  • 发表了主题帖: 【 STM32WB55 测评】7# STM32WB开发板ADC的使用和配置

    本帖最后由 北方 于 2019-5-16 11:32 编辑 1. ADC的使用和配置STM32WB55标称ADC的精度达到16位,这个是一个专用ADC芯片所能达到的标准。不过,再其文档中,只是提到能达到12位的精度。因此这里面还是有些差异的,应该是用其他方法达到的16位。 总共的19个通道,其中有3个事内部使用的,分别的hi温度,电池电压,和参考电压,对应于不同的地址。 ADC还有一个有意思的watchdog功能,可以实现ADC超过范围时的闭锁功能。低功耗ADC是STM32的传统,这里仍然保留。 2. 主要特性 - 12,10,8,6bit的设置精度, - 转换时间,0.234us --12bit,或者0.297us--12bit,更低的精度如10位可以达到0.203us。 - 数据自我矫正,这个就减少了一个需要calibration的功能。 - oversampler,这个可以取样16位,但是应该是硬件仍然12位 具体结构参考下图, 具体时钟逻辑图, 3. 例程分析 3.1 连接开发板的arduino-A2接口,对应ADC_CHANNEL_6,这样可以显示其中连接在A2的电压变化 3.2 核心代码如下, int main(void) {   uint32_t tmp_index_adc_converted_data = 0;   HAL_Init();   SystemClock_Config();   MX_TIM2_Init();   for (tmp_index_adc_converted_data = 0; tmp_index_adc_converted_data < ADC_CONVERTED_DATA_BUFFER_SIZE; tmp_index_adc_converted_data++)   {     aADCxConvertedData[tmp_index_adc_converted_data] = VAR_CONVERTED_DATA_INIT_VALUE;   }      BSP_LED_Init(LED2);      Configure_ADC();      /* Run the ADC calibration in single-ended mode */   if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED) != HAL_OK)   {     /* Calibration Error */     Error_Handler();   }   if (HAL_TIM_Base_Start(&htim2) != HAL_OK)   {     /* Counter enable error */     Error_Handler();   }      /* Start ADC group regular conversion with DMA */   if (HAL_ADC_Start_DMA(&AdcHandle,                         (uint32_t *)aADCxConvertedData,                         ADC_CONVERTED_DATA_BUFFER_SIZE                        ) != HAL_OK)   {     /* ADC conversion start error */     Error_Handler();   }        while (1)   { } } 复制代码 3.3 代码简析 首先,初始化硬件,设定系统时钟和外设设定,   HAL_Init(); SystemClock_Config(); MX_TIM2_Init(); 然后设置ADC   Configure_ADC(); 最后就是启动DMA状态下的ADC, HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED); HAL_TIM_Base_Start(&htim2); HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE); 3.4 ADC 的设置 对应ADC的设置,是在config中确定的,如下代码,这个设定了用户手册中需要设定的时钟,精度,通道,矫正方式等,虽然内容很多,但是,注解和使用很直观, AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV2;   AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;   AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;   AdcHandle.Init.ScanConvMode          = ADC_SCAN_DISABLE;              /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */   AdcHandle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;   AdcHandle.Init.LowPowerAutoWait      = DISABLE;   AdcHandle.Init.ContinuousConvMode    = ENABLE;                        /* Continuous mode to have maximum conversion speed (no delay between conversions) */   AdcHandle.Init.NbrOfConversion       = 1;                             /* Parameter discarded because sequencer is disabled */   AdcHandle.Init.DiscontinuousConvMode = DISABLE;                       /* Parameter discarded because sequencer is disabled */   AdcHandle.Init.NbrOfDiscConversion   = 1;                             /* Parameter discarded because sequencer is disabled */   AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;            /* Software start to trig the 1st conversion manually, without external event */   AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because trig of conversion by software start (no external event) */   AdcHandle.Init.DMAContinuousRequests = ENABLE;                        /* ADC with DMA transfer: continuous requests to DMA to match with DMA configured in circular mode */   AdcHandle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;   AdcHandle.Init.OversamplingMode      = DISABLE;   if (HAL_ADC_Init(&AdcHandle) != HAL_OK)   {     /* ADC initialization error */     Error_Handler();   }         /*## Configuration of ADC hierarchical scope: ##############################*/   /*## ADC group injected and channels mapped on group injected ##############*/      /* Note: ADC group injected not used and not configured in this example.    */   /*       Refer to other ADC examples using this feature.                    */   /* Note: Call of the functions below are commented because they are         */   /*       useless in this example:                                           */   /*       setting corresponding to default configuration from reset state.   */         /*## Configuration of ADC hierarchical scope: ##############################*/   /*## channels mapped on group regular         ##############################*/      /* Configuration of channel on ADCx regular group on sequencer rank 1 */   /* Note: On this STM32 serie, ADC group regular sequencer is                */   /*       fully configurable: sequencer length and each rank                 */   /*       affectation to a channel are configurable.                         */   /* Note: Considering IT occurring after each ADC conversion                 */   /*       (IT by ADC group regular end of unitary conversion),               */   /*       select sampling time and ADC clock with sufficient                 */   /*       duration to not create an overhead situation in IRQHandler.        */   sConfig.Channel      = ADCx_CHANNELa;               /* ADC channel selection */   sConfig.Rank         = ADC_REGULAR_RANK_1;          /* ADC group regular rank in which is mapped the selected ADC channel */   sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;  /* ADC channel sampling time */   sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* ADC channel differential mode */   sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* ADC channel affected to offset number */   sConfig.Offset       = 0;                           /* Parameter discarded because offset correction is disabled */   复制代码 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-05-15
  • 发表了主题帖: 【 STM32WB55 测评】6# STM32WB开发板UART的使用

    1. 再开发板的使用过程中UART是需要首先调试和测试的,因为多数情况下,开发板的数据反馈和调试,最简便的方法就是使用串口把需要的状态数据回传到计算机。2.这里首先使用的例程就是UART_printf。这个串口需要访问的是st-link的虚拟串口。直接连接电脑并编译运行就可以了。这个过程中,需要注意的是,参数设置比较不通俗,如下:115200-7-1-odd-None   - Hyperterminal configuration:     - Data Length = 7 Bits     - One Stop Bit     - Odd parity     - BaudRate = 115200 baud     - Flow control: None 这个可以理解为区分与通用的UART传输,显示在串口工具的数据就是, 核心代码如下, int main(void) {   HAL_Init();   SystemClock_Config(); PIO_Init();   MX_USART1_UART_Init();   /* USER CODE BEGIN 2 */   /* Initialize BSP Led for LED3 */   BSP_LED_Init(LED3);   /* Output a message on Hyperterminal using printf function */   printf("\n\r UART Printf Example: retarget the C library printf function to the UART\n\r");   printf("** Test finished successfully. ** \n\r");         int temp=1000;   while (1)   {     /* USER CODE END WHILE */                 HAL_Delay(temp);                 printf("*Current tick is ** %d\n\r",temp);     /* USER CODE BEGIN 3 */   } } 复制代码 3. 进行修改,增加一个定时语句,隔1000ms输出一组,结果如下, 4. 调试成功。 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-05-13
  • 发表了主题帖: 5# STM32WB开发板蓝牙例程浅析

    本帖最后由 北方 于 2019-5-13 12:49 编辑 1. ST的SDK提供了比较丰富的例程,不过双核使用的例程还没补充,应该在后面升级版补充,现在是1.0版本。2. 跳过电灯,直接从蓝牙例程开始测试。 蓝牙心率测量使用的是ble低功耗蓝牙,先下载手机app ST BLE Profile application on the android device         https://play.google.com/store/ap ... hlevalidation&hl=en     https://itunes.apple.com/fr/App/st-ble-profile/id1081331769?mt=8 然后编译例程,并下载到板卡,就可以了。 这个例程使用的是CM4内核,写入的地址如下图,正如内存分布图所示。 3. 主要的程序如下, int main(void) {   /* USER CODE BEGIN 1 */   /* USER CODE END 1 */   /* MCU Configuration--------------------------------------------------------*/   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */   HAL_Init();   /* USER CODE BEGIN Init */   Reset_Device();   Config_HSE();   /* USER CODE END Init */   /* Configure the system clock */   SystemClock_Config();   /* USER CODE BEGIN SysInit */   PeriphClock_Config();   Init_Exti(); /**< Configure the system Power Mode */   /* USER CODE END SysInit */   /* Initialize all configured peripherals */   MX_GPIO_Init();   MX_DMA_Init();   MX_RF_Init();   MX_RTC_Init();   /* USER CODE BEGIN 2 */   /* USER CODE END 2 */   APPE_Init();   /* Infinite loop */   /* USER CODE BEGIN WHILE */         while(1)         {                 SCH_Run(~0);     /* USER CODE END WHILE */     /* USER CODE BEGIN 3 */   }   /* USER CODE END 3 */ }复制代码 4.  范例解析4.1 程序启动,依次启动硬件库HAL_init(),系统时钟,中断设置,外设GPIO,DMA,RTC等常规设置,其中射频是主要的部分,在 MX_RF_Init()完成。 4.2 具体和程序有关的在App目录下的app_ble.c,dis_app.c,hrs_app.c。这3个程序就是定义了HeatRate的蓝牙service和对应的参数以及执行特征的程序。 4.3 整个程序是基于RTOS的,这些应用都在scheduler中定义并使用。 4.4 对应于程序编写,需要比较清除蓝牙原理,让rtos的时序和逻辑,然后的代码就相当简单了。后面的详细内容在后面主观分析。 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-05-10
  • 发表了主题帖: 【 STM32WB55 测评】4# STM32WB开发板STM32CubeWB的使用

    STM32WB开发板STM32CubeWB的使用 1.  STM32WB开发板STM32CubeWB是开发的套件,可以可以理解为一套开发标准库及使用的SDK。当然,如果愿意从底层开发,没有问题,不过就是要自己搞清楚底层的reg访问和设置。 总体来说,stm的开发,比较难理解的就是一个简单的命令要很多语句,如ADC的使用,其实是要从时钟选择,中断使能,通道,adc参数设定等诸多过程。对应于底层,就是简单给若干地址访问和设置位置。 使用这个SDK,可以减少查阅手册的精力,也避免出错,但是其实记忆和学习工作量更大了,完全不懂手册也是不可能的。 2. 这个里面还包括了很多第三方的库,如 - CMSIS-RTOS implementation with FreeRTOS™ -  Full USB Device stack - STMTouch, touch sensing library solution - STM32_WPAN,支持 Bluetooth® Low Energy (BLE) 5.0, 802.15.4OpenThread certified stacks and 802-15-4 MAC layer. - FAT file system based on open source FatFS solution 如下图, 可以看到,代码驱动和LL底层代码是可以都支撑HAL的。 对应本开发板套件支持的芯片型号为, 在文件夹中的组织如下, 3. 具体使用就比较简单了,进入对应的example文件夹,选择工程文件,打开就可以,然后编译。作为大厂,都是可以简单通过编译并的 3.1 开发可使用HAL的模式,创建工程后,需要添加需要的中间件midleware 首先需要定义firmware元件,要复制并修改xxx_conf_template.h文件, 然后启动HAL_Init(),设定系统时钟,初始化外围设备, 最后才能开始开发自己的项目。 3.2 也可以从LL层开始开发,一般是推荐移植现有的范例程序, 然后重点修改,stm32wbxx_it.h,stm32wbxx_it.c,以及main.c程序。 4. 如何写入无线协处理库 该库位于 Projects\STM32WB_Copro_Wireless_Binaries 需要安装和启动STM32CubeProgrammer,这个是CLI的命令行模式程序。 然后设定boot loader模式,设定BOOT0在Vdd,在nucleo上市连接CN7.5和CN7.7,用USB_user和J2供电,不用st-link,对doggle直接连接usb口,主要SW2切换到BOOT0的位置 以下是执行过程, 删除现有无线栈, STM32_Programmer_CLI.exe -c port=usb1 -fwdelete 写入无线栈, STM32_Programmer_CLI.exe -c port=usb1 -fwupgrade Wireless_Coprocessor_Binary] [Install address] firstinstall=1 对应不同的栈需要选择对应的写入地址,参见Release_Notes.html 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处 写栈成功后,要切换到正常的模式,不能在boot loader模式运行程序。 5.一些问题。 使用HAL和LL编程的区别是,一个更抽象,一个更又效率,但是对于用户手册和硬件要足够理解。而且可以同时使用,仅仅注意初始化的设置要准确。LL比HAL覆盖更多的API,如SCB和Sys Tick就只在LL中存在。

  • 2019-05-09
  • 发表了主题帖: 【 STM32WB55 测评】3# STM32WB开发板的boot顺序和radio模块

    本帖最后由 北方 于 2019-5-9 14:52 编辑 1. STM32WB开发板的boot顺序需要从组织结构的角度来分析。明显,这个比GD32要复杂得多。2. 首先是这么多信息源,如何交互,这里是用了matrix来组织的。NXP LPC54114使用了不同的组织结构。 内存分配时4G地址,8段,每段512M。 3. 启动顺序由下面的引脚定义, 分别从主存,系统内存和SRAM中启动,启动访问别名地址都是0x080000,但是物理地址分别是0x000000, 0x1FFF000,0x200000. 这个也是,可以把firmware写在不同内存区域需要了解的。用keil是可以选择写入内存起始地址的,这样就可以更好运用编程工具。 CPU1,可以从用户选择的地址启动,同时st出厂时也设定了嵌入式boot loader,可以通过USART和I2C,SPI进行flash 写入。 CPU2,启动需要在CPU1设定C2BOOT为之后才能启动。 4. Flash的写入 Flash可以用ICP或者IAP的方式写入,这里就存在很大的访问失败可能性,多核系统,建议用semaphores的方式写入,避免这样的冲突。 这意味着如果,变砖不要紧,只要知道代码的起始位置就可以重置flash。 程序写入分为标准写入和快速写入两种方式, 5. 关于radio的无线部分,说明文件很少,只是说明是由cpu2来控制底层代码的,通过多核的mailbox消息系统实现。这样,也比单核的更精简,用户可以专心在cpu1上编写应用程序,从逻辑上,很像用一个MCU来控制的蓝牙模块SoC。这个也是一个简便的射频实现方式。 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 回复了主题帖: 【STM32WB55 测评】+USBDongle变砖记

    wb的库提供了doggle的源码,可以自己定制和编译,应该可以写入的,不用急。我正在研究,也试一下写入自定义的bin,看是成功还是变砖。

  • 2019-05-08
  • 发表了主题帖: 【 STM32WB55 测评】2# STM32WB开发板的使用

    本帖最后由 北方 于 2019-5-8 15:51 编辑 1. STM32WB支持蓝牙5.0和802.15.4双协议栈,这次套件包括两部分,一个nucleo作为server,另一个doggle作为client。 2. nucleo板及其资源如下, 3. 另一个doggle的资源如下, 4. 出厂配置的范例就是一个作为广播的server,另一个作为client的群工作方式,可以互相控制绿色LED的亮灭。 4.1 首先给nucleo板通过st-link的usb口加电,led开始闪烁。这时就自动进入server模式,开始广播信号。 4.2 然后直接通过usb-A给doggle加电,进入client模式,按下SW1,进入server时自动连接模式。 4.3 建立连接后,led的闪烁频率都发生变化, 4.4 在nucleo板上按SW1可以控制client的led亮灭,同时控制SW2可以控制连接的间隔。 5. 快速进入开发状态,当然是直接登陆mbed网络,可以快速开始开发的。不过应该还没有蓝牙的配置,应该只是对应于M0内核的模式,不适合比较全面的开发。 6. 便于开发,提供了参考范例程序STM32CubeWB Firmware Examples for STM32WBxx Series ,并提供了参考的内核架构, 后续可以围绕这个开始项目开发。 此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-05-05
  • 回复了主题帖: 免费送:Aim TTi电流测量探头、专业信号发生器,还有京东卡等小礼品等你来

    这个是要求两个一起评测还是只评测其中的一个

最近访客

< 1/6 >

统计信息

已有116人来访过

  • 芯币:388
  • 好友:1
  • 主题:74
  • 回复:78
  • 课时:--
  • 资源:--

留言

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


现在还没有留言