Возвращение в хобби, новый проект, понимай как хочешь...
В общем, после некоторого забвения, решил поиграться с F4BY и сделать проект с нуля - очень простой (можно сказать для чайников), который в принципе мог бы быть уроком для самого простого вхождения в STM32, но к сожалению не получилось 😦
Если кому интересен сам процесс могу рассказать с картинками и видео, но позже - когда решу проблему…
И так: взят STM32CUBE MX (генератор кода для STM - пока без ссылок - всё можно взять у них на сайте ST), там же System Workbench for STM32 ( бесплатная среда, требуется регистрация для скачивания, ссыль так же есть на сайте ST) собственно F4BY (хотя неважно - любой контроллер STM32 - суть не в этом).
Короче, в STM32CUBE MX конфигурируешь то что хочешь получить от процессора(создаёшь хардварный абстрактный слой для нужного проца, в System Workbench for STM32 просто дописываешь то, что тебе нужно…
Проблема: не смог прочитать компас HMC5883/5983 по шине i2c - что говорит шина - return HAL_BUSY - занято, “перезвоните попозже”. Ладно, было принято решение “прозвонить” шину по адресам (какие есть) - ответ получаю стабильно - 2 устройства компас и баро, но как только пытаюсь читать компас получаю пустые данные (так для понятия картины - настраивать и читать его я умею - это частный случай), перепробовал кучу вариантов работы с i2c в данном хале, примеры:
void HMC5883L_initialize() {
HAL_I2C_Mem_Write(&hi2c2, HMC5883l_ADDRESS, 0x00 , 1, &RegSettingA , 1, 100);
HAL_I2C_Mem_Write(&hi2c2, HMC5883l_ADDRESS, 0x01 , 1, &RegSettingB , 1, 100);
HAL_I2C_Mem_Write(&hi2c2, HMC5883l_ADDRESS, 0x02 , 1, &RegSettingMR , 1, 100);
}
void HMC5883LRead(int16_t *destination) {
HAL_I2C_Mem_Read(&hi2c2,HMC5883l_ADDRESS,HMC5883l_ADD_DATAX_MSB_MULTI, 1, buffer, 6, 100);
destination[0] = (((int16_t)buffer[0]) << 8) | buffer[1];
destination[1] = (((int16_t)buffer[4]) << 8) | buffer[5];
destination[2] = (((int16_t)buffer[2]) << 8) | buffer[3];
}
или
void HMC5883L_initialize() {
buff[0] = HMC5883L_RA_CONFIG_A;
buff[1] = HMC5883l_Enable_A;
HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)HMC5883l_ADDRESS, buff, 2, 100);
HAL_Delay (100);
buff[0] = HMC5883L_RA_CONFIG_B;
buff[1] = HMC5883l_Enable_B;
HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)HMC5883l_ADDRESS, buff, 2, 100);
HAL_Delay (100);
buff[0] = HMC5883L_RA_MODE;
buff[1] = HMC5883l_MR;
HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)HMC5883l_ADDRESS, buff, 2, 100);
HAL_Delay (100);
}
void HMC5883LRead(int16_t *destination) {
buff[0] = HMC5883L_RA_DATAX_H;
HAL_I2C_Master_Transmit(&hi2c2,(uint16_t) HMC5883l_ADDRESS, buff, 1, 100);
HAL_I2C_Master_Receive(&hi2c2, (uint16_t)HMC5883l_ADDRESS, &buffer[0], 6, 100);
destination[0] = (((int16_t)buffer[0]) << 8) | buffer[1];
destination[1] = (((int16_t)buffer[4]) << 8) | buffer[5];
destination[2] = (((int16_t)buffer[2]) << 8) | buffer[3];
}
короче - как бы не старался - при записи и/или чтении всё одно - “занято”, ладно, есть же умный гугель! Ога или Аго, в либах есть беда: не сбрасывается флаг аналогового фильтра на лапах, но ведь адреса то мы пробиваем??? ладно у СТ есть костыль под это дело цельных 15 шагов (как прям для буржуйских алкоголиков) - применим:
/**
1. Disable the I2C peripheral by clearing the PE bit in I2Cx_CR1 register.
2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level
(Write 1 to GPIOx_ODR).
3. Check SCL and SDA High level in GPIOx_IDR.
4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to
GPIOx_ODR).
5. Check SDA Low level in GPIOx_IDR.
6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to
GPIOx_ODR).
7. Check SCL Low level in GPIOx_IDR.
8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to
GPIOx_ODR).
9. Check SCL High level in GPIOx_IDR.
10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to
GPIOx_ODR).
11. Check SDA High level in GPIOx_IDR.
12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
13. Set SWRST bit in I2Cx_CR1 register.
14. Clear SWRST bit in I2Cx_CR1 register.
15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register.
**/
void HAL_I2C_ClearBusyFlagErrata_2_14_7(I2C_HandleTypeDef *hi2c) {
static uint8_t resetTried = 0;
if (resetTried == 1) {
return ;
}
GPIO_InitTypeDef GPIO_InitStruct;
// 1
__HAL_I2C_DISABLE(hi2c);
// 2
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WRITE_ODR(GPIOB, GPIO_PIN_10);
HAL_GPIO_WRITE_ODR(GPIOB, GPIO_PIN_11);
// 3
GPIO_PinState pinState;
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10) == GPIO_PIN_RESET) {
for(;;){}
}
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11) == GPIO_PIN_RESET) {
for(;;){}
}
// 4
GPIO_InitStruct.Pin = GPIO_PIN_10;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_10);
// 5
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10) == GPIO_PIN_SET) {
for(;;){}
}
// 6
GPIO_InitStruct.Pin = GPIO_PIN_11;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_11);
// 7
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11) == GPIO_PIN_SET) {
for(;;){}
}
// 8
GPIO_InitStruct.Pin = GPIO_PIN_10;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WRITE_ODR(GPIOB, GPIO_PIN_10);
// 9
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10) == GPIO_PIN_RESET) {
for(;;){}
}
// 10
GPIO_InitStruct.Pin = GPIO_PIN_11;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WRITE_ODR(GPIOB, GPIO_PIN_11);
// 11
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11) == GPIO_PIN_RESET) {
for(;;){}
}
// 12
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// 13
hi2c->Instance->CR1 |= I2C_CR1_SWRST;
// 14
hi2c->Instance->CR1 ^= I2C_CR1_SWRST;
// 15
__HAL_I2C_ENABLE(hi2c);
resetTried = 1;
}
void HAL_GPIO_WRITE_ODR(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->ODR |= GPIO_Pin;
}
Фиг вам (национальное индейское жилище) - занято и всё тут, тестером тыкал - да шина висит в полуподвешеном состоянии, мысли кончились, вот решил написать…
Короче решил бросить эту идею и написать всё на
STM32 Standard Peripheral Libraries
по крайней мере все драйвера у меня (кроме усб - но это решаемо) написаны и работают, конечно это сложнее для начинающих, но мне проще - я с ними уже работал, и уже воевал с этой шиной на F4 - в тот раз я победил)))