日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 嵌入式 > 嵌入式大雜燴
[導(dǎo)讀]大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是嵌入式里串口(UART)自動(dòng)波特率識(shí)別程序設(shè)計(jì)與實(shí)現(xiàn)。串口(UART)是嵌入式里最基礎(chǔ)最常用也最簡(jiǎn)單的一種通訊(數(shù)據(jù)傳輸)方式,可以說(shuō)是工程師入門(mén)通訊領(lǐng)域的啟蒙老師,同時(shí)串口打印也是嵌入式項(xiàng)目里非常經(jīng)典的調(diào)試與交互方...

大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是嵌入式里串口(UART)自動(dòng)波特率識(shí)別程序設(shè)計(jì)與實(shí)現(xiàn)

串口(UART)是嵌入式里最基礎(chǔ)最常用也最簡(jiǎn)單的一種通訊(數(shù)據(jù)傳輸)方式,可以說(shuō)是工程師入門(mén)通訊領(lǐng)域的啟蒙老師,同時(shí)串口打印也是嵌入式項(xiàng)目里非常經(jīng)典的調(diào)試與交互方式。

最精簡(jiǎn)的串口僅使用兩根單向信號(hào)線:TXD、RXD,這兩根信號(hào)線是獨(dú)立工作的,因此數(shù)據(jù)收發(fā)既可分開(kāi)也可同時(shí)進(jìn)行,這就是所謂的全雙工。串口沒(méi)有主從機(jī)概念,并且沒(méi)有專門(mén)的時(shí)鐘信號(hào) SCK,所以串口通信也屬于異步傳輸。

說(shuō)到異步傳輸,這就不得不提波特率(每秒鐘傳輸bit數(shù))的問(wèn)題了,通信雙方必須使用一致的波特率才能完成正確的數(shù)據(jù)傳輸。正常情況下,我們都是為兩個(gè)串口設(shè)備事先約定好波特率,比如 MCU 與上位機(jī)通信,在 MCU 程序里按 115200 的波特率去初始化 UART 外設(shè),然后上位機(jī)串口調(diào)試助手也設(shè)置 115200 波特率,雙方再聯(lián)合工作。

有時(shí)候,我們也希望能有一種靈活的波特率約定方式,比如建立通信前,在上位機(jī)串口調(diào)試助手里隨意設(shè)置一種波特率,然后按這個(gè)波特率發(fā)送數(shù)據(jù),MCU 端能自動(dòng)識(shí)別出這個(gè)波特率,并用識(shí)別出來(lái)的波特率去初始化 UART 外設(shè),然后再進(jìn)行后續(xù)數(shù)據(jù)傳輸,這種方式就叫自動(dòng)波特率識(shí)別。痞子衡今天要分享的就是在 MCU 里實(shí)現(xiàn)自動(dòng)波特率識(shí)別的程序設(shè)計(jì):

  • 程序主頁(yè):https://github.com/JayHeng/cortex-m-apps/tree/master/components/autobaud

一、串口(UART)自動(dòng)波特率識(shí)別程序設(shè)計(jì)

1.1 函數(shù)接口定義

首先是設(shè)計(jì)自動(dòng)波特率識(shí)別程序頭文件:autobaud.h ,這個(gè)頭文件里直接定義如下 3 個(gè)接口函數(shù)原型。涵蓋必備的初始化流程 init()、deinit(),以及最核心的波特率識(shí)別功能 get_rate()。

//!?@brief?初始化波特率識(shí)別
void?autobaud_init(void);

//!?@brief?檢測(cè)波特率識(shí)別是否已完成,并獲取波特率值
bool?autobaud_get_rate(uint32_t?*rate);

//!?@brief?關(guān)閉波特率識(shí)別
void?autobaud_deinit(void);

1.2 識(shí)別設(shè)計(jì)思想

關(guān)于識(shí)別,因?yàn)樯衔粰C(jī)數(shù)據(jù)是從 RXD 引腳過(guò)來(lái)的,所以在 MCU 里需要先將 RXD 引腳配置成普通數(shù)字輸入 GPIO(這個(gè)引腳需要上拉,默認(rèn)保持高電平),然后檢測(cè)這個(gè) GPIO 的電平跳變(一般用下降沿)并計(jì)時(shí)。

下圖是典型的 UART 單字節(jié)傳輸時(shí)序,I/O 空閑狀態(tài)是高電平,傳輸時(shí)總是由 1bit 低電平起始位開(kāi)啟,然后是從 LSB 到 MSB 的 8bit 數(shù)據(jù)位,校驗(yàn)位是可選項(xiàng)(我們暫不開(kāi)啟),最后由 1bit 高電平停止位結(jié)束,I/O 回歸高電平空閑狀態(tài)。

  • Note 1:檢測(cè)下降沿跳變,是因?yàn)?I/O 空閑為高,起始位的存在保證了每 Byte 傳輸周期總是從下降沿開(kāi)始。
  • Note 2:起始位和停止位兩個(gè) bit 的存在還兼有波特率容錯(cuò)的功能,通信雙方波特率在 3% 的誤差內(nèi)數(shù)據(jù)傳輸均可以正常進(jìn)行。
雖然我們不需要約定上位機(jī)波特率,但是要想實(shí)現(xiàn)波特率自動(dòng)識(shí)別,上位機(jī)初始傳輸?shù)臄?shù)據(jù)卻必須要事先約定好(可理解為接頭暗號(hào)),這涉及到 MCU 里檢測(cè)電平跳變次數(shù)與相應(yīng)計(jì)時(shí)計(jì)算。MCU識(shí)別完成后將暗號(hào)發(fā)回給上位機(jī)確認(rèn)。

痞子衡設(shè)計(jì)的接頭暗號(hào)是 0x5A, 0xA6 兩個(gè)字節(jié),兩字節(jié)暗號(hào)相比單字節(jié)暗號(hào)容錯(cuò)性更好一些(以防 I/O 上有干擾,導(dǎo)致誤識(shí)別),根據(jù)指定的暗號(hào)和 UART 傳輸時(shí)序圖,我們很容易得到如下常量定義:

enum?_autobaud_counts
{
????//!?0x5A?字節(jié)對(duì)應(yīng)的下降沿個(gè)數(shù)
????kFirstByteRequiredFallingEdges?=?4,
????//!?0xA6?字節(jié)對(duì)應(yīng)的下降沿個(gè)數(shù)
????kSecondByteRequiredFallingEdges?=?3,
????//!?0x5A?字節(jié)(從起始位到停止位)第一個(gè)下降沿到最后一個(gè)下降沿之間的實(shí)際bit數(shù)
????kNumberOfBitsForFirstByteMeasured?=?8,
????//!?0xA6?字節(jié)(從起始位到停止位)第一個(gè)下降沿到最后一個(gè)下降沿之間的實(shí)際bit數(shù)
????kNumberOfBitsForSecondByteMeasured?=?7,
????//!?兩個(gè)下降沿之間允許的最大超時(shí)(us)
????kMaximumTimeBetweenFallingEdges?=?80000,
????//!?對(duì)實(shí)際檢測(cè)出的波特率值做對(duì)齊處理,以便于更好地配置UART模塊
????kAutobaudStepSize?=?1200
};
上述常量定義里,kMaximumTimeBetweenFallingEdges 指定了兩個(gè)下降沿之間允許的最大時(shí)間間隔,超過(guò)這個(gè)時(shí)間,自動(dòng)波特率程序?qū)G掉前面統(tǒng)計(jì)的下降沿個(gè)數(shù),重頭開(kāi)始識(shí)別,這個(gè)設(shè)計(jì)也是為了防止 I/O 上有電平干擾,導(dǎo)致誤識(shí)別。

kAutobaudStepSize 常量是為了對(duì)檢測(cè)出的波特率值做對(duì)齊處理,公式是 rounded = stepSize * (value/stepSize 0.5),其中 value 是實(shí)際檢測(cè)出的波特率值,rounded 是對(duì)齊后的波特率值,用對(duì)齊后的波特率值能更好地配置UART外設(shè)(這跟UART模塊里波特率發(fā)生器SBR設(shè)計(jì)有關(guān))。

最后就是 I/O 電平下降沿檢測(cè)方法設(shè)計(jì),這里既可以用軟件查詢(就是循環(huán)讀取 I/O 輸入電平,比較當(dāng)前值與上一次值的差異),也可以使用GPIO模塊自帶的邊沿中斷功能。推薦使用后者,一方面計(jì)時(shí)更精確,另外也不用阻塞系統(tǒng)。檢測(cè)到下降沿發(fā)生就調(diào)用一次如下 pin_transition_callback() 函數(shù),在這個(gè)函數(shù)里統(tǒng)計(jì)跳變次數(shù)以及計(jì)時(shí)。

//!?@brief?管腳下降沿跳變回調(diào)函數(shù)
static?void?pin_transition_callback(void);

1.3 主代碼實(shí)現(xiàn)

根據(jù)上一小節(jié)描述的設(shè)計(jì)思想,我們很容易寫(xiě)出下面的主代碼(autobaud_irq.c),代碼里痞子衡都做了詳細(xì)注釋。有一點(diǎn)要提的是關(guān)于其中系統(tǒng)計(jì)時(shí),可參考痞子衡舊文 《嵌入式里通用微秒(microseconds)計(jì)時(shí)函數(shù)框架設(shè)計(jì)與實(shí)現(xiàn)》 。

//!?@brief?使能GPIO管腳中斷
extern?void?enable_autobaud_pin_irq(pin_irq_callback_t?func);
//!?@brief?關(guān)閉GPIO管腳中斷
extern?void?disable_autobaud_pin_irq(void);

//!
static?uint32_t?s_transitionCount;
//!
static?uint64_t?s_firstByteTotalTicks;
//!
static?uint64_t?s_secondByteTotalTicks;
//!
static?uint64_t?s_lastToggleTicks;
//!
static?uint64_t?s_ticksBetweenFailure;

void?autobaud_init(void)
{
????s_transitionCount?=?0;
????s_firstByteTotalTicks?=?0;
????s_secondByteTotalTicks?=?0;
????s_lastToggleTicks?=?0;
????//?計(jì)算出下降沿之間最大超時(shí)對(duì)應(yīng)計(jì)數(shù)值
????s_ticksBetweenFailure?=?microseconds_convert_to_ticks(kMaximumTimeBetweenFallingEdges);
????//?使能GPIO管腳中斷,并注冊(cè)中斷處理回調(diào)函數(shù)
????enable_autobaud_pin_irq(pin_transition_callback);
}

void?autobaud_deinit(void)
{
????//?關(guān)閉GPIO管腳中斷
????disable_autobaud_pin_irq();
}

bool?autobaud_get_rate(uint32_t?*rate)
{
????if?(s_transitionCount?==?(kFirstByteRequiredFallingEdges? ?kSecondByteRequiredFallingEdges))
????{
????????//?計(jì)算出實(shí)際檢測(cè)到的波特率值
????????uint32_t?calculatedBaud?=
????????????(microseconds_get_clock()?*?(kNumberOfBitsForFirstByteMeasured? ?kNumberOfBitsForSecondByteMeasured))?/
????????????(uint32_t)(s_firstByteTotalTicks? ?s_secondByteTotalTicks);

????????//?對(duì)實(shí)際檢測(cè)出的波特率值做對(duì)齊處理
????????//?公式:rounded = stepSize *?(value/stepSize .5)
????????*rate?=?((((calculatedBaud?*?10)?/?kAutobaudStepSize)? ?5)?/?10)?*?kAutobaudStepSize;

????????return?true;
????}
????else
????{
????????return?false;
????}
}

void?pin_transition_callback(void)
{
????//?獲取當(dāng)前系統(tǒng)計(jì)數(shù)值
????uint64_t?ticks?=?microseconds_get_ticks();
????//?計(jì)數(shù)這次檢測(cè)到的下降沿
????s_transitionCount ;

????//?如果本次下降沿與上次下降沿之間間隔過(guò)長(zhǎng),則從頭開(kāi)始檢測(cè)
????uint64_t?delta?=?ticks?-?s_lastToggleTicks;
????if?(delta?>?s_ticksBetweenFailure)
????{
????????s_transitionCount?=?1;
????}

????switch?(s_transitionCount)
????{
????????case?1:
????????????//?0x5A?字節(jié)檢測(cè)時(shí)間起點(diǎn)
????????????s_firstByteTotalTicks?=?ticks;
????????????break;

????????case?kFirstByteRequiredFallingEdges:
????????????//?得到?0x5A?字節(jié)檢測(cè)期間內(nèi)對(duì)應(yīng)計(jì)數(shù)值
????????????s_firstByteTotalTicks?=?ticks?-?s_firstByteTotalTicks;
????????????break;

????????case?(kFirstByteRequiredFallingEdges? ?1):
????????????//?0xA6?字節(jié)檢測(cè)時(shí)間起點(diǎn)
????????????s_secondByteTotalTicks?=?ticks;
????????????break;

????????case?(kFirstByteRequiredFallingEdges? ?kSecondByteRequiredFallingEdges):
????????????//?得到?0xA6?字節(jié)檢測(cè)期間內(nèi)對(duì)應(yīng)計(jì)數(shù)值
????????????s_secondByteTotalTicks?=?ticks?-?s_secondByteTotalTicks;
????????????//?關(guān)閉GPIO管腳中斷
????????????disable_autobaud_pin_irq();
????????????break;
????}

????//?記錄本次下降沿發(fā)生時(shí)系統(tǒng)計(jì)數(shù)值
????s_lastToggleTicks?=?ticks;
}

二、串口(UART)自動(dòng)波特率識(shí)別程序?qū)崿F(xiàn)

前面講的都是硬件無(wú)關(guān)設(shè)計(jì),但最終還是要落實(shí)到具體 MCU 平臺(tái)上的,其中 GPIO 中斷部分是跟 MCU 緊相關(guān)的。我們以恩智浦 i.MXRT1011 為例來(lái)介紹硬件實(shí)現(xiàn)。

2.1 管腳中斷方式實(shí)現(xiàn)(基于i.MXRT1011)

恩智浦 MIMXRT1010-EVK 有板載調(diào)試器 DAPLink,這個(gè) DAPLink 中也集成了 USB 轉(zhuǎn)串口的功能,對(duì)應(yīng)的 UART 引腳是 IOMUXC_GPIO_09_LPUART1_RXD 和 IOMUXC_GPIO_10_LPUART1_TXD,我們就選用這個(gè)管腳 GPIO1[9] 做自動(dòng)波特率檢測(cè),實(shí)現(xiàn)代碼如下:

  • BSP程序:https://github.com/JayHeng/cortex-m-apps/tree/master/apps/autobaud_imxrt1011/bsp/src/pinmux_utility.c
typedef?void?(*pin_irq_callback_t)(void);
static?pin_irq_callback_t?s_pin_irq_func;

//!?@brief?UART引腳功能切換函數(shù)
void?uart_pinmux_config(bool?setGpio)
{
????if?(setGpio)
????{
????????IOMUXC_SetUartAutoBaudPinMode(IOMUXC_GPIO_09_GPIOMUX_IO09,?GPIO1,?9);
????}
????else
????{
????????IOMUXC_SetUartPinMode(IOMUXC_GPIO_09_LPUART1_RXD);
????????IOMUXC_SetUartPinMode(IOMUXC_GPIO_10_LPUART1_TXD);
????}
}

//!?@brief?使能GPIO管腳中斷
void?enable_autobaud_pin_irq(pin_irq_callback_t?func)
{
????s_pin_irq_func?=?func;
????//?開(kāi)啟GPIO1_9下降沿中斷
????GPIO_SetPinInterruptConfig(GPIO1,?9,?kGPIO_IntFallingEdge);
????GPIO1->IMR?|=?(1U?<9);
????NVIC_SetPriority(GPIO1_Combined_0_15_IRQn,?1);
????NVIC_EnableIRQ(GPIO1_Combined_0_15_IRQn);
}

//!?@brief?GPIO中斷處理函數(shù)
void?GPIO1_Combined_0_15_IRQHandler(void)
{
????uint32_t?interrupt_flag?=?(1U?<9);
????//?僅當(dāng)GPIO1_9中斷發(fā)生時(shí)
????if?((GPIO_GetPinsInterruptFlags(GPIO1)?
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過(guò)流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問(wèn)題卻十分常見(jiàn),不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問(wèn)題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(chē)(EV)作為新能源汽車(chē)的重要代表,正逐漸成為全球汽車(chē)產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車(chē)的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車(chē)的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車(chē) 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車(chē)場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問(wèn)題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周?chē)娮釉O(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開(kāi)關(guān)電源具有效率高的特性,而且開(kāi)關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉