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

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

RT-Thread驅動之路:stm32設備驅動開發之uart中斷處理④


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

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

      serial:串口設備句柄,來自于哪個串口設備的中斷,對應的句柄就是誰。

      event:中斷事件類型。

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

/*uart_isr的主要用途:調用框架層rt_hw_serial_isr,通知上層中斷已經發生*/
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中斷  發送中斷等不是重點,不展開了。
}

      這段代碼是uart_isr 的一部分專門處理接收中斷觸發的數據,作用很簡單,如果讀數據寄存器不為空,且RXNE為中斷使能狀態,則調用rt_hw_serial_isr觸發讀數據操作,關于該函數的響應事件類型如下:

#define RT_SERIAL_EVENT_RX_IND          0x01    /* 接收一個字節數據*/
#define RT_SERIAL_EVENT_TX_DONE         0x02    /* 一個字節數據發送完成   */
#define RT_SERIAL_EVENT_RX_DMADONE      0x03    /* DMA接收完成 */
#define RT_SERIAL_EVENT_TX_DMADONE      0x04    /* DMA發送完成*/

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

/* 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;
        }
//.......這部分處理其它的事件響應
}
}

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

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

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 3
收藏 4
關注 149
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 无码人妻精品一区二区三区久久久 | 国产又粗又硬又猛的毛片视频 | 国产精品一区二区在线 | 性伦欧美刺激片在线观看 | 乱人伦人妻中文字幕 | 中文字幕在线中文 | 91伊人 | 日本精品中文字幕在线不卡 | 久久香蕉国产线看观看6 | 龙珠z免费观看国语版 | 日韩不卡在线观看视频 | 亚洲中文有码字幕日本第一页 | 成av在线 | 97久久国产| 亚洲第一网站 | 成年人在线免费观看热视频 | 99ri国产精品| 999久久久免费精品播放 | 欧美熟妇色ⅹxxx欧美妇 | 在线不卡视频 | 色噜噜噜噜噜噜亚洲精品 | 欧美国产精品久久久 | 97精品人人A片免费看 | 欧美日韩不卡一区二区 | 看真人视频一级毛片 | 国产精品国产片 | 日韩不卡高清视频 | 孕妇奶水仑乱A级毛片免费看 | 色婷婷99se在线观看 | 任你操精品视频 | 5252aⅴhaose我爱久久 | av片在线免费看 | 丰满熟妇人妻Av无码区 | 每日更新在线观看AV_手机 | 台湾中文佬娱乐网 | 四虎永久在线精品免费AV | 色yeye免费人成网站在线观看 | 国产精品日韩AV在线播放 | 国产一区福利在线 | 大地资源网更新免费播放视频 | 国产精品视频色 |