Тема: OneWire на STM32 за допомоги HAL USART та DMA
Закортіло мені, аж засвербіло, сабжику.
Та не склалось як гадалось.
Щось дані які читаю з датчика більше схожі на випадкові.
Схема підключення:
http://we.easyelectronics.ru/uploads/im … 234939.png
Сутність 1-wire через USART:
Передача: на швидкості 115200 передаємо байт 0x00 це буде біт - "1", а передавши байт 0xFF отримаємо біт - "0". Тому для передачі одного байту по 1-wire треба вдути по UART 8 байтів які складаються з 0xFF та 0x00.
Прийом: Дуємо в UART байт 0xFF і якщо прочитується той же ж 0xFF то це датчик надсилає нам біт - "1". Як не 0xFF, то це буде біт - "0". Тому щоб прийняти байт з пристрою, теж треба надіслати 8 разів 0xFF і прийняти 8 байтів, а потім проаналізувавши байти на наявність 0xFF і !0xFF скласти один байт.
Нашкрябав такі функції:
Функцію reset - перевірити наявність на шині якихось пристроїв:
OneWire_TypeDef OneWire_Reset(void)
{
uint8_t ow_presence = ONEWIRE_BYTE_RESET;
OneWire_UARTInit(9600);
//HAL_UART_Transmit_DMA(&HUARTx, &ow_presence, 1);
HAL_UART_Transmit(&HUARTx, &ow_presence, 1, 100);
//HAL_UART_Receive_DMA(&HUARTx, &ow_presence, 1);
HAL_UART_Receive(&HUARTx, &ow_presence, 1, 100);
//OneWire_UARTInit(115200);
if (ow_presence != ONEWIRE_BYTE_RESET)
{
return OneWire_OK;
}
return OneWire_No_Device;
}
Ця функція працює нормально саме без DMA, але для пересилки одного байту DMA особливо і не треба. Грець з ним.
Функція надсилання та прийому байтів:
OneWire_TypeDef OneWire_WriteRead(uint8_t* buffTX, uint8_t lenTX, uint8_t* buffRX, uint8_t lenRX)
{
if(OneWire_Reset() == OneWire_No_Device)
{
return OneWire_No_Device;
}
OneWire_UARTInit(115200);
if (lenTX != 0)
{
for (uint8_t i = 0; i < lenTX; i++)
{
for (uint8_t j = 0; j < 8; j++)
{
internal_Buffer[i * 8 + j] = ((buffTX[i] >> j) & 0x01) ? 0xff : 0x00;
}
}
//HAL_UART_Transmit_DMA(&HUARTx, &(internal_Buffer[0]), lenTX * 8);
//HAL_UART_Receive_DMA(&HUARTx, &(internal_Buffer[0]), lenTX * 8);
HAL_UART_Transmit(&HUARTx, &(internal_Buffer[0]), lenTX * 8, 100);
HAL_UART_Receive(&HUARTx, &(internal_Buffer[0]), lenTX * 8, 100);
}
if (lenRX != 0)
{
for (uint8_t i = 0; i <= lenRX * 8; i++)
{
internal_Buffer[i] = 0xff;
}
//HAL_UART_Transmit_DMA(&HUARTx, &(internal_Buffer[0]), lenRX * 8);
//HAL_UART_Receive_DMA(&HUARTx, &(internal_Buffer[0]), lenRX * 8);
HAL_UART_Transmit(&HUARTx, &(internal_Buffer[0]), lenRX * 8, 100);
HAL_UART_Receive(&HUARTx, &(internal_Buffer[0]), lenRX * 8, 100);
}
if (lenRX != 0)
{
for (uint8_t i = 0; i < lenRX; i++)
{
for (uint8_t j = 0; j < 8; j++)
{
buffRX[i] = (buffRX[i]) + (((internal_Buffer[i * 8 + j] == 0xff) ? 0x01 : 0x00) << j);
}
}
}
return OneWire_OK;
}
Перед кожним запитом робимо ресет, перевіряємо наявність хоч когось на лінії.
Потім формуємо буфер згідно правил "0" це 0xFF, а "1" це 0x00.
Далі весь буфер женемо в UART.
Якщо передбачається щось прийняти, то на час прийому женемо в UART 0xFF (кількість байт прийому * 8 біт), і слухаємо як відповідає пристрій на наше кожне 0xFF.
Потім прийомний буфер аналізуємо, та формуємо з байтів біти, а з бітів складаємо вже реальні байти.
Спочатку даю запит "міряй", а через дві секунди, даю запит "віддай байти":
OneWire_WriteRead((uint8_t*) "\xcc\x44", 2, NULL, 0);
HAL_Delay(2000);
uint8_t buff[2];
OneWire_WriteRead((uint8_t*) "\xcc\xbe", 2, buff, 2);
Теоретично наче все правильно. Але в buff якась хрінь.
Коли використовую HAL_UART_Transmit_DMA та HAL_UART_Receive_DMA то buff[0] та buff[1] однакові між собою і зменшуються з кожним запитом на 1 від 0xFF.
Коли використовую HAL_UART_Transmit та HAL_UART_Receive (без DMA), то байти в buff[0] та buff[1] більш рандомні і плавають незалежно один від одного.
Може в кого є позитивний досвід по сабжику? Чи може в коді щось не правильно? Які є ідеї як проаналізувати хто винен і що робити? Будь що?