99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

程序小白
認(rèn)證:優(yōu)質(zhì)創(chuàng)作者
所在專題目錄 查看專題
單片機(jī)應(yīng)用與驅(qū)動(dòng)開發(fā)之路:這時(shí)的你只需要扣動(dòng)扳機(jī)。
RT-Thread驅(qū)動(dòng)之路:stm32設(shè)備驅(qū)動(dòng)開發(fā)之uart注冊(cè)①
RT-Thread驅(qū)動(dòng)之路:stm32設(shè)備驅(qū)動(dòng)開發(fā)之uart設(shè)備創(chuàng)建②
RT-Thread驅(qū)動(dòng)之路:stm32設(shè)備驅(qū)動(dòng)開發(fā)之uart操作方法③
RT-Thread驅(qū)動(dòng)之路:stm32設(shè)備驅(qū)動(dòng)開發(fā)之uart中斷處理④
RT-Thread驅(qū)動(dòng)之路:stm32設(shè)備驅(qū)動(dòng)開發(fā)之淺析注冊(cè)機(jī)制⑤
作者動(dòng)態(tài) 更多
基于stm32采用PWM驅(qū)動(dòng)伺服控制器學(xué)習(xí)筆記
3星期前
基于STM32驅(qū)動(dòng)TM1638學(xué)習(xí)筆記——軟件篇
04-19 12:42
基于TM1638驅(qū)動(dòng)8位數(shù)碼管設(shè)計(jì)分享
02-24 11:26
RT-Thread驅(qū)動(dòng)之路: Studio創(chuàng)建FAL分區(qū)⑤
01-02 08:30
RT-Thread驅(qū)動(dòng)之路: Studio 掛載通用SPI flash④
2024-12-23 13:41

RT-Thread驅(qū)動(dòng)之路:stm32設(shè)備驅(qū)動(dòng)開發(fā)之uart操作方法③


      接上篇有了uart設(shè)備對(duì)象及rt_uart_ops結(jié)構(gòu)體以后,我們就需要提供對(duì)應(yīng)的真實(shí)的能操控硬件的函數(shù),其實(shí)真正操作的硬件的函數(shù)并不多,創(chuàng)建的結(jié)構(gòu)體對(duì)象如下:

static const struct rt_uart_ops stm32_uart_ops =
{
    .configure = stm32_configure,
    .control = stm32_control,
    .putc = stm32_putc,
    .getc = stm32_getc,
    .dma_transmit = stm32_dma_transmit
};

      先來看下基于hal庫代碼實(shí)現(xiàn)的stm32_configure的完整代碼,當(dāng)你需要更換其它單片機(jī)時(shí),再系統(tǒng)沒有提供對(duì)應(yīng)的bsp的情況下,你可以仿照代碼進(jìn)行重構(gòu)該函數(shù)用于適用于特殊的硬件,系統(tǒng)也提供了很多種不同的芯片的bsp:

static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
    struct stm32_uart *uart;
    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(cfg != RT_NULL);

    uart = rt_container_of(serial, struct stm32_uart, serial);

    uart->handle.Instance          = uart->config->Instance;
    uart->handle.Init.BaudRate     = cfg->baud_rate;
    uart->handle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
    uart->handle.Init.Mode         = UART_MODE_TX_RX;
    uart->handle.Init.OverSampling = UART_OVERSAMPLING_16;
    switch (cfg->data_bits)
    {
    case DATA_BITS_8:
        uart->handle.Init.WordLength = UART_WORDLENGTH_8B;
        break;
    case DATA_BITS_9:
        uart->handle.Init.WordLength = UART_WORDLENGTH_9B;
        break;
    default:
        uart->handle.Init.WordLength = UART_WORDLENGTH_8B;
        break;
    }
    switch (cfg->stop_bits)
    {
    case STOP_BITS_1:
        uart->handle.Init.StopBits   = UART_STOPBITS_1;
        break;
    case STOP_BITS_2:
        uart->handle.Init.StopBits   = UART_STOPBITS_2;
        break;
    default:
        uart->handle.Init.StopBits   = UART_STOPBITS_1;
        break;
    }
    switch (cfg->parity)
    {
    case PARITY_NONE:
        uart->handle.Init.Parity     = UART_PARITY_NONE;
        break;
    case PARITY_ODD:
        uart->handle.Init.Parity     = UART_PARITY_ODD;
        break;
    case PARITY_EVEN:
        uart->handle.Init.Parity     = UART_PARITY_EVEN;
        break;
    default:
        uart->handle.Init.Parity     = UART_PARITY_NONE;
        break;
    }

#ifdef RT_SERIAL_USING_DMA
    uart->dma_rx.last_index = 0;
#endif

    if (HAL_UART_Init(&uart->handle) != HAL_OK)
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

      代碼很長(zhǎng),但是功能很簡(jiǎn)單就是對(duì)串口進(jìn)行初始化,設(shè)置串口波特率,硬件流控,串口模式、串口采樣、數(shù)據(jù)位、停止位、DMA相關(guān)參數(shù)、最后調(diào)用HAL_UART_Init()完成串口的初始化功能。


      接下來看下stm32_control函數(shù)的代碼,代碼雖長(zhǎng)單功能并不復(fù)雜:

static rt_err_t stm32_control(struct rt_serial_device *serial, int cmd, void *arg)
{
    struct stm32_uart *uart;
#ifdef RT_SERIAL_USING_DMA
    rt_ubase_t ctrl_arg = (rt_ubase_t)arg;
#endif

    RT_ASSERT(serial != RT_NULL);
    uart = rt_container_of(serial, struct stm32_uart, serial);

    switch (cmd)
    {
    /* disable interrupt */
    case RT_DEVICE_CTRL_CLR_INT:
        /* disable rx irq */
        NVIC_DisableIRQ(uart->config->irq_type);
        /* disable interrupt */
        __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_RXNE);

#ifdef RT_SERIAL_USING_DMA
        /* disable DMA */
        if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX)
        {
            HAL_NVIC_DisableIRQ(uart->config->dma_rx->dma_irq);
            if (HAL_DMA_Abort(&(uart->dma_rx.handle)) != HAL_OK)
            {
                RT_ASSERT(0);
            }

            if (HAL_DMA_DeInit(&(uart->dma_rx.handle)) != HAL_OK)
            {
                RT_ASSERT(0);
            }
        }
        else if(ctrl_arg == RT_DEVICE_FLAG_DMA_TX)
        {
            HAL_NVIC_DisableIRQ(uart->config->dma_tx->dma_irq);
            if (HAL_DMA_DeInit(&(uart->dma_tx.handle)) != HAL_OK)
            {
                RT_ASSERT(0);
            }
        }
#endif
        break;
    /* enable interrupt */
    case RT_DEVICE_CTRL_SET_INT:
        /* enable rx irq */
        HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0);
        HAL_NVIC_EnableIRQ(uart->config->irq_type);
        /* enable interrupt */
        __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_RXNE);
        break;

#ifdef RT_SERIAL_USING_DMA
    case RT_DEVICE_CTRL_CONFIG:
        stm32_dma_config(serial, ctrl_arg);
        break;
#endif

    case RT_DEVICE_CTRL_CLOSE:
        if (HAL_UART_DeInit(&(uart->handle)) != HAL_OK )
        {
            RT_ASSERT(0)
        }
        break;

    }
    return RT_EOK;
}

      主要看一下幾個(gè)控制參數(shù):RT_DEVICE_CTRL_CLR_INT關(guān)閉中斷,如果有使用dma則關(guān)閉DMA。RT_DEVICE_CTRL_SET_INT:開啟終端,如果有使用dma則采用dma_config功能打開dma。RT_DEVICE_CTRL_CLOSE:關(guān)閉串口,就這幾個(gè)功能。


      發(fā)送函數(shù)功能最簡(jiǎn)單,輕松TC中斷標(biāo)記,將數(shù)據(jù)放入DR數(shù)據(jù)寄存器中,while循環(huán)等待TC中斷觸發(fā)(DR數(shù)據(jù)寄存器為空):

static int stm32_putc(struct rt_serial_device *serial, char c)
{
    struct stm32_uart *uart;
    RT_ASSERT(serial != RT_NULL);

    uart = rt_container_of(serial, struct stm32_uart, serial);
    UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC);
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \
    || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \
    || defined(SOC_SERIES_STM32G4)
    uart->handle.Instance->TDR = c;
#else
    uart->handle.Instance->DR = c;
#endif
    while (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) == RESET);
    return 1;
}

      接下來是讀取數(shù)據(jù),這里有個(gè)有意思的現(xiàn)象,看過源碼你會(huì)發(fā)現(xiàn)讀取數(shù)據(jù)和寫入數(shù)據(jù)訪問的實(shí)際的硬件寄存器都是一樣的,DR or RDR,那么你會(huì)不會(huì)有個(gè)疑問,那么某一刻讀取的數(shù)據(jù)會(huì)不會(huì)是剛寫入的數(shù)據(jù),代碼之后揭曉:

static int stm32_getc(struct rt_serial_device *serial)
{
    int ch;
    struct stm32_uart *uart;
    RT_ASSERT(serial != RT_NULL);
    uart = rt_container_of(serial, struct stm32_uart, serial);

    ch = -1;
    if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET)
    {
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \
    || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \
    || defined(SOC_SERIES_STM32G4)
        ch = uart->handle.Instance->RDR & 0xff;
#else
        ch = uart->handle.Instance->DR & 0xff;
#endif
    }
    return ch;
}

      揭曉答案啦:這里以DR為例,其實(shí)它是一對(duì)神奇的雙胞胎,一個(gè)名字對(duì)應(yīng)著兩個(gè)真實(shí)的寄存器,當(dāng)你寫入數(shù)據(jù)時(shí)實(shí)際寫入的是發(fā)送DR,當(dāng)你讀取數(shù)據(jù)時(shí)實(shí)際訪問的是接收DR,是通過你對(duì)硬件的讀or寫操作,硬件自行對(duì)應(yīng)的,當(dāng)年在這個(gè)問題上耗死了好些的腦細(xì)胞,也不知道是哪個(gè)天才設(shè)計(jì)的機(jī)制。


      最后到了還有連續(xù)傳送字節(jié)(發(fā)送)的實(shí)現(xiàn),借助的硬件的DMA技術(shù)實(shí)現(xiàn)的:

static rt_size_t stm32_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
{
    struct stm32_uart *uart;
    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(buf != RT_NULL);
    uart = rt_container_of(serial, struct stm32_uart, serial);

    if (size == 0)
    {
        return 0;
    }

    if (RT_SERIAL_DMA_TX == direction)
    {
        if (HAL_UART_Transmit_DMA(&uart->handle, buf, size) == HAL_OK)
        {
            return size;
        }
        else
        {
            return 0;
        }
    }
    return 0;
}

      帶著問題結(jié)束本篇吧,發(fā)送很簡(jiǎn)單 一個(gè)接一個(gè)的發(fā)送出去,那么接收呢,DR中有沒有數(shù)據(jù),是不是需要頻繁的觸發(fā)讀取函數(shù),或者讀不及時(shí)會(huì)不會(huì)被下一個(gè)來的數(shù)據(jù)將DR中的數(shù)據(jù)覆蓋,或者數(shù)據(jù)直接被丟掉呢?

聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場(chǎng)。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請(qǐng)聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯(cuò)的朋友,別忘了一鍵三連哦!
贊 3
收藏 4
關(guān)注 149
成為作者 賺取收益
全部留言
0/200
成為第一個(gè)和作者交流的人吧
主站蜘蛛池模板: 91色影视 | 男人天堂免费视频 | 欧美综合一区二区 | 久久一级黄色片 | 精品人妻中文字幕有码在线 | 亚洲精品亚洲人成在线观看麻豆 | 5252色成人免费视频 | mdmf.tv麻豆 | 亚洲国产成人精品无色码 | 欧美黄色性生活视频 | 久久精品aⅴ无码中文字字幕 | a级毛片免费观看网站 | 青青草最新视频 | 精品人妻少妇一区二区三区 | 欧美日韩在线影院 | 日韩一区二区观看 | 变态视频在线观看 | 久久久91精品国产一区二区精品 | 精品成人免费 | 亚洲一区二区三区含羞草 | 欧美黑人又粗又大久久久 | 日韩精品无码视频免费专区 | 91亚洲国产成人久久精品麻豆 | 永久免费av无码国产网站 | 久久超乳爆乳中文字幕 | free性欧美1819护士 | 久久人人槡人妻人人玩夜色AV | 伊人久久精品欧洲综合网 | 久久精品国产亚洲A∨麻豆 日本在线看片免费人成视频 | 亚洲小说综合网 | 精品91一区二区三区 | 亚洲黄色性视频 | 色爱综合网中文字幕第1页 国产农村妇女毛片精品久久 | 女人与牲口性恔配视频免费 | 亚洲一区天堂 | 性生大片免费观看网站蜜芽 | 免费av不卡在线观看 | xxx2高清在线观看免费视频 | 国产白嫩受无套呻吟 | 美女一区二区久久 | 免费的黄色大片 |