最近把玩了一下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协议发送与接收(非标)的更多相关文章

  1. java-TCP协议发送和接收数据

    TCP协议接收数据的步骤: A:创建接收数据的Socket对象 创建对象的时候要指定端口 B:监听客户端连接 等待客户端连接 C:获取Socket对象的输入流(字节流) D:读数据,并显示在控制台 E ...

  2. 【Java】学习路径56-TCP协议 发送、接收

    与UDP不同的是,TCP协议使用的是Socket,而不是DatagramSocket,这是要作区分的. 构造Socket对象的时候,可以直接指定ip地址与端口号.此时需要抛出异常. import ja ...

  3. PHP+socket+SMTP、POP3协议发送、接收邮件

    .实现SMTP协议的类dsmtp.cls.php:<?php            , $webname=).);     } } .实现POP3协议的类dpop3.cls.php: <? ...

  4. java实现http协议发送和接收数据

    public void sendMessage() throws Exception { System.out.println("调用servlet开始=================&q ...

  5. Java基础知识强化之网络编程笔记06:TCP之TCP协议发送数据 和 接收数据

    1. TCP协议发送数据 和 接收数据 TCP协议接收数据:• 创建接收端的Socket对象• 监听客户端连接.返回一个对应的Socket对象• 获取输入流,读取数据显示在控制台• 释放资源 TCP协 ...

  6. Java基础知识强化之网络编程笔记03:UDP之UDP协议发送数据 和 接收数据

    1. UDP协议发送数据 和 接收数据 UDP协议发送数据: • 创建发送端的Socket对象 • 创建数据,并把数据打包 • 调用Socket对象的发送方法,发送数据包 • 释放资源  UDP协议接 ...

  7. udp协议的数据接收与发送的代码

    我想基于lwIP协议中的UDP协议,用单片机做一个服务器,接受电脑的指令然后返回数据.以下是我的代码 /************************************************ ...

  8. 网络编程--使用TCP协议发送接收数据

    package com.zhangxueliang.tcp; import java.io.IOException; import java.io.OutputStream; import java. ...

  9. SMTP协议及POP3协议-邮件发送和接收原理(转)

    本文转自https://blog.csdn.net/qq_15646957/article/details/52544099 感谢作者 一. 邮件开发涉及到的一些基本概念 1.1.邮件服务器和电子邮箱 ...

随机推荐

  1. Spring Boot devtool的使用

    文章目录 添加Spring Boot devtool依赖 默认属性 自动重启 Live Reload 全局配置 Spring Boot devtool的使用 Spring Boot为我们提供了一个便捷 ...

  2. HTML JavaScript 基础(下)

    一.JavaScript 函数 1.普通函数-有函数名 function func(){ } 2.匿名函数-无函数名 setInterval(function(){ console.log(123); ...

  3. CSS开发技巧(四):解决flex多行布局的行间距异常、子元素高度拉伸问题

    在使用flex布局时,若出现换行,有两种较为特殊的现象是值得我们研究的: 子元素高度被拉伸,其实际高度大于它的内容高度. 各行子元素之间的行间距过大,甚至我们根本没有给子元素设置margin. 现在我 ...

  4. Babel 在浏览器环境使用方法

    Babel 也可以用于浏览器环境.但是,从 Babel 6.0 开始,不再直接提供浏览器版本,而是要用构建工具构建出来.如果你没有或不想使用构建工具 1.通过安装5.x版本的babel-core模块获 ...

  5. linux-网络管理(常用命令)

    网络查看 ifconfig : 查看与临时配置网络 ifdown 网卡设备名 : 关闭网卡 ifup 网卡设备名 : 启用网卡 netstat 网络状态查询 -t 列出TCP协议端口 -u 列出UDP ...

  6. 字符串后面空字符的问题(char*与string的转换)

    今天AC了不少题,困扰已久的Time limit error 也解决了,记住下次用STL容器的时候一定要清空容器. 其次是字符数组与字符串的浅谈. 字符数组是以'\0'结尾的,所以在字符数组赋值给字符 ...

  7. 第十届山东省赛L题Median(floyd传递闭包)+ poj1975 (昨晚的课程总结错了,什么就出度出度,那应该是叫讨论一个元素与其余的关系)

    Median Time Limit: 1 Second Memory Limit: 65536 KB Recall the definition of the median of elements w ...

  8. spring注入bean的几种策略模式

    上篇文章Spring IOC的核心机制:实例化与注入我们提到在有多个实现类的情况下,spring是如何选择特定的bean将其注入到代码片段中,我们讨论了按照名称注入和使用@Qualifier 注解输入 ...

  9. Hadoop入门学习笔记-第二天 (HDFS:NodeName高可用集群配置)

    说明:hdfs:nn单点故障,压力过大,内存受限,扩展受阻.hdfs ha :主备切换方式解决单点故障hdfs Federation联邦:解决鸭梨过大.支持水平扩展,每个nn分管一部分目录,所有nn共 ...

  10. B - Save the problem! CodeForces - 867B 构造题

    B - Save the problem! CodeForces - 867B 这个题目还是很简单的,很明显是一个构造题,但是早训的时候脑子有点糊涂,想到了用1 2 来构造, 但是去算这个数的时候算错 ...