DALI1.0学习——BIT解码

news2024/10/6 0:26:57

最近在学习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.coloradmin.cn/o/1295534.html

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

相关文章

代理IP怎么使用?Mac苹果系统设置http代理IP教程

代理IP是一种通过将请求转发到另一个服务器&#xff0c;以隐藏自己的真实IP地址的服务器。使用代理IP可以保护您的隐私和安全&#xff0c;防止被跟踪或被攻击。在本文中&#xff0c;我们将介绍如何在Mac苹果系统上设置http代理IP教程。 一、了解代理IP 代理IP地址是一种可以用来…

Web自动化测试(超详细)

一、什么是web自动化测试 自动化&#xff08;Automation&#xff09;是指机器设备、系统或过程&#xff08;生产、管理过程&#xff09;在没有人或较少人的直接参与下&#xff0c;按照人的要求&#xff0c;经过自动检测、信息处理、分析判断、操纵控制&#xff0c;实现预期的目…

Python并发-线程和进程

一、线程和进程对应的问题 **1.进程&#xff1a;**CPU密集型也叫计算密集型&#xff0c;指的是系统的硬盘、内存性能相对CPU要好很多&#xff0c;此时&#xff0c;系统运作大部分的状况是CPU Loading 100%&#xff0c;CPU要读/写I/O(硬盘/内存)&#xff0c;I/O在很短的时间就可…

基于Java的招聘系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

嵌入式杂记 - MDK的Code, RO-data , RW-data, ZI-data意思

嵌入式杂记 - Keil的Code, RO-data , RW-data, ZI-data意思 MDK中的数据分类MCU中的内部存储分布MDK中数据类型存储Code代码段例子 RO-data 只读数据段例子 RW-data 可读写数据段例子 ZI-data 清零数据段例子 在嵌入式开发中&#xff0c;我们经常都会使用一些IDE&#xff0c;例…

2023.12.7 关于 MySQL 事务详解

目录 事务的四大特性 原子性 一致性 持久性 隔离性 事务并发执行 脏读 不可重复读 幻读 四个隔离级别 read uncommitted read committed repeatable read serializable 事务的四大特性 原子性 一个事务中的所有操作&#xff0c;要么全部完成&#xff0c;要么全部…

2.修改列名与列的数据类型

修改字段名与字段数据类型 1.修改字段名 有时&#xff0c;在我们建好一张表后会突然发现&#xff0c;哎呀&#xff01;字段名貌似写错了&#xff01;怎么办&#xff1f;要删了表再重新建一个新表吗&#xff1f;还是要删了这个字段再新建一个新的字段&#xff1f; 都不用&…

【开源】基于JAVA的校园疫情防控管理系统

项目编号&#xff1a; S 037 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S037&#xff0c;文末获取源码。} 项目编号&#xff1a;S037&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生2.2 老师2.3 学校管理部门 三、…

proftpd安全加固:限制用户FTP登录

其实无所谓安全加固&#xff0c;因为proftp默认就是限制用户FTP登录的&#xff0c;这里有点凌乱得研究和实验了proftpd如何进行限制的&#xff0c;以及可能的放开限制。懂了这些才能更好的进行防护配置。 RootLogin指令其实主要作用就是启用ROOT访问。通常&#xff0c;proftpd在…

官方版小白重装系统之制作装机U盘篇

一、前言 很多人会安装电脑的操作系统&#xff0c;也有很多人不会安装&#xff0c;甚至还要花时间花金钱找人安装。 网上重装系统的网站很多&#xff0c;安装系统的工具软件也很多&#xff0c;其中不乏捆绑有病毒木马、广告间谍的&#xff0c;很多人深受其害&#xff0c;那为什…

聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化

聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化 目录 聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于谱聚类(Spectral Cluster)的聚类算法可视化&#xff08;完…

论文阅读《Learning Adaptive Dense Event Stereo from the Image Domain》

论文地址&#xff1a;https://openaccess.thecvf.com/content/CVPR2023/html/Cho_Learning_Adaptive_Dense_Event_Stereo_From_the_Image_Domain_CVPR_2023_paper.html 概述 事件相机在低光照条件下可以稳定工作&#xff0c;然而&#xff0c;基于事件相机的立体方法在域迁移时性…

Redis KEY*模糊查询导致速度慢、阻塞其他 Redis 操作

Redis KEY*模糊查询导致交互速度慢、阻塞其他 Redis 操作 查询速度慢的原因 在Redis中&#xff0c;使用通配符 KEYS 命令进行键的模糊匹配&#xff08;比如 KEYS key*&#xff09;可能会导致性能问题&#xff0c;尤其是在数据集较大时。这是因为 KEYS 命令的实现需要遍历所有…

盘古信息牵手时信集团,IMS-MOM护航制造企业海外工厂高效管理

在当前全球化经济背景下&#xff0c;制造企业海外工厂布局的趋势日益凸显。布局全球多工厂制造基地在管理方面需要直面多方面的挑战&#xff0c;包含复杂的全球供应链管理、跨地域资源协同合作、远程监测运营等等。在这种背景下&#xff0c;数字化智能制造系统被业内广泛应用&a…

多段图问题-动态规划解法

一、多段图问题 问题描述&#xff1a;设图G(V, E)是一个带权有向图&#xff0c;如果把顶点集合V划分成k个互不相交的子集Vi (2≤k≤n, 1≤i≤k)&#xff0c;使得对于E中的任何一条边(u, v)&#xff0c;必有u∈Vi&#xff0c;v∈Vim (1≤i≤k, 1&#xff1c;im≤k)&#xff0c;…

因小失大,一个普通的postman多接口顺序执行,让项目瘫痪了一天

Runner的使用 postman不仅可以单独运行某个接口&#xff0c;postman的 Runner模块可以运行多个接口&#xff0c;可以实现真正意义上的自动化接口测试 Runner的主要功能如下 按顺序调用接口&#xff0c;执行用例&#xff1b; 批量发送请求&#xff1b; 对接口数据进行参数化…

Termux+Hexo结合内网穿透轻松实现安卓手机搭建博客网站发布公网访问

文章目录 前言 1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并结合…

C++STL的string模拟实现

文章目录 前言string的成员变量成员函数构造函数拷贝构造赋值重载 模拟实现string各种接口print迭代器普通迭代器const迭代器 string比较大小push_backinsert 和 eraseinserterase reserve和resizereserveresize swapfindcout和cincoutcin 前言 今天要讲string的底层实现&…

c语言实例:计算并输出一个整数数组的平均值

大家好&#xff0c;今天给大家介绍一个c语言实例&#xff1a;计算并输出一个整数数组的平均值&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 以下是一个使用C语言实现的实例&am…

SMART PLC系统时间功能块

有时需要进行和系统时间相关的一些控制应用,所以PLC的系统时间对于此时的工程应用显得尤为重要。下面我们介绍系统时间功能块,这里的功能块我们可以对系统时间进行读取,还可以对系统时间进行修改。 1、系统时间 2、修改系统时间 功能块利用指针和指针运算完成系统时间读取和…