浙江公司响应式网站建设推荐网站网络广告推广
浙江公司响应式网站建设推荐,网站网络广告推广,莱芜金点子信息港最新招聘,哪家培训机构学校好最近在学习DALI调光相关知识并下载了Microchip提供的基于ATMega88PA的软件工程及硬件设计参考方案。写这些文章的目的就是把自己对知识的理解作一些梳理。
芯片厂果然专业#xff0c;考虑得相当周到#xff0c;为了芯片销量连软件和硬件方案全都提供了。芯片厂关于DALI1.0实…最近在学习DALI调光相关知识并下载了Microchip提供的基于ATMega88PA的软件工程及硬件设计参考方案。写这些文章的目的就是把自己对知识的理解作一些梳理。
芯片厂果然专业考虑得相当周到为了芯片销量连软件和硬件方案全都提供了。芯片厂关于DALI1.0实现的软硬件参考链接地址如下Salesforcehttps://microchip.my.salesforce.com/sfc/p/#o0000000KAkK/a/3l000001Iuci/0yucLkmht5A3PuLOo2MVtWQlQA1Ca1FgNK1KkCKafeg
Firmware部分是DALI1.0实现的源代码包括底层驱动及上层应用使用AVR系列专用开发IDEMicrochip 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说明传输出错 图1DALI时序
4、正确检测到停止位后将接收到的地址和数据递交给上一层进行帧逻辑处理。
再来看源代码文件dali_bit.cDALI从机的接收引脚边沿跳变中断处理程序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所示 图3BIT值改变时会有两个连续TE的高或低电平
5、代码第46行判断当bit_index_temp34时就将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值。 图4bit_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/diannao/92091.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!