STM Урок 49. HAL. Магнитометр LSM303DLHC. Часть 1

 Урок 49. HAL. Магнитометр LSM303DLHC

 

Часть 1

 

Сегодня мы продолжим тему датчиков с использованием технологии MEMS и вернёмся к датчику, который мы уже частично рассматривали 10 уроков назад – LSM303DLHC.

Повторюсь, что данный датчик установлен на плате STM32F3Discovery. И изучим мы сегодня его вторую часть – магнитометр. Магнитометр – это такой датчик, который способен реагировать и измерять такую величину, как магнитная индукция, которая измеряется в Гауссах (система СГС). Также в официальной таблице СИ магнитная индукция измеряется в Теслах. 1 Гаусс равен 100 мкТл или 1 Тесла равна 10000 Гауссов.

Технические характеристики данного описаны в даташите на него, ссылку на который я повторю в конце статьи. Основные характеристики, которые нам понадобятся – это те, что он также 16-битный, правда для показаний биты используются не все – только 12 бит и измерения свои он интерпретирует в регистрах в диапазоне от -2048 до +2047

 

image00

 

Также нам нужны следующие характеристики:

интерфейс для снятия показаний – I2C;

Диапазон показаний ±1.3 / ±1.9 / ±2.5 / ±4.0 / ±4.7 / ±5.6 / ±8.1 gauss;

Дискретность 1 Гаусса или количество градаций в 1 Гауссе зависит от установленного диапазона показаний, а также от осей и находится в пределах от 205 до 1100

 

image02

 

С остальными характеристиками, тонкостями, магнитометра мы познакомимся в ходе его программирования.

Проект мы создадим из предыдущего проекта для этого датчики – из проекта Accel и назовём его Mag

Запустим проект в Cube MX.

 

 

Внесём изменение следующее – прибавим скорость шины USART2

 

image01

 

Сгенерируем код, откроем проект, настроим программатор на авторезет, как обычно. Подключим файл lsm303dlhc.c. Скомпилируем проект.

В файле main.c в бесконечном цикле пока закомментируем вызов функции

 

//Accel_ReadAcc();

 

В файле lsm303dlhc.h удалим полностью всё и вставим готовый подготовленный код с новыми макросами для магнитометра и с исправленными прототипами функций

 

#ifndef LSM303DLHC_H_

#define LSM303DLHC_H_

 

#include «stm32f3xx_hal.h»

#include <string.h>

//————————————————

#define ABS(x)         (x < 0) ? (-x) : x

//————————————————

#define LD_PORT GPIOE

#define LD3 GPIO_PIN_9 //RED1

#define LD4 GPIO_PIN_8 //BLUE1

#define LD5 GPIO_PIN_10 //ORANGE1

#define LD6 GPIO_PIN_15 //GREEN1

#define LD7 GPIO_PIN_11 //GREEN2

#define LD8 GPIO_PIN_14 //ORANGE2

#define LD9 GPIO_PIN_12 //BLUE2

#define LD10 GPIO_PIN_13 //RED2

//————————————————-

#define ACC_I2C_ADDRESS                      0x32

#define MAG_I2C_ADDRESS                      0x3C

//————————————————

//————————————————-

#define LSM303DLHC_CTRL_REG1_A               0x20  /* Control register 1 acceleration */

#define LSM303DLHC_CTRL_REG2_A               0x21  /* Control register 2 acceleration */

#define LSM303DLHC_CTRL_REG3_A               0x22  /* Control register 3 acceleration */

#define LSM303DLHC_CTRL_REG4_A               0x23  /* Control register 4 acceleration */

#define LSM303DLHC_CTRL_REG5_A               0x24  /* Control register 5 acceleration */

#define LSM303DLHC_CRA_REG_M                 0x00  /* Control register A magnetic field */

#define LSM303DLHC_CRB_REG_M                 0x01  /* Control register B magnetic field */

#define LSM303DLHC_MR_REG_M                  0x02  /* Control register MR magnetic field */

//————————————————

#define LD3_ON HAL_GPIO_WritePin(LD_PORT, LD3, GPIO_PIN_SET) //RED1

#define LD4_ON HAL_GPIO_WritePin(LD_PORT, LD4, GPIO_PIN_SET) //BLUE1

#define LD5_ON HAL_GPIO_WritePin(LD_PORT, LD5, GPIO_PIN_SET) //ORANGE1

#define LD6_ON HAL_GPIO_WritePin(LD_PORT, LD6, GPIO_PIN_SET) //GREEN1

#define LD7_ON HAL_GPIO_WritePin(LD_PORT, LD7, GPIO_PIN_SET) //GREEN2

#define LD8_ON HAL_GPIO_WritePin(LD_PORT, LD8, GPIO_PIN_SET) //ORANGE2

#define LD9_ON HAL_GPIO_WritePin(LD_PORT, LD9, GPIO_PIN_SET) //BLUE2

#define LD10_ON HAL_GPIO_WritePin(LD_PORT, LD10, GPIO_PIN_SET) //RED2

#define LD3_OFF HAL_GPIO_WritePin(LD_PORT, LD3, GPIO_PIN_RESET) //RED1

#define LD4_OFF HAL_GPIO_WritePin(LD_PORT, LD4, GPIO_PIN_RESET) //BLUE1

#define LD5_OFF HAL_GPIO_WritePin(LD_PORT, LD5, GPIO_PIN_RESET) //ORANGE1

#define LD6_OFF HAL_GPIO_WritePin(LD_PORT, LD6, GPIO_PIN_RESET) //GREEN1

#define LD7_OFF HAL_GPIO_WritePin(LD_PORT, LD7, GPIO_PIN_RESET) //GREEN2

#define LD8_OFF HAL_GPIO_WritePin(LD_PORT, LD8, GPIO_PIN_RESET) //ORANGE2

#define LD9_OFF HAL_GPIO_WritePin(LD_PORT, LD9, GPIO_PIN_RESET) //BLUE2

#define LD10_OFF HAL_GPIO_WritePin(LD_PORT, LD10, GPIO_PIN_RESET) //RED2

//————————————————

#define LSM303DLHC_NORMAL_MODE            ((uint8_t)0x00)

#define LSM303DLHC_LOWPOWER_MODE          ((uint8_t)0x08)

//————————————————-

#define LSM303DLHC_ODR_1_HZ                ((uint8_t)0x10)  /*!< Output Data Rate = 1 Hz */

#define LSM303DLHC_ODR_10_HZ               ((uint8_t)0x20)  /*!< Output Data Rate = 10 Hz */

#define LSM303DLHC_ODR_25_HZ               ((uint8_t)0x30)  /*!< Output Data Rate = 25 Hz */

#define LSM303DLHC_ODR_50_HZ               ((uint8_t)0x40)  /*!< Output Data Rate = 50 Hz */

#define LSM303DLHC_ODR_100_HZ              ((uint8_t)0x50)  /*!< Output Data Rate = 100 Hz */

#define LSM303DLHC_ODR_200_HZ              ((uint8_t)0x60)  /*!< Output Data Rate = 200 Hz */

#define LSM303DLHC_ODR_400_HZ              ((uint8_t)0x70)  /*!< Output Data Rate = 400 Hz */

#define LSM303DLHC_ODR_1620_HZ_LP          ((uint8_t)0x80)  /*!< Output Data Rate = 1620 Hz only in Low Power Mode */

#define LSM303DLHC_ODR_1344_HZ             ((uint8_t)0x90)  /*!< Output Data Rate = 1344 Hz in Normal mode and 5376 Hz*/

//————————————————-

#define LSM303DLHC_X_ENABLE                ((uint8_t)0x01)

#define LSM303DLHC_Y_ENABLE                ((uint8_t)0x02)

#define LSM303DLHC_Z_ENABLE                ((uint8_t)0x04)

#define LSM303DLHC_AXES_ENABLE             ((uint8_t)0x07)

#define LSM303DLHC_AXES_DISABLE            ((uint8_t)0x00)

//————————————————-

#define LSM303DLHC_HR_ENABLE               ((uint8_t)0x08)

#define LSM303DLHC_HR_DISABLE              ((uint8_t)0x00)

//————————————————-

#define LSM303DLHC_FULLSCALE_2G            ((uint8_t)0x00)  /*!< ±2 g */

#define LSM303DLHC_FULLSCALE_4G            ((uint8_t)0x10)  /*!< ±4 g */

#define LSM303DLHC_FULLSCALE_8G            ((uint8_t)0x20)  /*!< ±8 g */

#define LSM303DLHC_FULLSCALE_16G           ((uint8_t)0x30)  /*!< ±16 g */

//————————————————-

#define LSM303DLHC_BlockUpdate_Continous   ((uint8_t)0x00) /*!< Continuos Update */

#define LSM303DLHC_BlockUpdate_Single      ((uint8_t)0x80) /*!< Single Update: output registers not updated until MSB and LSB reading */

//————————————————-

#define LSM303DLHC_BLE_LSB                 ((uint8_t)0x00) /*!< Little Endian: data LSB @ lower address */

#define LSM303DLHC_BLE_MSB                 ((uint8_t)0x40) /*!< Big Endian: data MSB @ lower address */

//————————————————-

#define LSM303DLHC_HPM_NORMAL_MODE_RES     ((uint8_t)0x00)

#define LSM303DLHC_HPM_REF_SIGNAL          ((uint8_t)0x40)

#define LSM303DLHC_HPM_NORMAL_MODE         ((uint8_t)0x80)

#define LSM303DLHC_HPM_AUTORESET_INT       ((uint8_t)0xC0)

//————————————————-

#define LSM303DLHC_HPFCF_8                 ((uint8_t)0x00)

#define LSM303DLHC_HPFCF_16                ((uint8_t)0x10)

#define LSM303DLHC_HPFCF_32                ((uint8_t)0x20)

#define LSM303DLHC_HPFCF_64                ((uint8_t)0x30)

//————————————————-

#define LSM303DLHC_HPF_AOI1_DISABLE        ((uint8_t)0x00)

#define LSM303DLHC_HPF_AOI1_ENABLE              ((uint8_t)0x01)

//————————————————-

#define LSM303DLHC_HPF_AOI2_DISABLE        ((uint8_t)0x00)

#define LSM303DLHC_HPF_AOI2_ENABLE         ((uint8_t)0x02)

//————————————————-

#define LSM303DLHC_ACC_SENSITIVITY_2G     ((uint8_t)1)  /*!< accelerometer sensitivity with 2 g full scale [mg/LSB] */

#define LSM303DLHC_ACC_SENSITIVITY_4G     ((uint8_t)2)  /*!< accelerometer sensitivity with 4 g full scale [mg/LSB] */

#define LSM303DLHC_ACC_SENSITIVITY_8G     ((uint8_t)4)  /*!< accelerometer sensitivity with 8 g full scale [mg/LSB] */

#define LSM303DLHC_ACC_SENSITIVITY_16G    ((uint8_t)12) /*!< accelerometer sensitivity with 12 g full scale [mg/LSB] */

//————————————————

#define LSM303DLHC_OUT_X_L_A                 0x28  /* Output Register X acceleration */

#define LSM303DLHC_OUT_X_H_A                 0x29  /* Output Register X acceleration */

#define LSM303DLHC_OUT_Y_L_A                 0x2A  /* Output Register Y acceleration */

#define LSM303DLHC_OUT_Y_H_A                 0x2B  /* Output Register Y acceleration */

#define LSM303DLHC_OUT_Z_L_A                 0x2C  /* Output Register Z acceleration */

#define LSM303DLHC_OUT_Z_H_A                 0x2D  /* Output Register Z acceleration */

//————————————————

#define LSM303DLHC_OUT_X_H_M                 0x03  /* Output Register X magnetic field */

#define LSM303DLHC_OUT_X_L_M                 0x04  /* Output Register X magnetic field */

#define LSM303DLHC_OUT_Z_H_M                 0x05  /* Output Register Z magnetic field */

#define LSM303DLHC_OUT_Z_L_M                 0x06  /* Output Register Z magnetic field */

#define LSM303DLHC_OUT_Y_H_M                 0x07  /* Output Register Y magnetic field */

#define LSM303DLHC_OUT_Y_L_M                 0x08  /* Output Register Y magnetic field */

//————————————————

#define LSM303DLHC_TEMPSENSOR_ENABLE         ((uint8_t) 0x80)   /*!< Temp sensor Enable */

#define LSM303DLHC_TEMPSENSOR_DISABLE        ((uint8_t) 0x00)   /*!< Temp sensor Disable */

//————————————————

#define LSM303DLHC_ODR_0_75_HZ              ((uint8_t) 0x00)  /*!< Output Data Rate = 0.75 Hz */

#define LSM303DLHC_ODR_1_5_HZ               ((uint8_t) 0x04)  /*!< Output Data Rate = 1.5 Hz */

#define LSM303DLHC_ODR_3_0_HZ               ((uint8_t) 0x08)  /*!< Output Data Rate = 3 Hz */

#define LSM303DLHC_ODR_7_5_HZ               ((uint8_t) 0x0C)  /*!< Output Data Rate = 7.5 Hz */

#define LSM303DLHC_ODR_15_HZ                ((uint8_t) 0x10)  /*!< Output Data Rate = 15 Hz */

#define LSM303DLHC_ODR_30_HZ                ((uint8_t) 0x14)  /*!< Output Data Rate = 30 Hz */

#define LSM303DLHC_ODR_75_HZ                ((uint8_t) 0x18)  /*!< Output Data Rate = 75 Hz */

#define LSM303DLHC_ODR_220_HZ               ((uint8_t) 0x1C)  /*!< Output Data Rate = 220 Hz */

//————————————————

#define  LSM303DLHC_FS_1_3_GA               ((uint8_t) 0x20)  /*!< Full scale = ±1.3 Gauss */

#define  LSM303DLHC_FS_1_9_GA               ((uint8_t) 0x40)  /*!< Full scale = ±1.9 Gauss */

#define  LSM303DLHC_FS_2_5_GA               ((uint8_t) 0x60)  /*!< Full scale = ±2.5 Gauss */

#define  LSM303DLHC_FS_4_0_GA               ((uint8_t) 0x80)  /*!< Full scale = ±4.0 Gauss */

#define  LSM303DLHC_FS_4_7_GA               ((uint8_t) 0xA0)  /*!< Full scale = ±4.7 Gauss */

#define  LSM303DLHC_FS_5_6_GA               ((uint8_t) 0xC0)  /*!< Full scale = ±5.6 Gauss */

#define  LSM303DLHC_FS_8_1_GA               ((uint8_t) 0xE0)  /*!< Full scale = ±8.1 Gauss */

//————————————————

#define LSM303DLHC_CONTINUOS_CONVERSION      ((uint8_t) 0x00)   /*!< Continuous-Conversion Mode */

#define LSM303DLHC_SINGLE_CONVERSION         ((uint8_t) 0x01)   /*!< Single-Conversion Mode */

#define LSM303DLHC_SLEEP                     ((uint8_t) 0x02)   /*!< Sleep Mode */                      

//————————————————

void AccelMag_Ini(void);

void AccelMag_Read(void);

//————————————————

#endif /* LSM303DLHC_H_ */

 

 

Исправим имя функции инициализации датчика на более универсальное также в файлах main.c и lsm303dlhc.c

 

  /* USER CODE BEGIN 2 */

        AccelMag_Ini();

  /* USER CODE END 2 */

//———————————————

void AccelMag_Ini(void)

{

 

Закомментируем в коде реализации данной функции строки, связанные с инициализацией акселерометра кроме считывания идентификатора, ибо данная опция у датчика универсальна

 

        else Error();

//        ctrl|=(LSM303DLHC_NORMAL_MODE|LSM303DLHC_ODR_50_HZ|LSM303DLHC_AXES_ENABLE);

//        ctrl|=((LSM303DLHC_BlockUpdate_Continous|LSM303DLHC_BLE_LSB|LSM303DLHC_HR_ENABLE)<<8);

//        AccInit(ctrl);

//        ctrl=(uint8_t)(LSM303DLHC_HPM_NORMAL_MODE|LSM303DLHC_HPFCF_16|\

//                                                                 LSM303DLHC_HPF_AOI1_DISABLE|LSM303DLHC_HPF_AOI2_DISABLE);

//        Accel_AccFilter(ctrl);

        LD7_ON;

 

Добавим функцию MagInit, скопировав полностью и исправив подобную функцию для акселерометра (AccInit). Входящий аргумент будет уже 32-битный, т.к. использовать будем 3 разных регистра и 16-битного нам не хватит

 

//———————————————

void MagInit(uint32_t InitStruct)

{

        uint8_t ctrl = 0x00;

        ctrl = (uint8_t) InitStruct;

        Accel_IO_Write(MAG_I2C_ADDRESS,LSM303DLHC_CRA_REG_M,ctrl);

        ctrl = (uint8_t)(InitStruct>>8);

        Accel_IO_Write(MAG_I2C_ADDRESS, LSM303DLHC_CRB_REG_M,ctrl);

        ctrl = (uint8_t)(InitStruct>>16);

        Accel_IO_Write(MAG_I2C_ADDRESS, LSM303DLHC_MR_REG_M,ctrl);

}

//———————————————

 

О регистрах и настройках их битов мы узнаем несколько позже, когда будем заносить в них значения перед вызовом данной функции. Если Вы заметили, то адрес I2C для общения с магнитометром у нас уже будет другой

 

image04

 

Добавим код настройки регистров инициализации в общую функцию инициализации, для этого вначале добавим ещё одну переменную для возможности передачи 32-битного значения настроек

 

        uint16_t ctrl = 0x0000;

        uint32_t ctrl32 = 0x00000000;

//        Accel_AccFilter(ctrl);

        ctrl32|=(LSM303DLHC_TEMPSENSOR_DISABLE|LSM303DLHC_ODR_220_HZ);

        ctrl32|=LSM303DLHC_FS_4_0_GA<<8;

        ctrl32|=LSM303DLHC_CONTINUOS_CONVERSION<<16;

        MagInit(ctrl32);

        LD7_ON;

 

А вот теперь и познакомимся вкратце, что у нас творится с настройками битов регистров управления.

В регистре CRA_REG_M (00h) мы отключим датчик температуры и настроим частоту считывания данных с осей магнитометра

 

image03

image06

image05

 

В регистре CRB_REG_M (01h) настроим предел измерений магнитометра

 

image08

image07

 

В регистре MR_REG_M (02h) включим непрерывный режим преобразования

 

image11

image09

 

В следующей части нашего занятия мы напишем функцию чтения данных датчика и попытаемся увидеть показания на ПК сначала в терминальной программе, а затем в двух программах визуализации.

 

 

 

Техническая документация на датчик

Программа Hyper Terminal

Программа NS Port Monitor

Программа NS Mag Visual

 

 

Купить отладочную плату можно здесь STM32F3-DISCOVERY

 

 

Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)

STM32 HAL. Магнитометр LSM303DLHC

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

STM32 HAL. Магнитометр LSM303DLHC

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*