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.mzph.cn/news/213114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【unity小技巧】实现枪武器随镜头手臂摇摆效果

文章目录 前言方法一、改变武器位置方法二、改变武器旋转结语完结 前言 如果我们视角移动转向&#xff0c;武器如果不跟着进行摇摆&#xff0c;会感觉我们的动作很生硬&#xff0c;特别是射击类游戏&#xff0c;如下 实现武器摇摆这里主要分享两种实现方法&#xff0c;一种是…

SSD数据在写入NAND之前为何要随机化?-Part1

SSD的存储介质是什么&#xff0c;它就是NAND闪存。那你知道NAND闪存是怎么工作的吗&#xff1f;其实&#xff0c;它就是由很多个晶体管组成的。这些晶体管里面存储着电荷&#xff0c;代表着我们的二进制数据&#xff0c;要么是“0”&#xff0c;要么是“1”。NAND闪存原理上是一…

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…

【密码学基础】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;我一开始就在想用递归或者…

设计CPU功能的数字电路

实验目的(1)熟悉Multisim 电路仿真软件的操作界面和功能; (2)掌握逻辑电路综合设计,并采用仿真软件进行仿真。 实验内容1.试设计一个简易CPU功能的数字电路,实验至少要求采用4个74HC/HCT194作为4个存储单元(可以预先对存储单元存储数据),74HC283作为计算单元。请实现…

多维时序 | MATLAB实现RIME-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测

多维时序 | MATLAB实现RIME-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测 目录 多维时序 | MATLAB实现RIME-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现RIME-CNN-…

idea本地调试hadoop 遇到的几个问题

1.DEA对MapReduce的toString调用报错&#xff1a;Method threw ‘java.lang.IllegalStateException‘ exception. Cannot evaluate org.apache.hadoop.mapreduc 解决方法&#xff1a;关闭 IDEA 中的启用“ tostring() ”对象视图 2.代码和hdfs路径都对的情况下&#xff0c;程序…

架构设计系列之基础:初探软件架构设计

11 月开始突发奇想&#xff0c;想把自己在公司内部做的技术培训、平时的技术总结等等的内容分享出来&#xff0c;于是就开通了一个 Wechat 订阅号&#xff08;灸哥漫谈&#xff09;&#xff0c;开始同步发送内容。 今天&#xff08;12 月 10 日&#xff09;也同步在 CSDN 上开通…

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《面向微电网群的云储能经济-低碳-可靠多目标优化配置方法》

这篇文章的标题涵盖了以下关键信息&#xff1a; 面向微电网群&#xff1a;研究的重点是微电网群&#xff0c;这可能指的是多个微电网系统的集合&#xff0c;而不仅仅是一个单独的微电网。微电网是指由分布式能源资源、储能系统和智能控制组成的小型电力系统&#xff0c;通常能够…

实现加盐加密方法以及java nio中基于MappedByteBuffer操作大文件

自己实现 传统MD5可通过彩虹表暴力破解&#xff0c; 加盐加密算法是一种常用的密码保护方法&#xff0c;它将一个随机字符串&#xff08;盐&#xff09;添加到原始密码中&#xff0c;然后再进行加密处理。 1. 每次调用方法产生一个唯一盐值&#xff08;UUID &#xff09;密码…