Урок 42
Часть 2
Подключаем акселерометр LSM6DS0
В предыдущей части нашего урока мы ознакомились с документацией на датчик, создали для него проект, добавили некоторые макросы и настроили библиотечные файлы, также написали функцию считывания идентификатора акселерометра и начали писать функцию инициализации датчика.
Продолжим писать код в функции AccInit
uint8_t value=0;
//установим бит BDU
value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG8);
value &= ~LSM6DS0_ACC_GYRO_BDU_MASK;
value |= LSM6DS0_ACC_GYRO_BDU_ENABLE;
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG8, value);//пока выключим датчик (ODR_XL = 000)
В данном регистре мы включим бит 6 – BDU, который отвечает за защиту старшего байта данных от изменения в том случае если еще не считан младший
Дальше напишем следующий код
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG8, value);
//пока выключим датчик (ODR_XL = 000)
value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL);
value &= ~LSM6DS0_ACC_GYRO_ODR_XL_MASK;
value |= LSM6DS0_ACC_GYRO_ODR_XL_POWER_DOWN;
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);
В данном регистре мы сначала включим режим пониженного энергопотребления.
Продолжим работу с управляющими битами дальше
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);
//Full scale selection 2G
value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL);
value &= ~LSM6DS0_ACC_GYRO_FS_XL_MASK;
value |= LSM6DS0_ACC_GYRO_FS_XL_2g;
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);
Работаем с тем же регистром 6, только настраиваем мы уже биты, отвечающие за максимальное ускорение. Выставим, как обычно 2g. Для этого нам не нужно включать 3 и 4 биты регистра.
Продолжим дальше
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);
//Включим оси
value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG5_XL);
value &= ~(LSM6DS0_ACC_GYRO_XEN_XL_MASK |
LSM6DS0_ACC_GYRO_YEN_XL_MASK |
LSM6DS0_ACC_GYRO_ZEN_XL_MASK);
value |= (LSM6DS0_ACC_GYRO_XEN_XL_ENABLE |
LSM6DS0_ACC_GYRO_YEN_XL_ENABLE |
LSM6DS0_ACC_GYRO_ZEN_XL_ENABLE);
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG5_XL, value);
Работаем мы теперь с регистром 5
Здесь мы включим использование всех трёх осей акселерометра
Продолжим дальше писать функцию инициализации
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG5_XL, value);
//Включим Data Rate 119 Гц
value = Accel_IO_Read(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL);
value &= ~LSM6DS0_ACC_GYRO_ODR_XL_MASK;
value |= LSM6DS0_ACC_GYRO_ODR_XL_119Hz;
Accel_IO_Write(0xD6, LSM6DS0_ACC_GYRO_CTRL_REG6_XL, value);
}
Здесь мы снова возвращаемся к регистру 6 и включаем скорость (частоту измерений) 119 Гц
Функция инициализации закончена. Теперь в основной функции перед вызовом функции AccInit потушим светодиод, а после вызова зажжем, чтобы убедиться что у нас нигде ничего не подвисло.
else Error();
LD2_OFF;
AccInit(ctrl);
LD2_ON;
Соберем код, прошьём МК и посмотрим результат.
Теперь будем писать код в функцию считывания данных с датчика Accel_GetXYZ
uint8_t i=0;
buffer[0] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_X_L_XL);
buffer[1] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_X_H_XL);
buffer[2] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_Y_L_XL);
buffer[3] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_Y_H_XL);
buffer[4] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_Z_L_XL);
buffer[5] = Accel_IO_Read(0xD6,LSM6DS0_ACC_GYRO_OUT_Z_H_XL);
Здесь мы считываем данные из регистров 0X28 — 0X2D, отвечающие за хранение считанных ускорений с осей – соответственно младших и старших байтов.
Затем в цикле занесем считанные байты уже двухбайтовыми величинами в соответствующий буфер
for(i=0;i<3;i++)
{
pData[i] = ((int16_t)((uint16_t)buffer[2*i+1]<<8)+buffer[2*i]);
}
Перейдем в функцию Accel_ReadAcc, которую мы затем вызовем в бесконечном цикле в main(). Закомментируем пока там строки, связанные с USART и зажжем светодиод в случае превышения значения по оси X
// sprintf(str1,»X:%06d Y:%06d Z:%06drn», xval, yval, zval);
// HAL_UART_Transmit(&huart2, (uint8_t*)str1,strlen(str1),0x1000);
// buf2[0]=0x12;
// buf2[1]=0x10;
// buf2[2]=(uint8_t)(xval>>8);
// buf2[3]=(uint8_t)xval;
// buf2[4]=0x10;
// buf2[5]=0x10;
// buf2[6]=(uint8_t)(zval>>8);
// buf2[7]=(uint8_t)zval;
// buf2[8]=0x13;
// HAL_UART_Transmit(&huart2,buf2,9,0×1000);
if(xval>1500)
{
LD2_ON;
}
else
{
LD2_OFF;
}
HAL_Delay(20);
Вызовем данную функцию в бесконечном цикле
/* USER CODE BEGIN 3 */
Accel_ReadAcc();
}
Соберем код, прошьём контроллер и проверим работу программы. При определенном отклонении платы светодиод должен зажигаться и потухать.
Если всё работает, то попытаемся считать уже точные данные через терминальную программу, раскомментировав код в функции Accel_ReadAcc, а также немного исправив, так как у нас подключен DMA.
sprintf(str1,»X:%06d Y:%06d Z:%06drn», xval, yval, zval);
HAL_UART_Transmit_DMA(&huart2, (uint8_t*)str1,strlen(str1));
Соберем код, прошьем контроллер, запустим монитор порта из программы arduino-nightly и посмотрим результат
Зайдем в Cube MX и в настройках USART вместо 256000 включим 512000.
Перегенерируем проект, соберем его и внесем еще некоторые изменения в код функции Accel_ReadAcc, опять закомментировав код вывода на терминал. Раскомментируем и внесем изменения в код вывода в программу визуализации. Программу будем использовать NS Port Monitor, поэтому код составим в соответствии с требованиями протокола данной программы (первые байты 0x11 и 0x55).
// sprintf(str1,»X:%06d Y:%06d Z:%06drn», xval, yval, zval);
// HAL_UART_Transmit_DMA(&huart2, (uint8_t*)str1,strlen(str1));
buf2[0]=0x11;
buf2[1]=0x55;
buf2[2] = (uint8_t) (xval >> 8);
buf2[3] = (uint8_t) xval;
buf2[4] = (uint8_t) (yval >> 8);
buf2[5] = (uint8_t) yval;
buf2[6] = (uint8_t) (zval >> 8);
buf2[7] = (uint8_t) zval;
HAL_UART_Transmit_DMA(&huart2,buf2,8);
if(xval>1500)
Соберем проект, прошьем контроллер, запустим программу и проверим результат на практике (нажмите на картинку для увеличения изображения)
Предыдущая часть Программирование МК STM32 Следующий урок
Техническая документация на датчик
Техническая документация на плату расширения
Отладочную плату можно приобрести здесь Nucleo STM32F401RE
Оценочную плату можно приобрести здесь STM32 X-NUCLEO-IKS01A1
Смотреть ВИДЕОУРОК
Доброго дня, можете подсказать, делаю по аналогии, но для датчика LSM6DSL, в нем отсутствуют регистры для включения осей акселерометра, может вы подскажете, что там необходимо включить вместо этого.