龙空技术网

ARM 嵌入式编程与实战应用(STM32F1 系列)第4章RGB 舞台灯光

金沙滩工作室 2123

前言:

当前各位老铁们对“stm32控制灯泡”大约比较讲究,看官们都需要学习一些“stm32控制灯泡”的相关内容。那么小编同时在网摘上收集了一些有关“stm32控制灯泡””的相关资讯,希望看官们能喜欢,你们一起来学习一下吧!

上一章主要介绍了基本定时器中断的用法,本章将首先介绍在线仿真调试程序的方法,然后讲解STM32的位带操作,最后学习通用定时器的输出比较功能产生PWM,并且通过实用例程进一步强化实际产品开发能力。

4.1Keil在线仿真调试

51单片机程序相对简单,调试程序时依靠程序员根据实验现象做分析,改动程序进行逻辑验证的方式查找程序逻辑错误。随着要实现的功能越来越复杂,所选用的单片机从51单片机换到了STM32,所要编写的代码量也成倍增加,因此调试工具也要鸟枪换炮,采用ST-Link在线调试程序。

在线仿真调试就是将程序下载到系统中运行后,可以对程序进行逐步跟踪并且察看数据的变化。有了在线仿真调试功能,程序员可以测试每一行源代码,从而找出程序错误。在这个过程中,程序员可以通过设置断点,显示和监控内存内容、寄存器内容、控制输入输出等多种方式,从而找出错误根源。

在线仿真调试可以实现Keil软件和目标板的联调,更加直观了解单片机运行的过程,高效快速排查问题,从而提高产品和项目开发的效率。

4.1.1 软件配置

在所构建的工程模板中的system_stm32f10x.c文件中,有两段针对系统时钟的宏定义,如图4-1所示,用户选择哪个时钟就在图4-1左侧一段取消注释哪个时钟,其他时钟全部注释掉,这里系统默认用的是72MHz。

图4-1 系统时钟宏定义

在线调试仿真,Keil软件的配置信息必须要和实际目标板的运行时钟一致,因此在Debug选项卡中选择ST-Link仿真器,然后点击Settings按钮,如图4-2所示。

图4-2 debug窗口

打开Trace选项卡,在Core Clock处填写系统时钟72.000000MHz,如图4-3所示。

图4-3 设置硬件仿真时钟频率

当程序编译通过,显示0错误0警告的时候,选择菜单项Debug-->Start/Stop Debug Session,或者点击图4-4中红色方框内的按钮,进入在线仿真调试页面。

图4-4启动/结束仿真调试按钮

在程序窗口中显示代码行号的左侧灰色区域点击鼠标左键,设置断点(红色标记)。如图4-5所示:

1、Reset:为程序复位;

2、Run:为全速运行;

3、Step:为单步执行,一次执行一条语句。当遇到函数时就进入并且继续单步执行;

4、Step Over:也是单步执行,但它遇到函数时不会进入函数内部,而是直接执行整个函数;

5、Step Out:单步执行到函数内时,用step out就可以执行完函数余下部分,并返回到上一层函数。

点击全速运行,程序就会循环执行,如果设置了断点,每次运行到断点处就会停止。此时,可以通过点击view菜单,打开watch窗口,然后设定所要观察的变量和寄存器,当运行到断点处或者单步运行时,就可以观察出寄存器状态。

图4-5 Keil仿真界面

在实际项目和产品开发的过程中,调试程序功能往往是程序员的最重要的工作,而在线仿真调试这个功能非常重要,体现在可以帮助程序员快速查找定位问题和解决问题。这个重要的功能主要是针对逻辑错误查找的,因此难以举例演示,这个功能的重要性需要慢慢在开发中体会。

4.2位带操作

4.2.1 位带、位带识别区

前边操作STM32的GPIO时都是采用操作寄存器的方式,也就是一次性操作16位,这种方式编程比较复杂,单片机的执行效率也低。编写程序代码时,更多时候是操作一组GPIO中的某一位,而其它位不需要操作,这种情况下希望用更加简易的方式,不需要对16个口全部操作,就可以使用STM32的位带操作。

如果之前学过51单片机,对位带并不陌生。在51单片机中有一部分寄存器,可以直接对寄存器中的某一位进行读写;比如sbit LED = P1^0; LED = 0;再比如TR0 = 1;这些都是位带操作。除此之外,51单片机的内存地址20H到2FH这16个字节共128位的内存,是可以位操作的,其他内存地址只能字节操作。用C语言编程时,内存的位操作一般不直接使用,但可以直观的感受到寄存器的位操作。

STM32的位带在《Cortex-M3权威指南》资料中有详细介绍,可以进行位带操作的有两部分,分别是SRAM区的最低1MB范围和片内外设区的最低1MB范围。SRAM区1MB的内存一般编程的时候不常用,用的比较多的是片内外设区的最低1MB,也就是外设寄存器所在地址空间。

编程操作时,不方便对外设寄存器的某一位直接访问,因此在片内外设区另外开辟了一个32MB大小的寻址空间,取名为位带别名区。在这个地址空间中,每4个字节对应了位带区的一个位。有了这层关系,对位带别名区的某4个字节的操作,就等价于对这个地址对应的位带区的某一位的操作。

Cortex-M3的地址空间是4GB,片内外设的地址从0x40000000到0x5FFFFFFF共512MB。其中从0x40000000到0x40100000的地址空间是片内外设的1MB的位带区,从0x42000000到0x43FFFFFF是对应的32MB的位带别名区,如图4-6所示。

图4-6 片内外设地址

一般情况下,要改写某一个寄存器某一位的值,如果不采用位带操作,要分三步,第一步读出寄存器的值,第二步改变需要改变的那一位,第三步将改变后的值写进寄存器;而如果采用位带操作程序代码会更简单,代码执行效率也更高。

4.2.2 位带和位带别名区

编写代码时我们要操作某个寄存器的某一位,比如是GPIO的某一个IO口,那在程序中直接操作的就是相对应的位带别名区的一个32位的地址。首先确定要操作的寄存器的地址,也就是他的位带地址,然后确定要操作的是哪一位,最终根据映射关系计算出要操作的这一位所映射的位带别名区的地址。

统一用一个片上外设区和SRAM区的位带与位带别名区的映射公式:

1、其中addr表示的是外设寄存器的地址,bitnum表示的是要操作的这一位在这个寄存器的第几位。

2、(addr & 0xF0000000)+0x2000000区分的是片上外设区还是SRAM区的位带,片上外设区的位带地址是从0x40000000到0x40100000,SRAM区的位带地址是从0x20000000到0x20100000,大多数情况下只操作外设。

3、(addr &0x00FFFFFF)<<5)表示这一位所在的寄存器的第0位对应的位带别名区地址。由于位带区的一个寄存器是32位,因此映射到位带别名区就是32个字节,左移5相当于乘以32。

4、bitnum<<2是确定这一位相对于寄存器第0位对应的位带别名区地址的偏移地址。由于相对于寄存器的第0位,每偏移1个位,位带别名区就偏移4个字节,因此需要左移2位,相当于乘以4。

0x4001080C~0x4001080F表示的是GPIO端口A上"端口输出数据寄存器(ODR)" 4字节的地址空间。该寄存器的0~15位,对应端口A上的16个引脚。以0x4001080C地址空间中的第0位(0 bit)为例,它表示PA0引脚,通过膨胀关系,在位带别名区有一个4字节(32bit)大小的区域也表示PA0引脚,该区域的起始地址为0x42210180,如图4-7所示。之前我们是通过对ODR寄存器的第0位"置1",控制PA0引脚输出高电平,现在我们可以直接对PA0对应的位带别名区的地址空间置1,实现同样的功能,并且操作更简单,效率更高。

图4-7位带区与位带别名区的膨胀对应关系图

实际开发中,位带主要是应用在GPIO端口操作。将GPIO端口输入/输出数据寄存器的数据位通过公式找到对应的位带别名区地址,将代码保存在config.h文件中,若想使用位带操作,必须添加以下代码,之后的例程中默认在config.h中添加代码。具体代码如下:

通过上面位带设置程序,对IO口赋值时不必再使用"位设置"或"位清除"函数,而是可以像操作51单片机的IO口一样操作STM32的GPIO引脚。比如以PA1引脚为例,设置其为输出模式:

首先使用宏定义PA1对应的位带区地址,即: define PA1 PAout(1) 。其中PA1为宏定义的引脚名称,这个可以随意设置,PAout(1)才是关键,其中PA表示GPIO端口A,out表示输出模式,in表示输入模式;(1)表示引脚号。

通过这种操作,可以用PA1 = 1; 替代GPIO_SetBits(GPIOA, GPIO_Pin_1);

4.2.3 练习

将2.6,3.6.3,3.9小节中的程序,改为位带方式,重新编写一编,在此不再粘贴代码,具体代码可以到"Kingst-32F1开发板配套光盘\《ARM嵌入式编程与实战应用--STM32F1系列》例程\Lesson4"文件夹下查看。

4.3 RGB调色

在音乐广场、KTV、酒吧等场所,往往都有激情四射的舞台灯光,效果绚烂夺目,本小节通过开发一套简易舞台灯控制系统来提高读者的实际产品开发能力。

4.3.1 RGB调色原理

前边介绍过RGB小灯的发光原理,理论上三原色相互搭配,可以产生七色,如图4-8所示。有了七种颜色,就可以编程实现单色显示、单色渐变、渐变切换、单色闪烁、闪烁切换等复杂的功能,让简单的RGB小灯通过程序发挥出强大的功能。

图4-8 RGB调色

4.3.2 PWM脉宽调制

PWM是Pulse Width Modulation的缩写,它的中文名字是脉冲宽度调制,一种说法是它利用微处理器的数字输出来对模拟电路进行控制的一种有效的技术,其实就是使用数字信号达到一个模拟信号的效果。

首先从它的名字来看,脉冲宽度调制,就是改变脉冲宽度来实现不同的效果。我们先来看三组不同的脉冲信号,如图4-9所示。

图4-9 PWM波形

这是一个周期是10ms,即频率是100Hz的波形,但是每个周期内,高低电平脉冲宽度各不相同,这就是PWM的本质。在这里大家要记住一个概念,叫做"占空比"。占空比是指高电平的时间占整个周期的比例。比如第一个周期的占空比是40%,第二周期的占空比是60%,第三周期的占空比是80%,这就是PWM的解释。

如果我们用100Hz的信号,如4-9所示,假如高电平熄灭小灯,低电平点亮小灯的话,第一部分波形熄灭4ms,点亮6ms,亮度最高,第二部分熄灭6ms,点亮4ms,亮度次之,第三部分熄灭8ms,点亮2ms,亮度最低。通过定时器的输出比较功能,就可以实现PWM的脉冲宽度调制,来调整小灯的亮暗程度。

4.4 通用定时器调制PWM

4.4.1 通用定时器输出比较功能

STM32F103ZE拥有TIM2、TIM3、TIM4和TIM5共4个通用定时器。这4个定时器除了具备基本定时器的向上计数器功能外,还可以向下、向上/向下计数。此外还具备独立通道,能够实现输入捕获、输出比较、PWM输出、单脉冲输出等功能,其中输出比较模式用来控制输出一个波形,或者指示一段给定的的时间已经计到,这里所说的计到指的是设定一个比较值与计数器中的计数值进行对比,当计数值等于设定的比较值时表示设定的时间计到。比如设置定时器预分频值为7199,预装载值为99,向上计数,当启动定时器后,计数器开始从0计数到99共计10ms,然后溢出,重新计数。通过输出比较功能设定一个比较值为49,当计数器计数到49时会产生一个捕获/比较事件,告诉单片机已经计到比较值,此时可以控制IO口输出低电平,然后计数器继续计数到99,当计数器溢出时再设置IO口输出高电平。计数器从0计到49期间输出高电平,从50计到99之间输出低电平,每隔10ms循环一次,这就相当于输出了一个周期为10ms,占空比为50%的PWM信号。通过改变比较值的大小,就可以设定PWM的占空比。

STM32自带的PWM输出功能就是通过输出比较模式设定占空比信号,进而通过硬件控制通道引脚的电平状态。由于RGB小灯引脚没有连接到定时器的外部通道上,因为无法使用硬件PWM输出功能,但是依旧可以利用定时器的输出比较功能生成PWM,这比使用定时器控制IO口模拟产生PWM要精确很多。

已知每个通用定时器拥有4路捕获/比较通道,每路通道都拥有一个捕获/比较寄存器(TIMx_CCRx)用于装载比较值,该寄存器同样包含两个寄存器,一个是用户可以操作的,用于写入比较值,另一个用于和计数器进行比较的当前捕获/比较寄存器。如果设置了捕获/比较模式寄存器x(TIMx_CCMRx)中的输出比较预装载使能位(OCxPE),写入到TIMx_CCRx寄存器的比较值将在更新事件到来时才会传入到当前捕获/比较寄存器,否则比较值将立即写入当前捕获/比较寄存器,即写入的比较值立即生效,通常情况下默认使能输出比较预装载位,捕获/输入寄存器结构如图4-10所示。

图4-10 通用定时器捕获/比较通道结构图

当计数器与捕获/比较寄存器(TIMx_CCRx)中的内容相同时,如果设置了事件产生寄存器(TIMx_EGR)中的CCxG位,将会在通道上产生一个捕获/比较事件,若设置了相应的中断使能位(TIMx_DIER寄存器中的CCxIE位),则会产生一个捕获/比较中断。

配置通用定时器的输出比较功能步骤如下:

1、配置通用定时器的基本定时功能(参考3.6节基本定时器配制方法)

2、设置 TIMx 捕获/比较寄存器(CCRx)的预装载使能(x表示1、2、3、4)

3、设置 TIMx 捕获比较寄存器(CCRx)的值

4、设置NVIC中断优先级

5、清除TIMx更新中断及捕获/比较x中断标志位

6、使能TIMx更新中断和捕获/比较x的中断源

7、使能TIMx定时器

其中设置 TIMx 捕获/比较寄存器的预装载使能所用库函数如下:

上面四个库函数分别对应设置捕获/比较寄存器1、2、3、4的预装载使能,其中TIMx: x 可以是 2、3、4、5来选择 TIM 外设;TIM_OCPreload:输出比较预装载状态,参数如表4-1所示;

设置捕获比较寄存器(CCRx)的值所用到的库函数如下:

其中TIMx:x可以是 2、3、4、5,来选择 TIM 外设,CompareX(X表示1、2、3、4)设定的捕获/比较X寄存器新值。

关于设置捕获/比较中断源可以参考教程3.6.3小结表3-5,在此不再重复介绍。

4.4.2 RGB七色渐变实验

由于人眼视觉暂留效应,当小灯的闪烁频率为100Hz以上时,人眼基本分辨不出小灯在闪烁,因此PWM的频率要达到100Hz以上,假定PWM的频率为100Hz,其周期为1/100Hz=10ms,假设调节级别设定为256级,则每一级的时间约为39us,因此需要设定定时器的最小计数周期为39us。本节通过定时器TIM5的捕获/比较通道1、2、3分别控制R、G、B三个引脚的输出电平状态,产生三路PWM信号控制RGB刷新。上一章介绍了配置定时器TIM6定时1s进入中断,本节在上一章的基础上,设置定时器TIM5自动重装载值为255,预分频值为72*39-1,即计数周期为39us;设置TIM5捕获/比较通道1、2、3预装载使能,并使能对应中断。捕获/比较1、2、3寄存器的取值范围为0~255,对应256级调节亮度,当定时器TIM5计数到设定的捕获/比较x寄存器的数值时,触发捕获/比较x中断,在中断中设置RGB相应引脚输出高电平,熄灭小灯;当计数到255后产生定时器更新中断,设置RGB引脚输出低电平,点亮小灯。同时使用TIM6定时50ms刷新捕获/比较1、2、3寄存器中设定的比较值,控制RGB的亮度,实现七色渐变效果。

具体代码如下:

4.5 简易舞台灯控制系统

生活中经常能在荧幕或者舞台现场看到绚丽的舞台灯光,本节对实际舞台灯光效果进行了拆分,通过Kingst-32F1开发板自带的一个RGB小灯实现舞台灯光的各类显示效果。

4.5.1 舞台灯光控制程序

一、首先设计舞台灯光控制器的功能需求,如下所示:

1、单色闪烁显示模式&mdash;&mdash;实现红、绿、蓝、黄、紫、青、白七种颜色单独闪烁显示类型;

3、多色闪烁显示模式&mdash;&mdash;实现红绿、绿蓝、红蓝、红绿蓝间隔闪烁类型;

4、多色渐变显示模式&mdash;&mdash;实现红绿蓝三色渐变、红黄绿紫蓝青白七色渐变显示类型;

5、按键实现显示模式可调;

6、按键实现闪烁和渐变速度可调;

7、数码管显示当前RGB显示模式。

二、设置舞台灯光控制器的整体程序框架

1、功能划分

按键1: RGB模式选择按键;

范围1~13: 1-红光闪烁,2-绿光闪烁,3-蓝光闪烁,4-黄光闪烁,5-紫光闪烁,

6- 青光闪烁,7-白光闪烁,8-红绿交替闪烁,9-绿蓝交替闪烁,

10- 红蓝交替闪烁,11-红绿蓝交替闪烁,12-红绿蓝三色渐变,

13-红黄绿紫蓝青白七色渐变

按键2:调节闪烁或渐变速度逐渐变快

按键3:调节闪烁或渐变速度逐渐变慢

数码管:显示当前RGB灯光模式,使用数字1~13表示

三、编程程序代码

本节需要新建两个文本文件,保存在lighting.h和lighting.c,用于存放舞台灯光控制程序。

具体代码如下:

长按识别关注

知识共享|助力梦想

标签: #stm32控制灯泡