我在此分享一份DMX512协议的发送程序,希望对做灯光控制的人有一定的帮助(我测试过了跟DMX512控制台发出的方波是一样一样的)

2019-07-21 06:09发布

 这是DMX512发送的数据帧格式

我是做灯光控制的,但是涉及到DMX512协议我就一窍不通,所以赶紧在网上找相关的资料来恶补一下,就在网上了解DMX512协议是只发或只接收,是单向的,但是要处理好起始标志否则你接收不到正确数据!
数据位是9位,1位停止位,无奇偶校验,无硬件流,波特率固定是250000;
以下是模拟DMX512发出的数据帧,接收程序在网上一搜就有~
有需要DMX512接收程序的跟我说下,我就会把它贴出来分享给大家!
走过路过千万不要错过,希望大家看到的能帮忙为这个贴留个言,把帖顶起来让更多像我一样初学者能少走一些弯路把项目做好!
(非常喜欢原子的开源精神,希望大家能把原子的论坛炒热起来,这样路过的大神就能在这多分享一些好东西,我们这些初学者也就能多多学习一些知识!谢谢大家!)

u8 TXDData[530]; //接收缓冲区200个数据

/************************************************************
*函数名称:void uart2_init(u32 bound)
*功    能:串口2初始化函数
*说    明:初始化IO 串口2
*输入参数:bound=波特率
*输出参数:无
*************************************************************/
void uart2_init(u32 bound) //串口2初始化函数
{
//GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);  //使能USART2
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); //使能引脚复用,GPIOA时钟
 
  USART_DeInit(USART2);  //复位串口2

//USART2_TX   PA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA2

//USART2_RX  A.3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA3

  //USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;         //一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;           //字长为8位数据格式
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; //收发模式
USART_Init(USART2, &USART_InitStructure); //初始化串口2

//USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启接收中断  
//USART_ITConfig(USART2, USART_IT_TXE, ENABLE); //开启发送中断
USART_Cmd(USART2, ENABLE);                    //使能串口2
}

/*******************************************************************************
* 函数名称:void DMX_init(void)
* 功能描述:DMX512初始化
* 参数含义:无
* 备    注: 无
*********************************************************************************/
void DMX_init(void) //DMX512初始化
{
int i;
  TXDData[0] = 0; //起始码00
  for(i = 1; i<=512; i++)
  {
     TXDData = 0;
  }
uart2_init(250000);//串口2初始化函数->发送DMX512
}
/*******************************************************************************
* 函数名称:void GPIO_Tx_Normal_Config(void)
* 功能描述:发送引脚变为普通IO
* 参数含义:无
* 备    注: 无
*********************************************************************************/
void GPIO_Tx_Config(u8 Set)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  
  //设置发送的引脚为普通IO
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
if(0 == Set)
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //普通IO
}
else
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用IO
}
  GPIO_Init(GPIOA, &GPIO_InitStructure); //引脚初始化
}
/*******************************************************************************
* 函数名称:void DMX_SendPacket(void)
* 功能描述:DMX512发送数据 
* 参数含义:无
* 备    注: 无
*********************************************************************************/
void DMX_SendPacket(void) //发送DMX512数据
{
//配置为普通IO
pDMX_buf = 0; /*发送起始码 00*/
GPIO_Tx_Config(0); //设置发送的引脚为普通IO
PA2 = 0; //输出低电平
delay_us(150); //延时150us
PA2 = 1; //输出高电平
delay_us(13); //延时13us
GPIO_Tx_Config(1); //设置发送的引脚为复用IO

  //USART1->DR = 0x0100 | TXDData[0]; //第0帧前导码
  //while((USART2->SR&0X40)==0);//循环发送,直到发送完毕
IWDG_ReloadCounter();    //喂狗
while(pDMX_buf <= 18) //1-512 195
  {
while((USART2->SR&0X40)==0);//等待,直到发送完毕
    if(USART2->SR & (1<<6))
    { 
       
USART2->DR = 0x0100 | TXDData[pDMX_buf];
       pDMX_buf++;
    }  
  }
}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
41条回答
ruoshui215113
1楼-- · 2019-07-25 17:49
楼主 把接收的发一下呗 急需  跪谢
潜龙探渊
2楼-- · 2019-07-25 23:43
 精彩回答 2  元偷偷看……
潜龙探渊
3楼-- · 2019-07-26 01:14
/************************************************************
*函数名称:void uart2_init(u32 bound)
*功    能:串口2初始化函数
*说    明:初始化IO 串口2
*输入参数:bound:波特率
*输出参数:无
*************************************************************/
void uart2_init(u32 bound) //串口2初始化函数
{
//GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
         
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);  //使能USART2
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);         //使能引脚复用,GPIOA时钟

        USART_DeInit(USART2);  //复位串口2
       
        //USART2_TX   PA.2
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
        GPIO_Init(GPIOA, &GPIO_InitStructure);                 //初始化PA2

        //USART2_RX          PA.3
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //PA3
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
        GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA3

  //Usart2 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;  //抢占优先级2
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                         //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                   //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
  
  //USART 初始化设置
        USART_InitStructure.USART_BaudRate                                                 = bound;                                                                         //一般设置为9600;
        USART_InitStructure.USART_WordLength                                         = USART_WordLength_9b;           //字长为8位数据格式
        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; //收发模式
        USART_Init(USART2, &USART_InitStructure);                 //初始化串口2
       
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启接收中断                                                                         //接收个数清零
        USART_Cmd(USART2, ENABLE);                    //使能串口2
}

/************************************************************
*函数名称:void USART2_IRQHandler(void)  
*功    能:串口中断函数
*说    明:串口2中断服务程序
*************************************************************/
void USART2_IRQHandler(void)                        //串口2中断服务程序
{
        static u16 UDR=0;
        static u16 RXB8=0;
        static uint16_t pDMX_buf = 0;  //数据指针
        static uint8_t fDMX_buf_right = 0;

        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//USART_FLAG_RXNE
        {
                IWDG_ReloadCounter();    //喂狗
                UDR  = USART_ReceiveData(USART2);  //16bit  0-8  9bit
                RXB8 = (UDR&0x0100);  //得到第9位数据

                if(RXB8 == 0) //如果是复位信号
                {   
                        if(!UDR) //如果数据为0
                        {
                    fDMX_buf_right = 1; //接收数据正确
                                pDMX_buf = 0;       //直接接收第一个数据,不保存第0个数据
                  }
                }
                else  //rxb8=1 pDMX_buf =1 调光数据
                {
                         if(1 == fDMX_buf_right)
                         {
                     RXDData[pDMX_buf++] = (u8)UDR; //得到8位的数据
                                 //接收到0-192个数据
                                 if(pDMX_buf > 20)
                                 {
                                                fDMX_buf_right = 0;
                                                DMXSignalFlag = 1;                 //更新调光数据
                                 }
                   }
                }
        }
//--------------------------------接收中断---------------------------------------------       
  if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)
  {   
      // Disable the USART2 Transmit interrupt
      USART_ITConfig(USART2, USART_IT_TXE, DISABLE);         //清中断 要不然一直执行此中断 OK
  }
}
ruoshui215113
4楼-- · 2019-07-26 05:47
潜龙探渊 发表于 2016-11-10 09:52
哦,那我要找一下了,因为太久了程序都不知道放哪里啦

主要通过485接受DMX数据,DMX512中break的88us和MAB的8us如何处理判断
ioremap
5楼-- · 2019-07-26 10:26
为什么发送的时候IO需要变为普通Io
潜龙探渊
6楼-- · 2019-07-26 12:21
ioremap 发表于 2017-10-31 11:37
为什么发送的时候IO需要变为普通Io

因为要发送头帧的波形

一周热门 更多>