DALI1.0學習——BIT解碼

最近在學習DALI調光相關知識并下載了Microchip提供的基于ATMega88PA的軟件工程及硬件設計參考方案。寫這些文章的目的就是把自己對知識的理解作一些梳理。

芯片廠果然專業,考慮得相當周到,為了芯片銷量連軟件和硬件方案全都提供了。芯片廠關于DALI1.0實現的軟硬件參考鏈接地址如下:Salesforceicon-default.png?t=N7T8https://microchip.my.salesforce.com/sfc/p/#o0000000KAkK/a/3l000001Iuci/0yucLkmht5A3PuLOo2MVtWQlQA1Ca1FgNK1KkCKafeg

Firmware部分是DALI1.0實現的源代碼,包括底層驅動及上層應用,使用AVR系列專用開發IDE:Microchip Studio。

這一篇主要理解下如何解碼主機發送來的BIT信號,重點是dali_bit.c文件,關于DALI主機發送數據的時序可以參考這篇博文:DALI通信及C語言實現 - 斑鳩,一生。 - 博客園 (cnblogs.com)

主機和從機通信使用半雙工,波特率為1200,參考示例中從機使用GPIO的邊沿跳變(上升沿和下降沿都觸發)結合定時器來解碼主機發送來的信號,具體配置如下:

1、GPIO為雙邊沿跳變中斷,中斷處理完成后定時器計數清零;

2、定時器溢出時間為32微秒。1200BIT/S的波特率傳輸一個BIT的時間約833微秒,半個BIT,也就是一個TE為416微秒,所以定時器約溢出13次左右,曼切斯特編碼是在傳輸一半BIT時間的時候產生邊沿跳變,傳輸1就是上升沿,0是下降沿;

定時器和GPIO配置完成后,就開始等待主機發送前向幀,從機解析數據的思路如下:

1、總線在沒有數據發送時,從機的接收引腳(也就是雙邊沿跳變引腳)一直是高電平;

2、當主機發送起始號時,從機的接收引腳會檢測到一個下降沿,當經過約半個BIT的時間后如果檢測到一個上升沿,則證明是有效的起始信號,進入準備接收信號階段;

3、以后每隔兩個TE就讀取一次實際傳輸的BIT,如圖1所示,同時不停檢測是否有連續4個TE,如果數據接收完成后出現4個連續TE,證明是接收到了停止位,本次數據接收成功,如果數據沒有接收完成就出現4個TE說明傳輸出錯;

圖1:DALI時序

4、正確檢測到停止位后,將接收到的地址和數據遞交給上一層進行幀邏輯處理。

再來看源代碼文件dali_bit.c,DALI從機的接收引腳邊沿跳變中斷處理程序dali_bit_pcint_interrupt函數如下:

/*** \brief External pin interrupt handler** This is the handler for external pin interrupt*/
void dali_bit_pcint_interrupt(void)
{static uint8_t bit_index;uint8_t bit_index_temp;uint8_t dali_bit_rx;bit_index_temp = bit_index;pin_level = DALI_INPORT & (1 << DALI_INPUT);if (status_receive == 0) {if (pin_level == LOW) {/* dali bus falling edge indicates start bit */bit_index_temp = 0;status_receive = BIT_START;dali_rec_addr = 0;dali_rec_data = 0;}} else if (status_receive == BIT_START) {/* dali pin must be high after the second INT0 edge */if ((level_time > MIN_TE_CNT) && (level_time < MAX_TE_CNT)) {			/* get the start bit and get ready for 16 bit data. */status_receive = BIT_0;bit_index_temp += 1;} else {/* Start bit error */status_receive = 0;}} else if (status_receive < BIT_STOP1) {if (level_time > MIN_2TE_CNT) {/* Long level (2xTe) is detected */bit_index_temp += 2;} else if ((level_time > MIN_TE_CNT) &&(level_time < MAX_TE_CNT)) {/* Short level (1xTe) is detected */bit_index_temp += 1;} else {status_receive = 0;}if (bit_index_temp >= 34) { /* If the last Te is low (dali bit 0), a rising edge is* detected before stop bit */			 status_receive = BIT_STOP1;}/* Decode dali bit at every second Te bit */if (bit_index_temp & 0x01) {/* shift out the lowest bit to get dali bit */			dali_bit_rx = bit_index_temp >> 1;if (dali_bit_rx <= BIT_7) { //the current bit number, maximum 8 for the address byte/* get the address byte */dali_rec_addr <<= 1;if (pin_level) {dali_rec_addr |= 0x01;}} else {/* get the data byte */dali_rec_data <<= 1;if (pin_level) {dali_rec_data |= 0x01;if (dali_bit_rx == BIT_15) { /* if the last Te is high (dali bit 1), a Te * high period is added before stop bit */						 status_receive = BIT_STOP2;}}}}} else {status_receive = 0;}dali_slave_set_addr_to_service(dali_rec_addr);dali_slave_set_data_to_service(dali_rec_data);bit_index = bit_index_temp;TCNT0 = 0;level_time = 0;
}

代碼分析:

1、由于在接收主機發送的數據時會多次進入邊沿跳變中斷,必須使用靜態變量bit_index并結合變量bit_index_temp保存當前已獲取的BIT索引,確切的說應該是TE索引,pin_level用于獲取從機輸入引腳的電平狀態,變量status_receive表示當前接收的是起始信號、數據還是停止位;

2、當主機發送起始信號時會觸發第一個下降沿,第16行判斷如果DALI輸入引腳是低電平,則初始化一些變量,并將接收狀態轉為BIT_START,也就是起始信號;

3、起始信號下降沿觸發后,第二次邊沿跳變觸發時必須是上升沿且觸發時間必須是在一個TE周期內才被認為是正常的起始信號,如圖2所示,Start部分先有一個下降沿然后一個上升沿才開始發送MSB。變量level_time會在定時器0的溢出中斷處理程序中累加,溢出時間約為32微秒(8MHz頻率不分頻,最大計數256,溢出時間 = 256/8000000),約13個溢出周期后就是一個TE的時間:416微秒左右,當然這個時間不可能剛好,有正負5個溢出周期左右誤差范圍,所以第25行使用了if ((level_time > MIN_TE_CNT) && (level_time < MAX_TE_CNT))。此時變量bit_index_temp被設置為1,同時status_receive設置為準備接收第一個數據BIT,即BIT_0;

圖2:起始信號,先一個下降沿然后一個上升沿

4、正確接收到起始信號后,準備接收地址和數據字節。代碼第34行判斷只要不是接收停止位就保存當前接收到的BIT。代碼第35行到第41行判斷:如果是經過兩個TE時間才產生邊沿跳變中斷的話則將bit_index_temp加2,否則加1。當發送不同BIT值時就會出現兩個TE后才會出現邊沿跳變的情況,例如:前面的比特是0,后面接著是1就會出現連續兩個TE的低電平然后產生上升沿跳變,如圖3所示;

圖3:BIT值改變時會有兩個連續TE的高或低電平

5、代碼第46行判斷當bit_index_temp>=34時就將status_receive切換到接收停止位1,因為包括起始BIT、地址字節和數據字節共17個BIT,也就是34個TE,當接收到最后一個BIT并且是低電平,這里要注意:只有當最后一個BIT是低電平,bit_index_temp才會等于34,高電平應該是33。最后一個BIT是0且它后面出現上升沿則證明接收到的是停止位1

6、代碼第53行到76行是解碼接收到的BIT值并賦值給地址變量dali_rec_addr和數據變量dali_rec_data。首先第53行使用了if (bit_index_temp & 0x01),bit_index_temp必須為奇數且大于1時if條件才為真。那我們來看一下當接收地址和數據的BIT時,bit_index_temp是不是奇數并且對應的BIT是否正確,如圖4所示,當起始位的上升沿產生后bit_index_temp被設置為1,然后從35行到41行根據邊沿跳變觸發時間將bit_index_temp加2或者加1,我們可以看到bit_index_temp確實是在每次為奇數時才讀取接收到的BIT,為節省空間在圖中我把bit_index_temp改為了bit_idx。

第1個紅點位置:也就是有效起始信號上升沿中斷時bit_idx = 1

第2個紅點位置:由于經過兩個TE才產生下降沿中斷,bit_idx執行了加2,變成3,此時if (bit_index_temp & 0x01)條件為真,讀取數據剛好是BIT值0,和曼切斯特編碼含義一樣

第3個紅點位置:經過了兩個TE產生了上升沿中斷,bit_idx執行了加2,變成5,此時if (bit_index_temp & 0x01)條件為真,讀取數據剛好是BIT值1,和曼切斯特編碼含義一樣

第4個紅點位置:經過了1個TE產生了下降沿中斷,bit_idx執行了加1,變成6,此時if (bit_index_temp & 0x01)條件為假,所以沒有讀取數據

第5個紅點位置:經過了1個TE產生了上升沿中斷,bit_idx執行了加1,變成7,此時if (bit_index_temp & 0x01)條件為真,讀取數據剛好是BIT值1,和曼切斯特編碼含義一樣

第6個紅點位置:經過了兩個TE產生了下降沿中斷,bit_idx執行了加2,變成9,此時if (bit_index_temp & 0x01)條件為真,讀取數據剛好是BIT值0,和曼切斯特編碼含義一樣

后面的以此類推,可見確實是bit_index_temp變量為奇數且非起始位時才讀取并保存BIT值。

圖4:bit_index_temp為奇數時讀取數據

7、dali_bit_rx用于判斷當前接收到的是地址字節還是數據字節并計算出BIT號,BIT_0到BIT_15,對應值:1-16,小于等于BIT_7時是地址字節,否則就是數據字節。前面說過奇數位獲取一次數據,每隔兩個值計算一下當前的BIT序號,所以dali_bit_rx = bit_index_temp >> 1。代碼第60行和第66行根據當前引腳的電平來保存數據,在第68行判斷如果是最后一個數據BIT了,則設置接收狀態為停止位2

8、最后幾行代碼主要將定時器0的計數值清零并且將定時器0溢出次數level_time清零。用局部靜態變量保存當前的TE索引號,以便下次產生邊沿跳變中斷時賦值給bit_index_temp。

DALI1.0的比特解碼部分就介紹到這里,后續繼續整理其他內容,希望和大家一起學習交流。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/213114.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/213114.shtml
英文地址,請注明出處:http://en.pswp.cn/news/213114.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【unity小技巧】實現槍武器隨鏡頭手臂搖擺效果

文章目錄 前言方法一、改變武器位置方法二、改變武器旋轉結語完結 前言 如果我們視角移動轉向&#xff0c;武器如果不跟著進行搖擺&#xff0c;會感覺我們的動作很生硬&#xff0c;特別是射擊類游戲&#xff0c;如下 實現武器搖擺這里主要分享兩種實現方法&#xff0c;一種是…

xtu oj 1271 color

題目描述 Alice在玩一個游戲&#xff0c;她在一個mn的格子里&#xff0c;隨機涂黑k個格子。然后她每次可以把一行或者一列的格子染成紅色&#xff0c;但是這一行中不能有黑色的格子。 請問她最多能把多少個格子涂成紅色&#xff1f; 輸入 第一行是一個整數T(T≤100)&#xf…

華為OD機試 - 數的分解(Java JS Python C)

題目描述 給定一個正整數 n,如果能夠分解為 m(m > 1)個連續正整數之和,請輸出所有分解中,m最小的分解。 如果給定整數無法分解為連續正整數,則輸出字符串"N"。 輸入描述 輸入數據為一整數,范圍為 (1, 2^30] 輸出描述 比如輸入為: 21 輸出: 21=10+11 …

SSD數據在寫入NAND之前為何要隨機化?-Part1

SSD的存儲介質是什么&#xff0c;它就是NAND閃存。那你知道NAND閃存是怎么工作的嗎&#xff1f;其實&#xff0c;它就是由很多個晶體管組成的。這些晶體管里面存儲著電荷&#xff0c;代表著我們的二進制數據&#xff0c;要么是“0”&#xff0c;要么是“1”。NAND閃存原理上是一…

唯創知音WT588F02B語音芯片在電子針療儀中的聲音播放提示應用

在醫療技術領域&#xff0c;電子針療儀作為一種非侵入性的治療設備&#xff0c;被廣泛應用于各種疼痛管理和康復治療。然而&#xff0c;操作電子針療儀需要一定的專業知識和經驗&#xff0c;以確保安全有效的治療。為了解決這一難題&#xff0c;唯創知音WT588F02B語音芯片被應用…

0基礎學java-day14-(集合)

一、集合 前面我們保存多個數據使用的是數組&#xff0c;那么數組有不足的地方&#xff0c;我們分析一下 1.數組 2 集合 數據類型也可以不一樣 3.集合的框架體系 Java 的集合類很多&#xff0c;主要分為兩大類&#xff0c;如圖 &#xff1a;[背下來] package com.hspedu.c…

設計模式之GoF23介紹

深入探討設計模式&#xff1a;構建可維護、可擴展的軟件架構 一、設計模式的背景1.1 什么是設計模式1.2 設計模式的歷史 二、設計模式的分類2.1 創建型模式2.2 結構型模式2.3 行為型模式 三、七大設計原則四、設計模式關系結論 :rocket: :rocket: :rocket: 在軟件開發領域&…

算法:爬樓梯(迭代和動態規劃)

迭代 時間復雜度 O(n) 空間復雜度 O(1) /*** param {number} n* return {number}*/ var climbStairs function(n) {let l 0, r 0 , sum 1for(let i1; i<n; i){l rr sumsum l r}return sum }; 動態規劃 時間復雜度 O(n) 空間復雜度 O(n) /*** param {number} n* r…

Memcached學習

一、概念 Memcached是一個開源的&#xff0c;高性能的內存緩存軟件&#xff0c;從名稱上看Mem就是內存&#xff0c;二cache是緩存。作用通過在事先規劃好的內存空間中臨時緩存數據庫中的各類數據&#xff0c;以達到減少業務對數據庫的直接高并發訪問&#xff0c;從而達到提升數…

【密碼學基礎】Diffie-Hellman密鑰交換協議

DH介紹 Diffie-Hellman密鑰協議算法是一種確保共享密鑰安全穿越不安全網絡的方法。 這個機制的巧妙在于需要安全通信的雙方可以用這個方法確定對稱密鑰&#xff0c;然后可以用這個密鑰進行加密和解密。 但是注意&#xff0c;這個密鑰交換協議 只能用于密鑰的交換&#xff0c;而…

Java面試題(每天10題)-------連載(45)

Dubbo篇 1、Dubbo的服務調用流程 2、Dubbo支持那種協議&#xff0c;每種協議的應用場景&#xff0c;優缺點&#xff1f; dubbo&#xff1a; 單一長連接和 NIO 異步通訊&#xff0c;適合大并發小數據量的服務調用&#xff0c;以及消費者遠大于提供者。傳輸協議 TCP&#xff0c;…

Proteus仿真--射擊小游戲仿真設計

本文介紹基于proteus射擊小游戲仿真設計&#xff08;完整仿真源文件及代碼見文末鏈接&#xff09; 仿真圖如下 K1-K4為4個按鍵&#xff0c;用于上移、下移、確認等&#xff0c;模擬單機游戲 仿真運行視頻 Proteus仿真--射擊小游戲仿真設計 附完整Proteus仿真資料代碼資料 …

ArcGIS界面顯示分辨率調整

因為電腦顯示分辨率的問題呢&#xff0c;ArcGIS的界面顯示會字體顯示不合適&#xff0c;出現模糊情況&#xff0c;這時候只需要做個簡單的操作設置一下便可以解決&#xff01; 1、右鍵ArcMap的快捷啟動方式。 2、對應選擇兼容性——>更高DPI設置——>勾選替代DPI縮放行為…

自然場景圖像中的文本檢測綜述

摘 要 本文對自然場景文本檢測問題及其方法的研究進展進行了綜述. 首先, 論述了自然場景文本的特點、自然場景文本檢測技術的研究背景、現狀以及主要技術路線. 其次, 從傳統文本檢測以及深度學習文本檢測的視角出發, 梳理、分析并比較了各類自然場景文本檢測方法的優缺點, 并介…

體系化學習運籌學基礎算法的實踐和總結

文章目錄 引言目標設計目標實踐文章匯總經驗總結一則預告 引言 眨眼間已經12月了&#xff0c;眼看著2023年馬上要過完了。 女朋友最近總說&#xff0c;工作以后感覺時間過的好快。事實上&#xff0c;我也是這么認為的。年紀越大&#xff0c;越會擔心35歲危機的降臨。所以&…

Xubuntu16.04系統中使用EDIMAX EW-7822UAC無線網卡開啟5G自發AP

目錄 1.關于 EDIMAX EW-7822UAC2.驅動安裝3.查看無線網卡信息3.通過create_ap配置5G自發AP 1.關于 EDIMAX EW-7822UAC 官網介紹 https://www.edimax.com/edimax/merchandise/merchandise_detail/data/edimax/global/wireless_adapters_ac1200_dual-band/ew-7822uac/ 詳細參數…

Python開發運維:Python項目發布到K8S集群

目錄 一、實驗 1.Python項目發布到K8S集群 一、實驗 1.Python項目發布到K8S集群 &#xff08;1&#xff09;獲取應用程序代碼 #把hello-python.tar.gz壓縮包上傳到k8s控制節點master1的root下&#xff0c;手動解壓 tar zxvf hello-python.tar.gz &#xff08;2&#xff0…

【Linux】進程周邊001之進程概念

&#x1f440;樊梓慕&#xff1a;個人主頁 &#x1f3a5;個人專欄&#xff1a;《C語言》《數據結構》《藍橋杯試題》《LeetCode刷題筆記》《實訓項目》《C》《Linux》 &#x1f31d;每一個不曾起舞的日子&#xff0c;都是對生命的辜負 目錄 前言 1.基本概念 2.描述進程-PCB…

LeetCode5.最長回文子串

昨天和之前打比賽的隊友聊天&#xff0c;他說他面百度面到這道算法題&#xff0c;然后他用暴力法解的&#xff0c;面試官讓他優化他沒優化出來&#xff0c;這道題我之前沒寫過&#xff0c;我就想看看我能不能用效率高一點的方法把它做出來&#xff0c;我一開始就在想用遞歸或者…

springboot(ssm滁州市特產銷售系統 特產商城系統Java系統

springboot(ssm滁州市特產銷售系統 特產商城系統Java系統 開發語言&#xff1a;Java 框架&#xff1a;ssm/springboot vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服務器&#xff1a;tomcat 數據庫&#xff1a;mysql 5.7&#xff08;或8.0&#xff09; …