PIC32输出比较(PWM)

发布者:theta18最新更新时间:2020-06-06 来源: eefocus关键字:PIC32  输出比较  PWM 手机看文章 扫描二维码
随时随地手机看文章

一.输出比较初始化


步骤:


1.复用端口映射为OCx     


例如:RPA0Rbits.RPA0R=0b0101; 即RPA0引脚作为外设OC1使用


2.OCM<2:0>:输出比较模式选择位


例如:OC1CON=0X06;      //输出比较端口1配置为PWM故障禁止模式。


3.OC32<5>:32 位比较模式位


例如:OC1CONCLR=0X010;  //将第五位清零,设置为16位单定时器模式。


4.OCTSEL<3>:输出比较定时器选择位


例如:OC1CONSET=0X08;  //将第三位设置为一,选择定时器3为基时钟


5.定时器使能初始化


例如:OpenTimer3(T1_ON|T1_SOURCE_INT|T1_PS_1_1,pwmn);


Pwmn周期数={ FB外设/pwmfp频率 } - 1;


6.ON<15>:输出比较外设使能位


例如:OC1CONSET=0X8000;         //将第15位置一,输出比较使能。


详细初始化控制寄存器见附二


 


二.中断触发条件


单比较模式


• 比较匹配事件强制OCx 引脚为高电平;该引脚的初始状态为低电平。在发生单比较匹配事件


时,产生中断。


• 比较匹配事件强制OCx 引脚为低电平;该引脚的初始状态为高电平。在发生单比较匹配事件时,产生中断。


• 比较匹配事件使OCx 引脚电平翻转。翻转事件是连续的,且每次翻转事件都会产生一次中断。


双比较模式


当OCx引脚被驱动为低电平(单脉冲的下降沿)时,相应通道的中断标志OCxIF会置为有效。


PWM模式


TyIF 中断标志在每个PWM 周期边界处置为有效。


当使能了具有故障保护输入模式的PWM 时,必须通过将相应的TRIS SFR 位置1 以将OCFx 故


障引脚配置为输入。选择PWM 故障模式时, OCFx 故障输入引脚不会自动配置为输入。


三.计算各项值


所需的PWM通过写入OCxRS 寄存器来指定PWM 占空比。可以在任何时候写OCxRS 寄存器,但是在PRy和TMRy 发生匹配(即周期结束)前占空比值不会被锁存到OCxR 中。


PWM 周期 = [(PR 1) • TPB • (TMR 预分频值)]  或T=PR 1/(Fpb/PS)


PWM 频率 = 1/[PWM 周期]


最大PWM 分辨率:在一个PWM周期内有n个时基(PR),为2的x次方,分辨率为x。


以频率为52.08 kHz为例


FPB = 10 MHz


Timer2 预分频比设置: 1:1


1/52.08 kHz = (PR2 1) • TPB • (Timer2 预分频值)=(PR2 1)/(FPB/Timer2预分频)


19.20 us = (PR2 1) • 0.1 us • (1)


PR2 = 191


确定可用于52.08 kHz PWM 频率和10 MHz 外设总线时钟速率的占空比的最大分辨率。


1/52.08 kHz = 2^PWM 分辨率• 1/10 MHz • 1


19.20 us = 2^PWM 分辨率• 100 ns • 1


192 = 2^PWM 分辨率


log10(192) = (PWM 分辨率) • log10(2)


PWM 分辨率 = 7.6 位


四.拓展


#用PWM绘制新波形


峰峰值最大为PR定时器数。


每个PWM周期为一个样本


所需波形频率:


所需频率=1/(n个样本*PWM周期)


每个样本波形的幅度值(占空比*PR):


波形/n,将n个值列入数组表格,OCxRS引用。


每个PWM周期输出通过RC滤波电路转换为模拟信号,约为一条幅值为 高电平*占空比 的直线,


通过改变占空比控制赋值y轴,再通过控制周期数控制产生的x轴


正弦波波形产生,占空比计算值 OC1RS=偏移量 振幅*SIN(2*pi/周期样本值),但如此短的时间无法


来的及计算sin,最好制成表格数组引用。


#发出声音


绘制相应的频率可发出相应的音高(do,re,me…),再调整波形幅度决定音色(不同的乐器)。


举例说明


一.用PWM制作呼吸灯效果


#include


#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)


#pragma config FPLLMUL = MUL_24


#pragma config FPLLODIV = DIV_2


#pragma config FPBDIV = DIV_1


#pragma config FNOSC = FRCPLL


#pragma config FUSBIDIO = OFF


#pragma config FWDTEN = OFF


#pragma config JTAGEN = OFF


int pwm1,pwmn,pwmfp,count,pwm_g;


void PWMinint()


{


 OC1CON=0;              //关闭 初始都为零,定时器二,16位模式


 OC1CON=0x06;           //PWM无故障模式


 OC1R=10000;            //初始占空比为10000


 OC1RS=10000;           


 pwmn=48000000/pwmfp-1;          PWM周期数


 OpenTimer2(T2_ON|T2_SOURCE_INT|T2_PS_1_1,pwmn);  //初始定时器2


 OC1CONSET=0x8000;              //开启输出比较使能


}


void __ISR(_TIMER_2_VECTOR,ipl3) Timer2hander(void)   //中断


{


    mT2ClearIntFlag();


 if(pwm_g==0)


    count ;            //当count越大亮度越低反之详见电路图


    else


    count--;


    if(count>4410)


    pwm_g=1;


    if(count==0)


    pwm_g=0;


    OC1RS=count*pwmn/4410;       //4410/4410=1s一翻转


}


int main()


{


    RPB7Rbits.RPB7R=0b0101;


    pwmfp=4410;


    PWMinint();


    mT2SetIntPriority(3);


    mT2IntEnable(1);


    INTEnableSystemMultiVectoredInt();


    while(1);


}


二.按键实时控制PWM


#include


// Configuration Bit settings


// SYSCLK = 48 MHz (8MHz Crystal / FPLLIDIV * FPLLMUL / FPLLODIV)


// PBCLK = 48 MHz (SYSCLK / FPBDIV)


// Primary Osc w/PLL (XT ,HS ,EC PLL)


// WDT OFF


#pragma config FPLLMUL = MUL_24, FPLLIDIV = DIV_2, FPLLODIV = DIV_2, FWDTEN = OFF


#pragma config POSCMOD = OFF, FNOSC = FRCPLL, FPBDIV = DIV_1,FSOSCEN = OFF


#pragma config FUSBIDIO = OFF           //FUSBIDIO?????


#pragma config FVBUSONIO = OFF


#pragma config JTAGEN   = OFF           //JTAG disable


#pragma config CP       = OFF


#pragma config DEBUG    = ON


// Period needed for timer 1 to trigger an interrupt every 0.1 second


// (48MHz PBCLK / 1 = 48000000KHz Timer 1 clock)


#define PERIOD  48000       //48000/48000000 = 0.001s = 1ms


#define BTN_DELAY   5 //2*1=2ms


#define SYS_FREQ (48000000L)


//????????


typedef enum //PRO_Status


{


    SHOW_PERIOD = 0,


    SHOW_DUTY,


    SHOW_SET_PERIOD,


    SHOW_SET_DUTY,


    SET_PERIOD,


    SET_DUTY


}PRO_STATUS;


PRO_STATUS g_status=SHOW_PERIOD;


UINT16 g_period=40,g_duty=20; //初始周期40,占空比20


UINT16 g_set_period=40,g_set_duty=20;


int    g_led_cnt=0,g_led_flag=0,g_btn_cnt=0,g_btn_flag=0,flag=0;


//显示于按键标志,用于周期性定时处理LED显示和按键


unsigned char Led_lib[] = {


    0x42, 0xf3, 0x86, 0xa2, 0x33, 0x2a, 0x0a, 0xf2, 0x02, 0x22, //0-9


    0x40, 0xf1, 0x84, 0xa0, 0x31, 0x28, 0x08, 0xf0, 0x00, 0x20, //0.-9.


    0x1e, 0x2a, 0x0e, 0x0f, 0xbf, 0x23, 0x9b, 0x8b}; //FSEt-yno


//LED字库SPI初始化


void SpiInitDevice() {


    // 8 bits/char, input data sampled at end of data output time


    SpiOpenFlags oFlags = SPI_OPEN_MSTEN | SPI_OPEN_CKP_HIGH | SPI_OPEN_MODE8 | SPI_OPEN_ON;


    PORTSetPinsDigitalOut(IOPORT_B, BIT_9);//作为锁存,1锁存,0开放


    PPSOutput(2, RPB8, SDO2); // Set RB8 pin as output for SDO2


    // Open SPI module, use SPI channel 2, use flags set above, Divide Fpb by 6


    SpiChnOpen(2, oFlags, 6);


}


void SpiDoBurst(unsigned char *pBuff, unsigned char Len) {


    if (pBuff) {


        unsigned int i;


        PORTClearBits(IOPORT_B, BIT_9);


        for (i = 0; i < Len; i ) {


            SpiChnPutC(2, pBuff[i]);


        }


        PORTSetBits(IOPORT_B, BIT_9);


    }


}


//LED初始化


void Led()


{


    static unsigned char ledBuff[4] = {0x00, 0x00, 0x00, 0x00};


    static int led = 0;


    int i,n;


    SpiDoBurst(ledBuff, 4);


    //LED显示 4,1,2,3


    switch(g_status)


    {


        case SHOW_PERIOD:


            led=g_period;


            ledBuff[3]=0b00010110;//Led_lib[1];


            break;


        case SHOW_DUTY:


            led=g_duty;


            ledBuff[3]=0b01001110;//Led_lib[2];


            break;


        case SHOW_SET_PERIOD:


            led=g_set_period;


            ledBuff[3]=0b00010100;//Led_lib[3];


            break;


        case SHOW_SET_DUTY:


            led=g_set_duty;


            ledBuff[3]=0b01001100;//Led_lib[4];


            break;


        case SET_PERIOD:


            led=g_set_period;


            ledBuff[3]=0b00010100;//Led_lib[3];


            break;


        case SET_DUTY:


            led=g_set_duty;


            ledBuff[3]=0b01001100;//Led_lib[4];


            break;


    }


    i=led/100;


    i=i;


    ledBuff[0]=Led_lib[i];


    led=led0;


    i=led/10;


    ledBuff[1]=Led_lib[i];


    i=led;


    ledBuff[2]=Led_lib[i];


    n ;


    if(n=2)


    flag=1;


}


void pwminit()


{


    RPB13Rbits.RPB13R=0b0101;//外设端口映射为OC4


    OC4CON=0;


    OC4R=0;


    OC4RS=0;


    OC4CON=0X06;    //PWM无故障模式


    OpenTimer2(T2_ON|T2_SOURCE_INT|T2_PS_1_1,g_period);  //基定时器初始


    OC4CONSET=0X8000;      //使能OC4


//    mT2SetIntPriority(1);


//    mT2IntEnable(1);


}


//void __ISR(_TIMER_2_VECTOR,ipl1) Timer2(void)


//{


//


//    mT2ClearIntFlag();


//    OC4RS=g_duty;    


//若由输出比较的基定时器2刷新值,则会随着PWM周期的太小刷新过快,会与定时器1的中断多次冲突造成定时器1无法正常工作。


//    PR2=g_period;   


//}


void Timer1Init()


{


    // Timer1@1ms


    OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_1, PERIOD);


 


    // Set up the timer interrupt with a priority of 2


    INTEnable(INT_T1, INT_ENABLED);


    INTSetVectorPriority(INT_TIMER_1_VECTOR, INT_PRIORITY_LEVEL_5);


    INTSetVectorSubPriority(INT_TIMER_1_VECTOR, INT_SUB_PRIORITY_LEVEL_0);


}


//??1????


void __ISR(_TIMER_1_VECTOR, ipl5) Timer1Handler(void)


{


    // Clear the interrupt flag


    INTClearFlag(INT_T1);


    OC4RS=g_duty;


    PR2=g_period;//由定时器1统一更新周期和占空比


    g_led_cnt ;


    if(g_led_cnt > 100)    //0.1s


    {


        g_led_cnt = 0;


        g_led_flag = 1;


    }


    g_btn_cnt ;


    if(g_btn_cnt > 5)     //5ms


    {


        g_btn_cnt = 0;


        g_btn_flag = 1;


    }


}


//设为数字端口,当有足够电压改变1与0的转换才有信号


void BtnInit()


{


    ANSELAbits.ANSA0 = 0;


    ANSELAbits.ANSA1 = 0;


//    ANSELBbits.ANSB3 = 0;


    ANSELBbits.ANSB14 = 0;


}


//????


void Button(void)


{


    static int btn0=0,btn1=0,btn2=0,btn3=0,n=0;


 


    if(PORTAbits.RA0 == 0) //sel


    {


        btn0 ;


        if(btn0 == BTN_DELAY)


        {


             switch(g_status)


            {


                case SHOW_PERIOD:


                    g_status=SHOW_SET_PERIOD;


                    break;

[1] [2] [3]
关键字:PIC32  输出比较  PWM 引用地址:PIC32输出比较(PWM)

上一篇:【PIC32MZ】按键中断
下一篇:pic 16 定时器 012

推荐阅读最新更新时间:2024-11-16 20:41

Actel FPGA的PWM IP的应用
脉冲宽度调制(PWM)是英文“Pluse Width Modulation”的缩写,简称脉宽调制。它是利用微处理器的数字输出来对 模拟 电路 进行 控制 的一种非常有效的技术,根据相应的载荷的变化来调制晶体管栅极或基极的偏置,来实现 开关 稳压 电源 输出晶体管或晶体管导通时间的改变。这种方式能使 电源 的输出电压在工作条件变化时保持恒定,广泛应用于测量、通信、功率 控制 与变化等许多领域。 Actel公司免费提供PWM IP核:CorePWM。CorePWM是基于APB 总线 形式的,它的优点是可以连接到Core8051或者是CortexM1处理器上,方便用户进行SoC设计,本文将主要介绍CorePWM的原理与应用。 1.
[模拟电子]
51单片机做的PWM无级调光程序
#i nclude reg51.h #i nclude user.h #define uchar unsigned char unsigned int value=100; unsigned int del=0; uchar value_temp=4; uchar temp=0; uchar code tab ={0x88,0xbe,0xc4,0x94,0xb2,0x91,0x81,0xbc,0x80,0x90,0xf7}; sbit pwm_port=p3^1; sbit key=p3^7; bit lamp_enable=0; void display(uchar dat) { p1=tab ; } void timer_i
[单片机]
FAN302HL:高集成度PWM控制器
     FAN302HL是一款高集成度PWM控制器,具有数项提升通用反激式转换器之性能的特性,如集成式500V JFET,可在器件开启后切断电流路径,减少启动损耗。而其专利恒定电流控制拓扑能够简化电路设计,且无需次级端恒流反馈电路,为电池充电器应用中提供重要的优势。   FAN302HL还具有数项保护功能,包括逐周期电流限制,以确保达到固定的峰值电流限制水平,即使在发生短路的情况下亦然。此外,该器件还将栅极输出电压箝制在15V水平,以保护功率MOSFET避免栅极-源极电压过高时造成损坏。   FAN302HL无需外部次级端过压保护(OVP)电路,如果VS引脚的OVP功能或内部过温保护功能任何一个被触发,该器件就会进入锁定
[电源管理]
FAN302HL:高集成度<font color='red'>PWM</font>控制器
基于PIC32上实现的TCP/IP网络协议和zigbee无线传感器网络的智能
一 项目背景 随着物联网的热潮的到来,2010年国内许多省市纷纷发布的《物联网发展规划》,物联网附属领域智能家居的发展也得到了非常大程度的推进。由于物联网的核心和基础仍然是互联网,所以在项目设计中我们将智能家居内部的传感器网络连接至控制核心PIC32,PIC32通过控制网络模块,按照TCP/IP协议来实现PIC32的Web服务器功能,使得可以通过手机、电脑的浏览器来远程访问该web服务器,并以点击链接的形式,控制用电器。这种嵌入式Web服务器的低功耗和高可靠性,使其特别适合作为家庭小型Web服务器控制。 二、需求信息 拟采用的平台: cerebot 32M 4 两个Digilent PMOD 产品: PmodN
[单片机]
基于<font color='red'>PIC32</font>上实现的TCP/IP网络协议和zigbee无线传感器网络的智能
基于51单片机的可调PWM波程序
#include reg52.h #define uint unsigned int uint pp; char num=2,dis; sbit pwm=P1^0; sbit s2=P3^4; sbit s3=P3^5; sbit dula=P2^6; sbit wela=P2^7; unsigned char code table = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f, 0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; void keyscan() { if(s2==0) { while(!
[单片机]
STM32F4CubeMX学习笔记之Time2 pwm
开发板:普中PZ6808L-F4 开发环境:keil5+CnbeMx CnbeMx配置为定时器2 配置IO口为PB10 PB11 好了就可以用示波器查看有没有输出了
[单片机]
STM32F4CubeMX学习笔记之Time2 <font color='red'>pwm</font>
基于新型PWM整流控制技术的在线式UPS设计
  1 概述   PWM 前端控制整流由于具有直流电压的变化,输入 功率 因数校正( PFC) 和输入电流谐波控制的能力等优点, 被广泛用于三相交直交电压系统。由前端整流器、直流电容, 以及逆变器组成的三相交直交电压系统广泛用于在线式U PS 。基于 DSP 控制的在线式UPS 的结构图如图1 所示。      图1 基于DSP 控制的在线式UPS 的结构图   图1 中, 主电路由输入变压器、输入滤波电路、电压和电流检测电路、蓄电池、功率电路、输出滤波电路和静态开关等组成。其中功率电路包括三个部分, 即输入的PFC、三相全桥逆变器、DC/ DC 部分。电路信号采用TMS320C2812 控制。该 控制器 是T I
[电源管理]
基于新型<font color='red'>PWM</font>整流控制技术的在线式UPS设计
STM32的TIM1互补PWM输出
芯片为STM32F412VETx,使用的是高级定时器TIM1的PWM互补PWM输出,看一下STM32CubeMX配置, 再看时钟的配置,TIM1用的是APB2的时钟,。 再看引脚的配置 产生的PWM频率为:Fpwm = 96MHz / ((95+1)(9999+1)) =100Hz,占空比为50% 然后生成代码,看下代码中的FMX_TIM1_Init函数初始化 /* TIM1 init function */ static void FMX_TIM1_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig; TIM_MasterConfigType
[单片机]
STM32的TIM1互补<font color='red'>PWM</font><font color='red'>输出</font>
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved