1

Тема: 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] більш рандомні і плавають незалежно один від одного.

Може в кого є позитивний досвід по сабжику? Чи може в коді щось не правильно? Які є ідеї як проаналізувати хто винен і що робити? Будь що?

2

Re: OneWire на STM32 за допомоги HAL USART та DMA

не знаю чи актуально, але...

послідовність має бути така:
1. Reset
2. isPresent
3. Skeep ROM Command
4. Convert Command
6. Delay
7. Reset
8. isPresent
9. Skeep ROM Command
10. Read Scratchpad
11. Delay
12. go to 1

Подякували: taburyak1

3

Re: OneWire на STM32 за допомоги HAL USART та DMA

VitekSVM написав:

не знаю чи актуально, але...

Щиро дякую, вже не актуально.
Ось остання версія: https://github.com/taburyak/STM32_OneWi … L_UART_DMA
Ось стаття: https://stm32withoutfear.blogspot.com/2 … e-hal.html