91视频免费?看_蜜芽MY188精品TV在线观看_国产免费无遮挡在线观看视频_深夜国产_亚洲精品欧洲精品_欧美黑人粗暴多交

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

RT-Thread驅(qū)動之路:stm32設(shè)備驅(qū)動開發(fā)之uart中斷處理④


      開篇分割線,我們在上一篇講過了uart相關(guān)的ops函數(shù)集,還有個更重要的就是uart中斷,發(fā)送你可以不用,但是接收什么時候來數(shù)據(jù),數(shù)據(jù)能不能及時的進(jìn)行處理,這都離不開中斷的作用,所以一般應(yīng)用中中斷接收是必選項。

      我們在寫uart驅(qū)動的時候,就需要考慮如何將中斷事件(有接收數(shù)據(jù)到達(dá))通知給uart設(shè)備驅(qū)動框架(也就是serial層),怎么發(fā)通知呢,當(dāng)然是調(diào)用uart設(shè)備驅(qū)動框架提供的rt_hw_serial_isr函數(shù),設(shè)備框架才能知道中斷到底發(fā)生了什么事。函數(shù)原型如下:

      serial:串口設(shè)備句柄,來自于哪個串口設(shè)備的中斷,對應(yīng)的句柄就是誰。

      event:中斷事件類型。

      接下來看一下stm32——uart設(shè)備中斷處理的真實操作:

/*uart_isr的主要用途:調(diào)用框架層rt_hw_serial_isr,通知上層中斷已經(jīng)發(fā)生*/
static void uart_isr(struct rt_serial_device *serial)
{
    struct stm32_uart *uart;
#ifdef RT_SERIAL_USING_DMA
    rt_size_t recv_total_index, recv_len;
    rt_base_t level;
#endif

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

    /* UART in mode Receiver -------------------------------------------------*/
    if ((__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) &&
            (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_RXNE) != RESET))
    {
        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
    }
   //......這里還有好多處理 例如DMA中斷  發(fā)送中斷等不是重點,不展開了。
}

      這段代碼是uart_isr 的一部分專門處理接收中斷觸發(fā)的數(shù)據(jù),作用很簡單,如果讀數(shù)據(jù)寄存器不為空,且RXNE為中斷使能狀態(tài),則調(diào)用rt_hw_serial_isr觸發(fā)讀數(shù)據(jù)操作,關(guān)于該函數(shù)的響應(yīng)事件類型如下:

#define RT_SERIAL_EVENT_RX_IND          0x01    /* 接收一個字節(jié)數(shù)據(jù)*/
#define RT_SERIAL_EVENT_TX_DONE         0x02    /* 一個字節(jié)數(shù)據(jù)發(fā)送完成   */
#define RT_SERIAL_EVENT_RX_DMADONE      0x03    /* DMA接收完成 */
#define RT_SERIAL_EVENT_TX_DMADONE      0x04    /* DMA發(fā)送完成*/

      接下來我們看下框架提供的代碼都做了哪些工作?

/* ISR for serial interrupt */
void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
{
    switch (event & 0xff)
    {
        case RT_SERIAL_EVENT_RX_IND:
        {
            int ch = -1;
            rt_base_t level;
            struct rt_serial_rx_fifo* rx_fifo;

            /* interrupt mode receive */
            rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
            RT_ASSERT(rx_fifo != RT_NULL);

            while (1)
            {
                ch = serial->ops->getc(serial);
                if (ch == -1) break;


                /* disable interrupt */
                level = rt_hw_interrupt_disable();

                rx_fifo->buffer[rx_fifo->put_index] = ch;
                rx_fifo->put_index += 1;
                if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;

                /* if the next position is read index, discard this 'read char' */
                if (rx_fifo->put_index == rx_fifo->get_index)
                {
                    rx_fifo->get_index += 1;
                    rx_fifo->is_full = RT_TRUE;
                    if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;

                    _serial_check_buffer_size();
                }

                /* enable interrupt */
                rt_hw_interrupt_enable(level);
            }

            /* invoke callback */
            if (serial->parent.rx_indicate != RT_NULL)
            {
                rt_size_t rx_length;

                /* get rx length */
                level = rt_hw_interrupt_disable();
                rx_length = (rx_fifo->put_index >= rx_fifo->get_index)? (rx_fifo->put_index - rx_fifo->get_index):
                    (serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index));
                rt_hw_interrupt_enable(level);

                if (rx_length)
                {
                    serial->parent.rx_indicate(&serial->parent, rx_length);
                }
            }
            break;
        }
//.......這部分處理其它的事件響應(yīng)
}
}

      當(dāng)觸發(fā)事件為接收一個字符是,那么就開啟讀取一個字符,在進(jìn)行數(shù)據(jù)存儲時防止數(shù)據(jù)出現(xiàn)異常,關(guān)閉硬件中斷,寫入成功后再次開啟終端,再中斷關(guān)閉時,中斷標(biāo)記位是有效的,也就是說連續(xù)來的數(shù)據(jù)可能已經(jīng)寫入到了DR寄存器中,所以這個時候就可以連續(xù)讀DR寄存器,直到ch返回-1。這個時候代表這當(dāng)前已無數(shù)據(jù),判斷當(dāng)前回調(diào)函數(shù)是否為空,不為空則更新緩沖區(qū)新存入數(shù)據(jù)長度(這個過程依舊是關(guān)中斷執(zhí)行)。得到正確的數(shù)據(jù)長度后,調(diào)用回調(diào)函數(shù)讀取數(shù)據(jù),到這里關(guān)于uart設(shè)備驅(qū)動的全部內(nèi)容就結(jié)束了,當(dāng)然關(guān)于發(fā)送中斷、DMA中斷部分內(nèi)容并沒有深入去講解,感興趣的小伙伴可以自己嘗試分析分析該部分代碼的實現(xiàn)邏輯。

      接下來是我們更感興趣的serial層數(shù)據(jù)的處理,筒子們下期再見~!

聲明:本內(nèi)容為作者獨立觀點,不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯的朋友,別忘了一鍵三連哦!
贊 3
收藏 4
關(guān)注 151
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 铜陵市| 鄂尔多斯市| 安阳县| 台东市| 靖宇县| 廉江市| 甘南县| 大厂| 南投县| 铁岭市| 上虞市| 曲阜市| 巩义市| 宜春市| 桂东县| 涟水县| 集安市| 安西县| 淮北市| 富顺县| 射阳县| 铅山县| 富民县| 当涂县| 连平县| 阿坝| 泸西县| 贵德县| 西乌| 菏泽市| 宝清县| 广河县| 株洲县| 邹平县| 岫岩| 灌阳县| 景德镇市| 旺苍县| 凤山县| 云浮市| 泗阳县|