一.输出比较初始化
步骤:
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;
上一篇:【PIC32MZ】按键中断
下一篇:pic 16 定时器 012
推荐阅读最新更新时间:2024-11-16 20:41
设计资源 培训 开发板 精华推荐
- 使用 IXYS 的 IXDN430CI 的参考设计
- LiNetRex
- EVAL-AD7477CB,使用 AD7477A、10 位、1 MSPS 高速、低功耗模数转换器的评估板
- NCP705 500 mA、超低静态电流、IQ 13 A、超低噪声、可调电压版本的 LDO 稳压器的典型应用
- DER-702 - 45 W USB PD 3.0,采用 3.3 V-16 V PPS 电源,使用 InnoSwitch3-Pro 和 Weltrend WT6635P 控制器
- elrs2.4G pp接收机——ExpressLRS开源接收机
- Luat_HMI-7I0-800480-A_V1.3
- 痛PCB[转载,分享]基板少女 PCB Girl
- 使用 Microchip Technology 的 SG317 的参考设计
- 王梦生日台灯离线语音控制器-基于启英泰伦C1122模组
- 睿瀚医疗万斌:“脑机接口+AI+机器人”是康复赛道的未来
- 希润医疗孟铭强:手功能软体机器人,让脑卒中患者重获新生
- 柔灵科技陈涵:将小型、柔性的脑机接口睡眠设备,做到千家万户
- 微灵医疗李骁健:脑机接口技术正在开启意识与AI融合的新纪元
- USB Type-C® 和 USB Power Delivery:专为扩展功率范围和电池供电型系统而设计
- 景昱医疗耿东:脑机接口DBS治疗技术已实现国产替代
- 首都医科大学王长明:针对癫痫的数字疗法已进入使用阶段
- 非常见问题解答第223期:如何在没有软启动方程的情况下测量和确定软启动时序?
- 兆易创新GD25/55全系列车规级SPI NOR Flash荣获ISO 26262 ASIL D功能安全认证证书
- 新型IsoVu™ 隔离电流探头:为电流测量带来全新维度
- MM32F103开发板测评等你来
- 基于PolarFire® SoC FPGA的Microchip非对称多处理(AMP)解决方案
- 看咱坛友自己的研讨会~ST-EEWORLD线下网友见面会实录
- 跟上未来,走进恩智浦最新技术大讲堂
- 阅读瑞萨电子电源模块系列白皮书,赢双重好礼:提升能量有礼&推荐100%有礼 !
- 学习有礼,分享也有礼!跟着小梅哥,一起intel SoC FPGA走起!
- 有奖直播:ADI数字主动降噪耳机方案 8月6日上午10:00-11:30 邀您聆听让技术为我们静下来
- TI有奖直播|C2000™ F280013x实现更低成本且更高效的实时控制方案
- 是德科技(Keysight)有奖征文,下笔赢示波器啦!