PWM信号生成对于每个嵌入式工程师来说都是至关重要的工具,它们在许多应用中非常方便,例如控制伺服电机的位置,在转换器/逆变器中切换很少的功率电子IC甚至是简单的LED亮度控制。在PIC微控制器中,可以通过设置所需的寄存器使用 比较,捕获和PWM (CCP)模块生成PWM信号,我们已经在PIC PWM教程中学习了如何做到这一点。但是这种方法有一个很大的缺点。
该PIC16F877A只能在引脚RC1和RC2产生PWM信号,如果我们使用CCP模块。但是我们可能会遇到这样的情况,即我们需要更多的引脚才能具有PWM功能。例如,对于我的机器人手臂项目,我想控制6台RC伺服电机,而CCP模块对此毫无希望。在这些情况下,我们可以使用定时器模块对GPIO引脚进行编程,以产生PWM信号。这样,我们可以通过任何所需的引脚生成尽可能多的PWM信号。还有其他一些硬件黑客,例如使用多路复用器IC,但是为什么可以通过编程在硬件上进行投资呢?因此,在本教程中,我们将学习如何将PIC GPIO引脚转换为PWM引脚,并对其进行测试,我们将使用数字示波器在proteus上对其进行仿真,并且通过PWM信号控制伺服电机的位置,并通过改变电位器来改变其占空比。
什么是PWM信号?
在开始讨论细节之前,让我们回顾一下什么是PWM信号。脉冲宽度调制(PWM)是一种数字信号,最常用于控制电路中。该信号在预定义的时间和速度中设置为高(5v)和低(0v)。信号保持高电平的 时间 称为 “开启时间” ,信号保持低电平的 时间 称为 “关闭时间”。 如下所述,PWM有两个重要参数:
PWM的占空比
PWM信号保持高电平(导通时间)的时间百分比称为占空比。如果信号始终为ON,则占空比为100%;如果信号始终为OFF,则占空比为0%。
占空比=打开时间/(打开时间+关闭时间)
变量名称 |
指 |
PWM_Frequency |
PWM信号的频率 |
T_TOTAL |
一个完整的PWM周期花费的总时间 |
吨 |
PWM信号的接通时间 |
T_OFF |
PWM信号的关闭时间 |
占空比 |
PWM信号的占空比 |
现在,让我们做一下数学。
这是标准公式,其中频率只是时间的倒数。频率值必须由用户根据其应用要求来决定和设置。
T_TOTAL =(1 / PWM_频率)
当用户更改占空比值时,我们的程序应根据此值自动调整T_ON时间和T_OFF时间。因此,以上公式可用于基于Duty_Cycle和T_TOTAL的值来计算T_ON。
T_ON =(占空比* T_TOTAL)/ 100
由于PWM信号在一个完整周期内的总时间将是导通时间与关闭时间的总和。我们可以如上所述计算关闭时间T_OFF。
T_OFF = T_TOTAL – T_ON
牢记这些公式,我们就可以开始对PIC单片机进行编程了。该程序涉及PIC定时器模块和PIC ADC模块,以根据来自POT的ADC值创建具有变化占空比的PWM信号。如果您不熟悉这些模块,那么强烈建议您通过单击超链接阅读相应的教程。
编程PIC以在GPIO引脚上生成PWM
像往常一样,可以在网站底部找到本教程的完整程序。在本节中,让我们了解程序的实际编写方式。像所有程序一样,我们从设置配置位开始。我已使用“内存视图”选项为我设置了它。
// CONFIG #pragma config FOSC = HS //振荡器选择位(HS振荡器) #pragma config WDTE = OFF //看门狗定时器使能位(禁止WDT) #pragma config PWRTE = OFF //上电定时器使能位(PWRT禁用) #pragma config伪BOREN = ON //欠压复位使能位(使能BOR) #pragma config伪LVP = OFF //低电压(单电源)在串行编程使能位(RB3是数字I / O ,必须使用MCLR上的HV进行编程) #pragma config CPD = OFF //数据EEPROM存储器代码保护位(Data EEPROM编码保护关闭) #pragma config WRT = OFF //闪存程序存储器写使能位(写保护关闭; EECON控制可以写入所有程序存储器) #pragma config CP = OFF //闪存程序存储器代码保护位(代码保护关闭) // #pragma config语句应在包含项目文件之前。 //使用项目枚举代替#define进行ON和OFF。 #包括
然后我们提到硬件中使用的时钟频率,这里我的硬件使用20MHz晶体,您可以在硬件中输入值。其次是PWM信号的频率值。由于我的目标是控制需要50Hz PWM频率的业余RC伺服电机,因此我将0.05KHz设置为频率值,您也可以根据您的应用要求进行更改。
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0.05 // in KHz(50Hz)
现在,我们有了频率的值,可以使用上面讨论的公式来计算T_TOTAL。将结果除以10即可得出以毫秒为单位的时间值。在我的情况下,T_TOTAL的值为2毫秒。
int T_TOTAL =(1 / PWM_Frequency)/ 10; //根据频率计算总时间(以毫秒为单位)// 2msec
随后,如ADC PIC教程中所述,我们初始化ADC模块以读取电位计的位置。接下来,我们有一个每次都会调用的中断服务例程,定时器溢出,稍后我们将返回到此,现在让我们检查主要功能。
在主要功能中,我们配置了计时器模块。在这里,我已配置定时器模块每隔0.1ms溢出一次。时间值可以使用以下公式计算
RegValue = 256-((Delay * Fosc)/(Prescalar * 4))延迟,以秒为单位,Fosc以hz为单位
对于我来说,如果预分频为64且Fosc为20MHz,延迟时间为0.0001秒(0.1ms),则我的寄存器(TMR0)的值应为248。因此配置如下所示
/ *****定时器的端口配置****** / OPTION_REG = 0b00000101; //具有外部频率和64作为预分频器的Timer0 //还使能PULL UP TMR0 = 248; //加载时间值0.0001s;delayValue只能在0-256之间,只有 TMR0IE = 1;//使能PIE1寄存器 GIE = 1的 定时器中断位;//启用全局中断PEIE = 1; //启用外围中断 / *********** ______ *********** /
然后我们必须设置输入和输出配置。在这里,我们使用AN0引脚读取ADC值,使用PORTD引脚输出PWM信号。因此,请使用下面的代码行将其初始化为输出引脚,并使它们变为低电平。
/ ***** I / O的端口配置****** / TRISD = 0x00; //指示MCU PORT D上的所有引脚都输出 PORTD = 0x00; //将所有引脚初始化为0 / *********** ______ *********** /
在无限 while 循环内,我们必须根据占空比计算接通时间(T_ON)的值。在 时间 和 值班 周期变化的基础上锅的,所以我们做了多次内部的位置 ,而 环如下图所示。0.0976是必须乘以1024以获得100的值,并且要计算T_ON,我们已经将其乘以10以获得以毫秒为单位的值。
while(1) { POT_val =(ADC_Read(0)); //使用ADC Duty_cycle =(POT_val * 0.0976) 读取POT的值 //将0到1024映射到0到100 T_ON =((Duty_cycle * T_TOTAL)* 10/100); //使用公式单位以毫秒为单位计算 准时__delay_ms(100); }
由于将计时器设置为每0.1ms溢出,因此将每0.1ms调用一次计时器中断服务程序ISR。在服务例程中,我们使用一个称为count的变量,并每隔0.1ms递增一次。这样我们就可以追踪时间。要了解有关PIC微控制器中中断的更多信息,请访问以下链接
if(TMR0IF == 1)//由于定时器溢出触发了定时器标志->每0.1ms设置为溢出 { TMR0 = 248; //加载定时器值 TMR0IF = 0; //清除计时器中断标志 计数++; //每0.1ms递增计数-> count / 10将以ms为单位给出计数值 }
最后是时候根据T_ON和T_OFF的值切换GPIO引脚了。我们有 count 变量,以毫秒为单位跟踪时间。因此,我们使用该变量来检查时间是否小于 准时 ,如果是,则使GPIO引脚保持打开状态,否则将其关闭并保持关闭状态,直到新的周期开始为止。可以通过将其与一个PWM周期的总时间进行比较来完成。相同的代码如下所示
if(count <=(T_ON))//如果时间少于准时 RD1 = 1; //打开GPIO, 否则 RD1 = 0;//否则, 如果(count> =(T_TOTAL * 10)) 关闭GPIO ,//使其保持关闭状态,直到新的循环开始count = 0;
电路原理图
用PIC微控制器的GPIO引脚生成PWM的电路图非常简单,只需用振荡器为PIC供电,然后将电位计连接到AN0引脚,将伺服电动机连接到RD1引脚,我们可以使用GPIO引脚获得PWM信号,我已经选择了RD1只是随机出现的。电位计和伺服电机均由5V供电,该电压由7805调节,如下图所示。
模拟
为了模拟项目,我使用了proteus软件。构建如下所示的电路,并将代码链接到您的仿真并运行它。您应该按照我们的程序在RD1 GPIO引脚上获得一个PWM信号,并且应该根据电位计的位置控制PWM的占空比。下面的GIF显示了通过电位计更改ADC值时PWM信号和伺服电机的响应方式。
使用PIC单片机控制伺服电机的硬件设置
我的完整硬件设置如下所示,对于那些正在关注我的教程的人,此板应该看起来很熟悉,这是到目前为止我在所有教程中都使用过的板。如果您有兴趣了解如何构建它,可以参考闪烁的LED教程。否则,只需遵循上面的电路图,一切就可以正常工作。
上载程序并改变电位计,您将看到伺服器根据电位计的位置更改位置。在此页末尾的视频中显示了该项目的完整工作。希望您理解该项目并喜欢构建,如果您有任何疑问,请随时将其发布在论坛上,我将尽我所能回答。
我打算通过添加选项来控制多个伺服电机,从而在该项目中继续前进,从而在其中构建一个机械臂,类似于我们已经构建的Arduino机械臂。所以直到那时再见!