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í)筆記
05-13 15:25
基于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中斷處理④


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

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

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

      event:中斷事件類型。

      接下來看一下stm32——uart設(shè)備中斷處理的真實(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ā)送中斷等不是重點(diǎn),不展開了。
}

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

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

聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請(qǐng)聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯(cuò)的朋友,別忘了一鍵三連哦!
贊 3
收藏 4
關(guān)注 151
成為作者 賺取收益
全部留言
0/200
成為第一個(gè)和作者交流的人吧
主站蜘蛛池模板: 亚洲不卡在线视频 | 国产极品女主播国产区 | 亚洲影院丰满少妇中文字幕无码 | 产精品视频在线观看免费 | 狠狠躁夜夜a产精品视频 | av天堂永久资源网av天堂 | 性欧美视频一区二区三区 | 国产精品裸体一区二区三区 | 亚洲欧洲老熟女AV | 成在线人AV无码高潮喷水 | 国产资源第一页 | 中文字幕天堂av | 亚洲一区av在线观看无码 | 国外xxx另类视频 | 日韩国产免费一区二区三区 | 人善交VIDEOS欧美3D | 91字幕网 | 国产精品av无码毛片久久 | 蜜桃精品视频 | 中文字字幕在线中文乱码范文 | 亚洲韩国精品无码一区二区三区 | 在线播放网站 | 亚洲av无码国产精品色午夜洪 | 成年站免费网站看V片在线 成人亚洲免费视频 | 国产麻豆精品精东影业AV网站 | 日韩视频一二三 | 久久婷婷五月综合色丁香 | 二区三区福利 | 国产高清一区二区三区 | 日韩精品在线免费视频 | 玩弄牲欲强老熟女 | 在线欧美日韩 | 免看一级一片 | 亚洲最大天堂无码精品区 | 青草青青在线视频 | www.51色.com | 性生大片免费观看网站蜜芽 | 大肉大捧一进一出好爽 | 91精品国产福利 | 亚洲综合图片区色 | 亚洲第一页在线视频 |