STM32F103VG使用RTT实现发送DMX512调光数据

DMX512调光协议和DALI一样属于数字调光协议,一个完整的DMX512数据包格式:1break+1mab+1startcode+512个调光数据。

DMX512发送是基于485串口的基础上实现的特殊的数据协议。

使用RTT需要把串口打开并且定义好相应的定义,这里不再赘述;因RTT的部分外设初始化不完善,本次使用的HAL库进行初始化部分。

实现步骤:

1.初始化GPIO口,使能485串口的3.3v以及使能为发送模式,这个根据实际需求进行初始化

/*
 * 初始化dmx512所要用到的pin,打开485的3.3v以及使能发送模式   PC8 3.3v, PC9 模式控制
 * */
int dmx512_pin_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOC_CLK_ENABLE();

     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET);

     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);

     /*Configure GPIO pins : PC7 PC8 PC9 */
     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

     return RT_EOK;
}

2.初始化要用到的485串口,数据位9,波特率250000

/*
 * 初始化dmx512所要用到的uart4
 * */
int dmx512_uart_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_UART4_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    huart4.Instance = UART4;
    huart4.Init.BaudRate = 250000;
    huart4.Init.WordLength = UART_WORDLENGTH_9B;
    huart4.Init.StopBits = UART_STOPBITS_1;
    huart4.Init.Parity = UART_PARITY_NONE;
    huart4.Init.Mode = UART_MODE_TX_RX;
    huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart4.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart4);

    return RT_EOK;
}

3.写一个切换串口引脚功能的函数,用于形成break和mab信号

/*
 * 切换dmx512发送pin脚的模式
 * */
int dmx512_pin_mode(int mode)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    if(mode)    //mode=1,当串口发送用,在dmx512发送中主要用于发送数据帧
    {
        GPIO_InitStructure.Pin = GPIO_PIN_10;
        GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; //复用推挽输出
        GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
    }
    else if(mode == 0)//mode=0,当普通io用,在dmx512发送中主要用来形成break和mab信号
    {
        GPIO_InitStructure.Pin = GPIO_PIN_10;
        GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;  //推挽输出
        GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
    }
    return RT_EOK;
}

4.写DMX512的数据发送函数,定义全局变量 int pDMX_buf、char dmx_buf[513]

/*
 * dmx512发送数据函数
 * */
int dmx512_send_frame(void)
{
    dmx512_pin_mode(0);
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, 0);
    rt_hw_us_delay(100);
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, 1);
    rt_hw_us_delay(10);
    dmx512_pin_mode(1);

    for(pDMX_buf = 0; pDMX_buf <= 512; pDMX_buf++)  //0:startcode   1-512:调光数据
    {

        if(pDMX_buf == 0)
        {
            UART4->DR = 0x00 | 0x100;//第一帧startcode
            while((UART4->SR & 0X40) == 0); //确保数据发送完成
        }

        else
        {
            UART4->DR = 0x100 | dmx_buf[pDMX_buf];
            while((UART4->SR & 0X40) == 0);     //确保数据发送完成
        }

    }
    return RT_EOK;
}

5.写一个DMX512的初始化函数,可以把前面的初始化的所有函数放进去并开启线程用于发送DMX512数据

*
 * 包含了dmx512所用到的所有初始化,并开启线程发送dmx512数据
 * */
int dmx512_init(void)
{
    int ret = RT_EOK;
    dmx512_pin_init();
    dmx512_uart_init();
    /* 创建 serial 线程 */
    rt_thread_t thread = rt_thread_create("dmx512", dmx512_send_thread, RT_NULL, 1024, 25, 10);
    /* 创建成功则启动线程 */
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        ret = RT_ERROR;
    }

    return ret;
}

6.实现线程函数,每隔400ms发送一个DMX512数据包

/*
 * dmx512数据发送线程,dmx512数据需要持续发送而且必须在1S内发送下一条
 * */
static void dmx512_send_thread(void *parameter)
{
    while(1)
    {
        dmx512_send_frame();
        rt_thread_mdelay(400);
    }

}

7.将dmx512_init放到MAIN中执行即可。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于驱动电机,你可以参考以下步骤: 1. 首先,你需要创建一个STM32F103C8T6的工程,并配置时钟树。你可以使用STM32CubeMX来创建并调整工程结构\[1\]。 2. 接下来,你需要编写GPIO驱动程序,以控制电机的引脚。你可以参考《STM32F10xxx闪存编程手册》中的GPIO章节来了解如何编写GPIO驱动程序\[2\]。 3. 在编写GPIO驱动程序之后,你可以编写延时函数,以实现电机的延时操作。你可以详细了解Systick定时器,并编写相应的延时函数\[1\]。 4. 最后,你可以使用RTT(Real Time Transfer)技术进行串口通信,以便进行电机的测试和调试。RTT是SEGGER公司推出的一种共享内存技术,可以方便地进行串口数据测试\[3\]。 需要注意的是,以上步骤只是一个简单的指导,具体的驱动电机的实现还需要根据你的具体需求和电机的类型进行相应的调整和编写。 #### 引用[.reference_title] - *1* *2* [从头开始写STM32F103C8T6驱动库(二)——编写系统初始化程序,配置时钟树](https://blog.csdn.net/Pluto0617/article/details/122615354)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [STM32F103C8T6单片机简介](https://blog.csdn.net/fantastic_sky/article/details/110229474)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值