stm32实现DMX512协议发送与接收(非标)
最近把玩了一下485,期间也接触了dmx512通信协议,该协议主要用于各种舞台灯光的控制当中,进而实现各种光效以及色彩变化。根据标准的512协议,其物理连接与传统上的RS485是完全一致的,并没有什么差别,差别只是在协议上的不同,工业上应用的主要是modbus协议,而这里是用512通信协议。
DMX512数据协议是美国舞台灯光协会(USITT)于1990年发布的一种灯光控制器与灯具设备进行数据传输的标准。它包括电气特性,数据协议,数据格式等方面的内容。
512协议规定使用的波特率是250Kbps,但是stm32可以支持shangMbps的波特率,所以说这不是什么大问题。
该协议发送的数据帧一共11位,1位开始位,8位数据,2个停止位,无校验位。
根据波特率可以知道,位时间是4us,11位数据供需要44us的时间。当然对于标准的512协议是需要break和mark after break 帧的,break是一个92us的低电平,而mark after break是一个12us的高电平,如下图所示
根据上面的图片(缺失了起始码,下图补上),512协议必须有break和mark,但是在我们通常的非标准收发中,检测break和mark相对比较困难,如果非要做,耗费的资源也比较多,比如定时器计时,中断等等。如果不是做标准控制器的,完全可以另辟蹊径。
根据512 协议,每一串数据的开始都要有一个起始码,也称复位码,其数据为0,但是从开始位数至第十位是0,用来声明数据传输开始,随后包含1-512个数据,也称调光数据,其是标准的数据帧,所以第十位是1,所以我们可以根据这个第十位来进行做文章。大家都知道,一般的单片机,像51,avr等都是支持8-9位数据发送的,所以我们就是用9位数据,1位停止位,无校验位,通过检测检测第十位,也就是所谓的RB8来进行数据的接收与传输,不需要发送break和mark。
1、发送端
串口设为 9位数据,1停止位,无校验位,波特率250000
void USART1_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 250000;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART1 */
USART_Init(USART1, &USART_InitStructure);
/* Enable USART1 Receive and Transmit interrupts */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//USART_ITConfig(USART1, USART_IT_TC, ENABLE);
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);
}
注意在初始化串口的时候别忘了485芯片设为发送状态
接下来主要就是数据包的发送,发送的时候注意起始码的数据第九位设为0,调光数据第九位设为1.
void DMX_SendPacket(void)
{
pDMX_buf = 0;
while (pDMX_buf <= 512) //1-512
{
/* send data packet to slaves*/
if(USART1->SR & (1<<6))
{
/*发送起始码 00*/
if (0 == pDMX_buf)
{
USART1->DR = ((USART1->DR) & 0xfe00); //第九位置0
}
else
{
USART1->DR = 0x0100 | DMX_buf[pDMX_buf]; //第九位置1
}
pDMX_buf++;
}
}
}
以上函数相比大家都可以看懂,接下来就是在main函数中进行循环数据的发送了,比如每200ms发送一次,由于发送快,偶尔的错误也不是很明显。
2,、接收端
接收端得工作就是接收的信息进行解码(废话),关键是对RB8的处理,接收用到了中断接收,所以需要使能接收中断。
void USART1_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 250000;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART1 */
USART_Init(USART1, &USART_InitStructure);
/* Enable USART1 Receive and Transmit interrupts */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//使能接收中断
//USART_ITConfig(USART1, USART_IT_TC, ENABLE);
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
//设置优先级分组:先占优先级和从优先级 ,先占优先级0位,从优先级4位
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART1_IRQHandler(void)
{
uint16_t UDR;
static uint16_t RXB8;
static uint16_t pDMX_buf = 0; //数据指针
static uint8_t fDMX_buf_right = 0;
//接收数据
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//USART_FLAG_RXNE
{
//USART_ClearITPendingBit(USART1,USART_FLAG_RXNE);
UDR = USART_ReceiveData(USART1);
RXB8 = (UDR & 0x0100);
if (RXB8 == 0) //复位信号
{
if (!UDR)
{
fDMX_buf_right = 1;//接收数据正确
pDMX_buf = 1; //直接接收第一个数据 不保存第0个数据。
}
}
else //rb8 =1 pDMX_buf=1 调光数据
{
if (1 == fDMX_buf_right)
{
DMX_buf[pDMX_buf++] = (u8)UDR;
//接收到512个数据
if (pDMX_buf > 512)
{
fDMX_buf_right = 0;
tim_update = SET; //更新调光数据
}
}
}
}
}
————————————————
版权声明:本文为CSDN博主「爱飞的小兵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cunlingwang/java/article/details/6712187
stm32实现DMX512协议发送与接收(非标)的更多相关文章
- java-TCP协议发送和接收数据
TCP协议接收数据的步骤: A:创建接收数据的Socket对象 创建对象的时候要指定端口 B:监听客户端连接 等待客户端连接 C:获取Socket对象的输入流(字节流) D:读数据,并显示在控制台 E ...
- 【Java】学习路径56-TCP协议 发送、接收
与UDP不同的是,TCP协议使用的是Socket,而不是DatagramSocket,这是要作区分的. 构造Socket对象的时候,可以直接指定ip地址与端口号.此时需要抛出异常. import ja ...
- PHP+socket+SMTP、POP3协议发送、接收邮件
.实现SMTP协议的类dsmtp.cls.php:<?php , $webname=).); } } .实现POP3协议的类dpop3.cls.php: <? ...
- java实现http协议发送和接收数据
public void sendMessage() throws Exception { System.out.println("调用servlet开始=================&q ...
- Java基础知识强化之网络编程笔记06:TCP之TCP协议发送数据 和 接收数据
1. TCP协议发送数据 和 接收数据 TCP协议接收数据:• 创建接收端的Socket对象• 监听客户端连接.返回一个对应的Socket对象• 获取输入流,读取数据显示在控制台• 释放资源 TCP协 ...
- Java基础知识强化之网络编程笔记03:UDP之UDP协议发送数据 和 接收数据
1. UDP协议发送数据 和 接收数据 UDP协议发送数据: • 创建发送端的Socket对象 • 创建数据,并把数据打包 • 调用Socket对象的发送方法,发送数据包 • 释放资源 UDP协议接 ...
- udp协议的数据接收与发送的代码
我想基于lwIP协议中的UDP协议,用单片机做一个服务器,接受电脑的指令然后返回数据.以下是我的代码 /************************************************ ...
- 网络编程--使用TCP协议发送接收数据
package com.zhangxueliang.tcp; import java.io.IOException; import java.io.OutputStream; import java. ...
- SMTP协议及POP3协议-邮件发送和接收原理(转)
本文转自https://blog.csdn.net/qq_15646957/article/details/52544099 感谢作者 一. 邮件开发涉及到的一些基本概念 1.1.邮件服务器和电子邮箱 ...
随机推荐
- Comparable 接口与Comparator的使用的对比
package com.yhqtv.java; import org.junit.Test; import java.util.Arrays; import java.util.Comparator; ...
- 开发AI+诊疗生发系统,「先锋汇美」借力人工智能辅助诊疗实现头皮医学检测...
困扰年轻人的脱发问题萌生了新兴的产业链.36氪先前曾剖析过近来火热的植发市场,更多人则选择"防范于未然","头皮检测"服务备受关注.此前,人们对"头皮 ...
- HDU1873 看病要排队【模拟+优先队列】
看病要排队 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- dijkstra preiority_queue优化 紫书学习
#include<bits/stdc++.h> using namespace std; const int maxn=1000+10; const int INF=1000000000; ...
- Centos 6.5升级gcc : 源码安装 + rpm安装
1. 前言 采用Centos 6.5默认的gcc版本为4.4.7,不支持c++ 11,需要升级: 首先想到用yum命令:执行yum update gcc-c++或yum update g++ 显示没有 ...
- DP背包(一)
01背包 for(int i=0;i<n;i++) //遍历每一件物品 for(int j=v;j>=wei[i];j--)//遍历背包容量,表示在上一层的基础上,容量为J时,第i件物品装 ...
- IO与反射机制总结
IO与反射机制全面总结 一.file类:属于java.io包中kkb 作用:操作文件或目录 file既可以表示文件,也可以表示目录,也可以表示盘符.利用他可以用来对文件进行操作. file中常用的构造 ...
- 算法---BitMap
问题: 假设有3亿个整数(范围0-2亿),如何判断某一个树是否存在.局限条件一台机器,内存500m. 常规的思路:我们可以将数据存到一个集合中,然后判断某个数是否存在:或者用一个等长的数组来表示,每个 ...
- P2380狗哥采矿(状态不易设计)
描述:https://www.luogu.com.cn/problem/P2380 首先分析一下,易知传送带一定是要么向上,要么向右.且一定摆满了整个矩阵. 所以我们设 f [ i ] [ j ]表示 ...
- Oracle触发器之替代触发器
替代触发器 替代视图增删改操作.视图可以认为成逻辑上的一张表,类似于把一个sql语句的执行结果永久的像表存储到数据 库中,视图一般用来做查询. 创建视图的语法: create view 视图名称 as ...