簡體   English   中英

LibOpenCM3 1-Wire over UART DMA STM32F1

[英]LibOpenCM3 1-Wire over UART DMA STM32F1

我剛開始使用 STM32F103 和 FreeRTOS + Libopencm3 了解嵌入式世界(在 Arduino、RPi 等之后)。 我的第一個挑戰是將溫度傳感器 DS18B20 與我的微處理器連接。 1-Wire 總線很容易理解,但不受本機支持,因此我按照您的建議和 go 使用 1-wire over UART 和 DMA。

DS18B20 在 USART2TX(+4k7 上拉 + 二極管)和 USART2RX 上有 DATA,VCC 到 5V 和 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 復位:

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));
    }
}

我收到一些位 0xCC、0xBE、0xFF 但沒有更多答案。

好的,所以

rcc_periph_clock_enable(RCC_USART2);

丟失了,所以 USART2 無法完成它的工作。 我現在可以發送和接收數據了。

重置 function 工作除了這條線(它無限期地等待):

while(usart_get_flag(USART2, USART_SR_TC));

我不明白為什么傳輸完成后這個標志不正確......但我在 RX 線上有 0x00,所以我認為傳感器正在響應(我希望......)

我的帶有 DMA 的 function ow_convert_to_scratchpad 看起來像是被阻塞了。 我不知道為什么...

我只是嘗試(為了好玩......)通過硬編碼發送的 0xCC、0x44、0xCC、0xBE 和傳感器讀取但沒有應答 (0x00) 來替換整個 DMA。

我參加聚會有點晚了,但是……你有沒有先嘗試一些不那么復雜的東西? (我的意思是檢查更簡單)

就像詢問單個 DS18B20 的地址一樣?

Reset bus and check presence.
Send search ROM cmd (write byte 0xF0)
loop 64 times reading address bits from LSB to MSB {
   read bit i
   read bit i complement
   check they are 1 and 0 or the other way around
   send bit i back to device so it sends you back the next bit
}

最后你有設備地址的 8 個字節。 1 字節系列 0x28 48 位地址 1 字節 CRC8 來檢查整個事情是否正確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM