Урок 51.
Часть 1
Магнитометр LIS3MDL
Сегодня мы продолжаем работу с датчиками, которые измеряют магнитную индукцию и называются магнитометрами. Мы рассматриваем и изучаем датчик-магнитометр, установленный на плате расширения X-NUCLEO-IKS01A1, предназначенной для работы с отладочной платой Nucleo. Мы будем подключать данную оценочную плату к плате Nucleo STM32F401RE. Выполнен данный датчик также с использованием технологии MEMS.
Этот магнитометр также наряду с интерфейсом I2C может подключаться и с использованием интерфейса SPI. Но мы будем использовать подключение именно по I2C, так как именно такое подключение имеет место в оценочной плате X-NUCLEO-IKS01A.
Датчик имеет следующие технические характеристики:
Диапазон показаний ±4/ ±8/ ±12/ ±16 gauss;
Чувствительность 1711 – 6842 LSB/gauss;
Среднеквадратичное значение уровня шума (RMS noise) при диапазоне ±12: 3.2 – 4.1 mgauss;
Отклонение от нуля ±1 mgauss при установке диапазона ±4 gauss.
Частота измерений 0,625 – 80 Гц.
С некоторыми остальными показателями, регистрами, значениями и другими тонкостями гироскопа мы познакомимся в ходе его программирования.
Проект мы создадим из готового проекта, в котором мы работали с гироскопом, установленном на этой же плате расширения – из проекта Gyro_LSM6DS0, только назовём мы данный проект теперь соответственно Mag_LIS3MDL.
Файлы lsm6ds0.c и lsm6ds0.h соответственно переименуем в lis3mdl.c и lis3mdl.h.
Запустим проект Cube MX. Проверим, что скорость USART у нас выставлена 230400 bps. Если не такая, то установим именно такую
Убедимся в том, что прерывания от USART у нас включены
Также нам нужен будет таймер, так как вместо бесконечного цикла мы будем использовать его. Задействовав таймер, мы сразу решим две проблемы. Во-первых, не нужно будет использовать задержку в процедуре считывания и обработки, что исключит простаивание и невозможность использования ресурсов МК. Во-вторых, теперь считывать оси мы будем только тогда, когда того захочет программа визуализации, тем самым исключим принятие одного и того же буфера на стороне ПК. Включим, например, TIM1
Таймер сконфигурируем следующим образом
Сгенерируем проект, откроем его. Настроим программатор на авторезет. Добавим файл lis3mdl.c. Скомпилируем проект.
По причине переименования файлов у нас будут ошибки. Для устранения данных ошибок мы исправим подключение заголовочных файлов в main.c и в lis3mdl.с
#include «stm32f4xx_hal.h»
#include «lis3mdl.h»
//——————————————-
В бесконечном цикле пока закомментируем код вызова функции считывания данных и отправки их в USART
/* USER CODE BEGIN 3 */
//AccelGyro_Read();
}
В файле lis3mdl.h удалим весь код и скопируем туда для экономии драгоценного времени заранее подготовленный код со всеми макросами и переменными из файла macro.txt
#ifndef LIS3MDL_H_
#define LIS3MDL_H_
#include «stm32f4xx_hal.h»
#include <string.h>
//————————————————
#define ABS(x) (x < 0) ? (-x) : x
//————————————————
#define LD2_Pin GPIO_PIN_5
#define LD2_GPIO_Port GPIOA
#define LD2_ON HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET) //GREEN
#define LD2_OFF HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET)
//————————————————
#define MAG_I2C_ADDRESS 0x3C
//————————————————
#define LIS3MDL_MAG_WHO_AM_I_REG 0X0F
#define LIS3MDL_MAG_CTRL_REG1 0X20
#define LIS3MDL_MAG_CTRL_REG2 0X21
#define LIS3MDL_MAG_CTRL_REG3 0X22
#define LIS3MDL_MAG_CTRL_REG5 0X24
//————————————————
#define LIS3MDL_MAG_WHO_AM_I 0x3D
//————————————————
#define LIS3MDL_MAG_MD_CONTINUOUS 0x00
#define LIS3MDL_MAG_MD_SINGLE 0x01
#define LIS3MDL_MAG_MD_POWER_DOWN 0x02
#define LIS3MDL_MAG_MD_POWER_DOWN_AUTO 0x0
#define LIS3MDL_MAG_MD_MASK 0x03
//————————————————
#define LIS3MDL_MAG_BDU_DISABLE 0x00
#define LIS3MDL_MAG_BDU_ENABLE 0x40
#define LIS3MDL_MAG_BDU_MASK 0x40
//————————————————
#define LIS3MDL_MAG_DO_0_625Hz 0x00
#define LIS3MDL_MAG_DO_1_25Hz 0x04
#define LIS3MDL_MAG_DO_2_5Hz 0x08
#define LIS3MDL_MAG_DO_5Hz 0x0C
#define LIS3MDL_MAG_DO_10Hz 0x10
#define LIS3MDL_MAG_DO_20Hz 0x14
#define LIS3MDL_MAG_DO_40Hz 0x18
#define LIS3MDL_MAG_DO_80Hz 0x1C
#define LIS3MDL_MAG_DO_MASK 0x1C
//————————————————
#define LIS3MDL_MAG_FS_4Ga 0x00
#define LIS3MDL_MAG_FS_8Ga 0x20
#define LIS3MDL_MAG_FS_12Ga 0x40
#define LIS3MDL_MAG_FS_16Ga 0x60
#define LIS3MDL_MAG_FS_MASK 0x60
//————————————————
#define LIS3MDL_MAG_OM_LOW_POWER 0x00
#define LIS3MDL_MAG_OM_MEDIUM 0x20
#define LIS3MDL_MAG_OM_HIGH 0x40
#define LIS3MDL_MAG_OM_ULTRA_HIGH 0x60
#define LIS3MDL_MAG_OM_MASK 0x60
//————————————————
#define LIS3MDL_MAG_TEMP_EN_DISABLE 0x00
#define LIS3MDL_MAG_TEMP_EN_ENABLE 0x80
#define LIS3MDL_MAG_TEMP_EN_MASK 0x80
//————————————————
#define LIS3MDL_MAG_OUTX_L 0X28
#define LIS3MDL_MAG_OUTX_H 0X29
#define LIS3MDL_MAG_OUTY_L 0X2A
#define LIS3MDL_MAG_OUTY_H 0X2B
#define LIS3MDL_MAG_OUTZ_L 0X2C
#define LIS3MDL_MAG_OUTZ_H 0X2D
//————————————————
void Mag_Ini(void);
void Mag_Read(void);
//————————————————
#endif /* LIS3MDL_H_ */
Функцию Accel_Gyro_Ini переименуем в Mag_Ini в файлах main.c и в lis3mdl.с
//———————————————
void Mag_Ini(void)
{
Mag_Ini();
/* USER CODE END 2 */
Следующая задача у нас – написать код инициализации датчика. И, как всегда, по сложившейся традиции, раз уж у нас подключение именно по шине I2C, начинаем мы её, конечно же, со считывания идентификатора микросхемы.
Исходя из подключения микросхемы, адрес мы выбираем 0x3C
—
Регистр для чтения идентификатора используем WHO_AM_I (0Fh)
В данной таблице мы также видим, переведя двоичный код в шестнадцатеричный, что идентификатор должен быть равен именно 0x3D.
Функцию Accel_ReadID переименуем в Mag_ReadID и в реализации, и в вызове
//———————————————
uint8_t Mag_ReadID(void)
{
HAL_Delay(1000);
if(Mag_ReadID()==0x68) LD2_ON;
Аналогичным образом поступим и с функциями Accel_IO_Read и Accel_IO_Write
//———————————————
uint8_t Mag_IO_Read(uint16_t DeviceAddr, uint8_t RegisterAddr)
{
//———————————————
void Mag_IO_Write(uint16_t DeviceAddr, uint8_t RegisterAddr, uint8_t Value)
{
Также подправим код в функции чтения идентификатора
//———————————————
uint8_t Mag_ReadID(void)
{
uint8_t ctrl = 0x00;
ctrl = Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_WHO_AM_I_REG);
return ctrl;
}
Исправим код в главной функции инициализации
HAL_Delay(1000);
if(Mag_ReadID()==LIS3MDL_MAG_WHO_AM_I) LD2_ON;
В функциях, которые мы пока не используем, закомментируем весь код, облачив его вот в такие теги /* */.
Скомпилируем код, прошьём контроллер и проверим результат нашей работы. Зелёный светодиод должен загореться
В следующей части нашего занятия мы продолжим и закончим писать инициализацию датчика и начнём писать код для получения данных с его осей.
Предыдущий урок Программирование МК STM32 Следующая часть
Техническая документация на датчик
Отладочную плату можно приобрести здесь Nucleo STM32F401RE
Оценочную плату можно приобрести здесь STM32 X-NUCLEO-IKS01A1
Смотреть ВИДЕОУРОК
Добавить комментарий