STM32F103C8T6+PWM+DMA驱动 WS2812灯带

2023-11-20

#STM32+PWM+DMA驱动 WS2812灯带

#文章目录

  • 1.理论:
  • 2代码:

理论:

1.WS2812参考数据手册:https://wenku.baidu.com/view/0925958fba68a98271fe910ef12d2af90342a80e.html
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.使用STM32F103C8T6驱动WS2812灯带,每个灯由24位组成三种颜色RGB,每8位控制一种颜色,颜色值0x00-0xFF。想要点亮一个灯需要将24位颜色值写入WS2812寄存器,如若点亮num个灯则需要写入 num24 位。根据数据手册可知还要加复位信号0(正常的0),因此需要写入 num24+reset(reset=?自己调) 位。

3.怎样发送num24+reset位数据呢? 由于WS2812的 0码 和 1码 并不是我们正常的 0 和 1,他是高低电平占不同的占空比,因此需要用PWM来模拟 0码 和 1码。当需要发送 0码 或 1码 时,我们只需要改变定时器的CCRx寄存器,来改变占空比,PWM频率800KHZ。
4.DMA则是搬运,将事先弄好的 num
24+reset位 对应的占空比值传送给 TIMx的CCRx寄存器。这样PWM输出的就是对应的颜色值了。

在这里插入图片11111111111111111111111111111111111111111111111111111111111描述
5.我之前使用的是TIM1_CH2对应的DMA1_Channel3通道行不通,因为这个找了好久原因。后面试了TIM1_UP对应的DMA1_Channel7通道就可以了。我也不知道为什么一定要用TIM1_UP事件,看网上也有用了非TIMx_UP事件的。

6.一般会出现的问题 1.PWM配置那里没配必须的那两句。2.DMA配置传输长度与定义的数组类型不符。3.DMA事件得要用TIMx_UP事件和其对应得通道。4.复位信号时间给的不够

代码:

/*-----------------------------------------  timer1 输出pwm --------------------------------------------------------*/
u16 LED_Buffer[2400];  //存放CCR值得数组
u8  color_buff[3] = {0x00,0x00,0xFF}//定义颜色GRB

#define    ONE     44    //我的对应CCR=44 为1码
#define    ZERO    22   //我的对应CCR=22 为0码

void Timer1_init(void)
{
	    TIM_TimeBaseInitTypeDef          TIM_TimeBaseStructure;
	    TIM_OCInitTypeDef                TIM_OCInitStructure;
	    GPIO_InitTypeDef                 GPIO_InitStructure;
	    DMA_InitTypeDef                  DMA_InitStructure;
		
		//clock
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
		
		//GPIO
	    GPIO_InitStructure.GPIO_Pin    = GPIO_Pin_9;
	    GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_AF_PP;
	    GPIO_InitStructure.GPIO_Speed  = GPIO_Speed_50MHz;
	    GPIO_Init(GPIOA, &GPIO_InitStructure);	
	    
	    //TIME
	    TIM_TimeBaseStructure.TIM_Period = 80-1; // 800kHZ   我时钟是64MHZ  64/80=800KHZ
	    TIM_TimeBaseStructure.TIM_Prescaler = 0;
	    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
	    
		//PWM
	    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
		TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Disable;//高级定时器这句一定要配
	    TIM_OCInitStructure.TIM_Pulse = 0; //CCRX寄存器值
	    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	    TIM_OC2Init(TIM1, &TIM_OCInitStructure);
		TIM_CtrlPWMOutputs(TIM1,ENABLE);
		TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);//使能预加载值,这句一定要配,不然时序会乱
	
	    //DMA
	    DMA_DeInit(DMA1_Channel5);
	    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(TIM1->CCR2);//设置CCR值
	    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)LED_Buffer;	//存放CCR值的数组
	    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;						
	    DMA_InitStructure.DMA_BufferSize = 240;
	    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;					
	    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//这里传输的是多少位,根据你定义的存放CCR值得数据类型,我是u16
	    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//这里传输的是多少位,根据你定义的存放CCR值得数据类型,我是u16
	    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;							
	    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	    DMA_Init(DMA1_Channel5, &DMA_InitStructure);
	   
	   	//这里我之前用的是TIM_DMA_CC2  对应的DMA1_Channel3通道行不通 ,具体为何我也不知道,后面使用TIM_DMA_Update 对应的DMA1_Channel5
	    TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
		TIM_Cmd(TIM1, DISABLE);
}


/*---------- 组包 将颜色位 转变成CCR值  发送颜色顺序GRB高位先发   我这里所有的灯都一样的颜色要不一样的自己改下面的-----------*/
void WS2812_led_send(uint8_t *color, uint16_t len)
{
    uint8_t i;
    uint16_t memaddr;
    uint16_t buffersize;
	memset(LED_Buffer,0,2400);
    buffersize = (len*24)+400;	//颜色位数+复位信号
    memaddr = 0;				
    while(len)
    {
        for(i=0; i<8; i++) // GREEN 
        {
            LED_Buffer[memaddr] = ((color[0]<<i) & 0x80) ? ONE:ZERO;
            memaddr++;
        }

        for(i=0; i<8; i++) // RED
        {
            LED_Buffer[memaddr] = ((color[1]<<i) & 0x80) ? ONE:ZERO;
            memaddr++;
        }

        for(i=0; i<8; i++) // BLUE
        {
            LED_Buffer[memaddr] = ((color[2]<<i) & 0x80) ? ONE:ZERO;
            memaddr++;
        }

        len--;
    }

    DMA_SetCurrDataCounter(DMA1_Channel5, buffersize); 	//下面这几句的顺序,不同型号MCU可能也会不同
    DMA_Cmd(DMA1_Channel5, ENABLE); 			
    TIM_Cmd(TIM1, ENABLE); 					
    while(!DMA_GetFlagStatus(DMA1_FLAG_TC5)) ; 	
    TIM_Cmd(TIM1, DISABLE); 	
    DMA_Cmd(DMA1_Channel5, DISABLE); 			
    DMA_ClearFlag(DMA1_FLAG_TC5); 			
}


int  main(void)
{
	Timer1_init();
		
	while(1)
	{
	  WS2812_led_send(color_buff,10);
	  delay_ms(5);
	}
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F103C8T6+PWM+DMA驱动 WS2812灯带 的相关文章

  • Java+MyEclipse+Tomcat (三)配置MySQL及查询数据显示在JSP网页中

    前面两篇文章讲述了如何配置MyEclipse和Tomcat开发JSP网站 如何配置Servlet简单实现表单提交 这篇文章主要讲述配置MySQL实现数据库连接MyEclipse 最后将查询表中的数据显示在JSP网页中 文章主要以图片描述为主
  • Java 多线程编程(入门)

    目录 一 简单介绍 Thread类 1 Thread类中一些常用的方法 2 编写一个简单多线程程序 入门 二 Java中创建多线程的方法 重点面试题 1 继承 Thread 类 2 实现 Runnable 接口 重写 run 3 使用匿名内
  • 00.mipi协议

    mipi差分信号原理 理解mipi协议 MIPI DSI LP mode命令及格式详解 MIPI信号的分析 结合示波器实际测试波形 MIPI 移动行业处理器接口 是Mobile Industry Processor Interface的缩写
  • onlyoffice报 error self signed certificate导致download failed错误处理

    安装nextcloud onlyoffice 打开onlyoffice报错 进入容器看out log报错信息 root nextcloud docker ps a Emulate Docker CLI using podman Create
  • HTTP请求详解

    HTTP概念 HTTP全称是HyperText Transfer Protocal 即超文本传输协议 是应用层协议 当你上网浏览网页的时候 浏览器和web服务器之间就会通过HTTP在Internet上进行数据的发送和接收 HTTP是一个基于

随机推荐

  • PHP 两个二维数组求不同

    public function arrcha arr1 0 id gt 1 name gt name arr1 1 id gt 2 name gt name2 arr1 2 id gt 3 name gt name3 arr1 3 id g
  • JNI入门基础

    环境安装 想要使用jni进行ndk开发 我们首先要安装下面这些工具 否则直接从入门到放弃 下载ndk支持 在Android studio中下载上图中框选的两个工具 版本号自己任意选一个 下载完成之后 Android Studio就拥有了进行
  • 类模板函数特化(专用化)specialization of …… after instantiation

    http stackoverflow com questions 7774188 explicit specialization after instantiation http blog csdn net xcysuccess3 arti
  • [ASP.NET MVC 小牛之路]05 - 使用 Ninject

    在 ASP NET MVC 小牛之路 系列上一篇文章 依赖注入 DI 和Ninject 的末尾提到了在ASP NET MVC中使用Ninject要做的两件事情 续这篇文章之后 本文将用一个实际的示例来演示Ninject在ASP NET MV
  • Spring Boot框架

    目录 一 Spring Boot 1 Spring Boot优点 2 创建Spring Boot 3 Spring Boot配置文件 1 配置文件的作用 2 properties文件格式 3 yml文件的格式 4 properties vs
  • 程序员升职记 全关卡攻略&通俗思路 Human Resource Machine

    程序员升职记 全过关方法 通俗思路 博主本着能过就过的思想 写出的解答必然不是最优解 但是可以给大家提供一点思路来参考 其中17和22的解答整理自网络 特别是17的解答 要比博主的原解答巧妙不少 1 收发室 模拟程序输入输出 HUMAN R
  • 深度学习大模型训练--分布式 deepspeed PipeLine Parallelism 源码解析

    deepspeed PipeLine Parallelism 源码解析 basic concept PipeDream abstract 1F1B 4 steps Code comprehension in deepspeed prepar
  • 再论FreeRTOS中的configTOTAL_HEAP_SIZE

    关于任务栈和系统栈的基础知识 可以参考之前的随笔 FreeRTOS 任务栈大小确定及其溢出检测 这里再次说明 define configTOTAL HEAP SIZE size t 17 1024 这个宏 官方文档解释 configTOTA
  • powervm虚拟化分析

    powervm是IBM推出的适用于power系列服务器的虚拟化技术 有其独特的功能和技术 本文和大家一起探讨一下 首先power是ibm处理器的名字 也常常用来标识ibm服务器的型号 常见的power7 power8小型机就是指期cpu是p
  • 启锐 588 打印机每次打印都流出一部分,没有重新切换纸张

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 588 488识别纸张 一 打印机关机 数据线拔掉 二 把纸拿出来 开机之后盖上盖子 三 然后把纸从机器后面塞进去让机器自动吸纸 四 然后长按打印机上面蓝色的按键 听到滴的
  • Java基础之随机生成数字和字母

    原文地址 http blog csdn net yaodong y article details 8115250 字母与数字的ASCII码 目 前计算机中用得最广泛的 字符集及其编码 是由美国国家标准局 ANSI 制定的ASCII码 Am
  • OpenGL视图变换及gluLookAt

    视图变换 即相机变换 其作用是把相机放在指定位置并使其对准场景 该变换是针对相机的变换 不会影响到模型 视图变换决定了相机的位置与方向 因此可以通过视图变换来改变相机位置与方向 从而达到从各个不同的位置与角度来观察同一个物体的情形 进行视图
  • SHAP显示原始特征

    1 问题描述 SHAP用于特征解释 对于机器学习方法往往需要对原始特征进行编码 而SHAP在绘制单个样本时 会显示每个特征及其取值 而这个取值已经是编码后的 通常无法确定其含义 如 下图所示的拍卖公司 城市和作者信息 预期达到的效果 2 实
  • 【西瓜书】4-决策树

    文章目录 4 1 基本流程 4 2 划分 4 2 1 信息增益 ID3 4 2 2 信息增益率 C 45 4 2 3 基尼指数 CART 4 3 剪枝处理 4 4 连续与缺失值 4 4 2 连续值处理 4 4 1 缺失值处理 4 5 多变量
  • Anchor是什么?

    1 选择性搜索 Selective Search 先介绍一下传统的人脸识别算法 是怎么检测出图片中的人脸的 以下图为例 如果我们要检测图中小女孩的人脸位置 一个比较简单暴力的方法就是滑窗 我们使用不同大小 不同长宽比的候选框在整幅图像上进行
  • crmeb重新安装_手动安装教程 · CRMEB 知识付费版 帮助文档 · 看云

    手动安装 1 创建数据库 倒入数据库文件 数据库文件目录 public install zhishifufei sql 2 修改数据库连接文件 配置文件路径 application database php 数据库类型 type gt my
  • vagrant启动openshift

    1 Install Vagrant 2 Install VirtualBox Ex yum install VirtualBox from the RPM Fusion repository 3 In your bashrc file or
  • 元胞自动机算法汇总含matlab代码_数学建模(十三)

    元胞自动机理论 许多复杂的问题都可以通过元胞自动机来建立模型 元胞自动机实质上是定义在一个具有离散 有限状态的元胞组成的元胞空间上 并按照一定的局部规则 在离散的时间维度上演化的动力学系统 元胞又可称为单元 细胞 是元胞自动机的最基本的组成
  • 【hortonworks/registry】registry 如何添加新的类型 支持 json

    1 概述 hortonworks registry 支持json 但是要自己扩展 有相关接口 支持基本类型 支持自定义对象类型 支持集合类型 map array null 支持嵌套结构 registry支持的数据类型有好几种 其中有Avro
  • STM32F103C8T6+PWM+DMA驱动 WS2812灯带

    STM32 PWM DMA驱动 WS2812灯带 文章目录 1 理论 2代码 理论 1 WS2812参考数据手册 https wenku baidu com view 0925958fba68a98271fe910ef12d2af90342