LibOpenCM3, 1-проводный, через UART DMA STM32F1 - PullRequest
0 голосов
/ 14 апреля 2020

Я только начал понимать встроенный мир (после Arduino, RPi и др. c) с STM32F103 и FreeRTOS + Libopencm3. Моя первая задача - подключить датчик температуры DS18B20 к моему микропроцессору. Шина 1-Wire довольно проста для понимания, но не поддерживается на родном языке, поэтому я следовал вашему совету и go для 1-wire over UART с DMA.

DS18B20 имеет данные на USART2TX (+4k7 + диод) и USART2RX, V CC до 5 В и GND.

Инициализация 1-Wire:

static void ow_init(void)
{
    // One-Wire
    // Already done : rcc_periph_clock_enable(RCC_GPIOA);
    gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
    gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
    usart_set_baudrate(USART2, 115200);
    usart_set_databits(USART2, 8);
    usart_set_stopbits(USART2, USART_STOPBITS_1);
    usart_set_mode(USART2, USART_MODE_TX);
    usart_set_parity(USART2, USART_PARITY_NONE);
    usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
    usart_enable(USART2);

    rcc_periph_clock_enable(RCC_DMA1);
}

1-Wire Reset:

uint8_t ow_reset(void)
{
    usart_disable_rx_dma(USART2);
    usart_disable_tx_dma(USART2);

    usart_set_baudrate(USART2, 9600);
    usart_set_databits(USART2, 8);
    usart_set_stopbits(USART2, USART_STOPBITS_1);
    usart_set_mode(USART2, USART_MODE_TX);
    usart_set_parity(USART2, USART_PARITY_NONE);
    usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);

    usart_send(USART2, 0xf0);
    while(usart_get_flag(USART2, USART_SR_TC));
    uint8_t ow_presence;
    ow_presence = usart_recv(USART2);

    usart_set_baudrate(USART2, 115200);
    usart_set_databits(USART2, 8);
    usart_set_stopbits(USART2, USART_STOPBITS_1);
    usart_set_mode(USART2, USART_MODE_TX_RX);
    usart_set_parity(USART2, USART_PARITY_NONE);
    usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);

    if(ow_presence != 0xf0)
    {
        return 1;
    }

    return 0;
}

Получение блокнота с:

void ow_convert_to_scratchpad(void)
{
    const uint8_t convert_T[] = {0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,  // 0xCC
                                 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00}; // 0x44

    dma_channel_reset(DMA1, DMA_CHANNEL7);
    dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t)&USART2_DR);
    dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t) convert_T);
    dma_set_number_of_data(DMA1, DMA_CHANNEL7, sizeof(convert_T));
    dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL7);
    dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
    dma_set_peripheral_size(DMA1, DMA_CHANNEL7, DMA_CCR_PSIZE_8BIT);
    dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_8BIT);
    dma_set_priority(DMA1, DMA_CHANNEL7, DMA_CCR_PL_LOW);

    dma_enable_channel(DMA1, DMA_CHANNEL7);
    usart_enable_tx_dma(USART2);
}

uint16_t ow_get_scratchpad(void)
{
    const uint8_t read_scratch[] = {0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,  // 0xCC
                                    0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF,  // 0xBE
                                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

    uint8_t buf[8];

    dma_channel_reset(DMA1, DMA_CHANNEL6);
    dma_set_peripheral_address(DMA1, DMA_CHANNEL6, (uint32_t)&USART2_DR);
    dma_set_memory_address(DMA1, DMA_CHANNEL6, (uint32_t) buf);
    dma_set_read_from_peripheral(DMA1, DMA_CHANNEL6);
    dma_set_number_of_data(DMA1, DMA_CHANNEL6, sizeof(read_scratch));
    dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL6);
    dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL6);
    dma_set_peripheral_size(DMA1, DMA_CHANNEL6, DMA_CCR_PSIZE_8BIT);
    dma_set_memory_size(DMA1, DMA_CHANNEL6, DMA_CCR_MSIZE_8BIT);
    dma_set_priority(DMA1, DMA_CHANNEL6, DMA_CCR_PL_LOW);

    dma_channel_reset(DMA1, DMA_CHANNEL7);
    dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t)&USART2_DR);
    dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t) read_scratch);
    dma_set_number_of_data(DMA1, DMA_CHANNEL7, sizeof(read_scratch));
    dma_set_read_from_peripheral(DMA1, DMA_CHANNEL6);
    dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL7);
    dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
    dma_set_peripheral_size(DMA1, DMA_CHANNEL7, DMA_CCR_PSIZE_8BIT);
    dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_8BIT);
    dma_set_priority(DMA1, DMA_CHANNEL7, DMA_CCR_PL_LOW);

    dma_enable_channel(DMA1, DMA_CHANNEL6);
    dma_enable_channel(DMA1, DMA_CHANNEL7);
    usart_enable_tx_dma(USART2);
    usart_enable_rx_dma(USART2);

    while(dma_get_interrupt_flag(DMA1, DMA_CHANNEL6, DMA_TCIF));

    uint16_t tt = 0;

    for(int i=0;i<32; i++)
    {
        uart1_printf("Bit : %d \n\r", buf[i]);
        if(buf[i] == 0xff)
        {
            tt = (tt >> 1) | 0x8000;
        }
        else
        {
            tt = tt >> 1;
        }
    }
    return tt;
}

static void demo_task(void *args)
{

    (void)args;

    for (;;) {
        uart1_printf("Hello\n\r");
        uint8_t p = ow_reset();
        uart1_printf("presence = %d\n\r", p);
        ow_convert_to_scratchpad();
        for(int i=0; i<5000000; i++)
        {
            __asm__("nop");
        }
        ow_reset();
        uint16_t t = ow_get_scratchpad();
        uart1_printf("t = %d \n\r", t);
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

И, наконец, задача, которая пытается достичь DS18B20

static void demo_task(void *args)
{

    (void)args;

    for (;;) {
        ow_reset();
        ow_convert_to_scratchpad();
        vTaskDelay(pdMS_TO_TICKS(500));
        ow_reset();
        uint16_t t = ow_get_scratchpad();
        uart1_printf("t = %d \n\r", t);
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

Я получаю некоторые биты, такие как 0x CC, 0xBE, 0xFF, но ответа больше нет.

1 Ответ

0 голосов
/ 14 апреля 2020

Хорошо, значит,

rcc_periph_clock_enable(RCC_USART2);

отсутствует, поэтому USART2 не может выполнить свою работу. Теперь я могу отправлять и получать данные.

Функция сброса работает, кроме этой строки (она ждет бесконечно):

while(usart_get_flag(USART2, USART_SR_TC));

Я не понимаю, почему этот флаг не соответствует действительности при передаче завершено ... Но у меня 0x00 на линии RX, поэтому я думаю, что датчик реагирует (я надеюсь ...)

Моя функция ow_convert_to_scratchpad с DMA выглядит как блокировка. Я не знаю, почему ...

Я только что попытался (для забавы ...) заменить весь DMA путем жесткого кодирования отправленных 0x CC, 0x44, 0x CC, 0xBE и читать, но нет ответа (0x00) от датчиков.

...