假设PPWM的脉宽为20,TH是高电平输出时间,TL是低电平输出时间,你只要在程序中满足TH+TL = 20就可以了
假设用延时程序来实现,delay(char i);为延时100us的程序,i为循环次数
void delay(uchar i)
{
uint x,y;
for(x=i;x>0;x--)
for(y=100;y>0;y--);
}
void main()
{
uchar pwm = 1,h = 20;
while(1)
{
RC3 =1;
delay(pwm);
RC3 = 0;
delay(h - pwm);
}
}
改变pwm的值(1-19)就可以改变输出高电平的宽度
例如:
//利作RC3控制输出PWM信号,控制电机正反转及转速,
//RC2为按键,默认为上拉高电平,当RC2按下为低电平时,RC1为电机以一定的速度转动,(松开默认为停止)长按停止
//MOS3205控制电机的管,高电平导通,低电平停止
//PIC16F877A,晶振4MHz
#include<pich>
#define uchar unsigned char
#define uint unsigned int
__CONFIG(0X3B31);
//uint initnum,Speed,motor;//定义一个溢出中断的变量
void delay_ms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=100;y>0;y--);
}
void init()//初始化接LED的RD端口为输出,及设置OPTION寄存器关闭TMR0定时计时器
{
TRISC0=0;
TRISC1=1;
TRISC2=1;
TRISC3=0;
TRISC4=0;
RC0=0;
RC1=1;
RC2=1;
RC3=0;
RC4=0;
/
TRISD=0;//输出状态
INTCON=0xc0;//设置中断控制寄存器为11000000,始终只用到两个位开总中断,开第二外设允许中断
PIE1=0x02;//使能定时器1为00000010开中断,始终只用一最后一个其他的不用理会
PR2=200;//装初值,定时器2是8位的寄存器有256个数但是可以设定一个周期寄存器到了就可以溢出,如果不设周期寄存器就为256溢出,初值56则200us溢出
TMR2=0;//这样用PR2表示初值,在中断函数中就不用加初值了;51的模式2中,THn是下限,也就是开始计时的值;PIC中的PR2是上限,也就是计时到这个值就归零
T2CON=0x04;//设置预分频器和后分频器就是开始启到动定时器2;这里都是1:1的比例
// T2CON=0x05;//设置预分频器1:4和后分频器就是开始启到动定时器2;这时候的时间是乘以后4倍,原本以200us产生一次中断现在则以800us产生一次中断,即8001000的时间闪动
// T2CON=0x0d;//设置预分频器1:4和后分频器1:2就是开始启到动定时器2;这时候的时间是乘以后4倍,再乘以2倍,原本以200us产生一次中断现在则以1600us产生一次中断即16001000的时间闪动
// PR2=100;设置周期寄存器,值设为100,到了就溢出,同时要将其初值设置为零才够精确
/
}
void delay_us(uint i)//1表示100us,2表示200us
{
uint a,b;
for(a=i;a>0;a--)
{
for(b=7;b>0;b--);
}
}
/
void pwm()
{
uchar pwm=10,h=20;//要输出pwm500hz的频率脉宽是2ms
while(1)
{
RC3=1;
delay_us(pwm);
RC3=0;
delay_us(h-pwm);
if(RC2==1)//加上这两句就可以退出了
break;
}
}/
void main()
{
uchar aa,pwm=10,h=20;
init();
while(1)////判断按键状态////长按可以调光
{
if(RC2==0)//判断RC2按下
{
delay_ms(10);
while(!RC2)
{
for(aa=0;aa<255;aa++)//当前输出延时一段时间,这样才能看出速度的变化
{
RC3=1;
delay_us(pwm);
RC3=0;
delay_us(h-pwm);
}
if(++pwm > 19)
pwm = 10;
}
}
else
{
RC3=0;
}
}
}
/
void go(uint motor1)//电机的速度参数
{
Speed=motor1;//给电机速度参数赋速度参数的变量
motor=0x64+Speed;//0x64为100在中间加上速度参数
}
void interrupt time0()//定时器的程序,后面不用写和51单片机那样的序号,也不用就算写在主函数的后面也不用声明
{ //51的模式2中,THn是下限,也就是开始计时的值;PIC中的PR2是上限,也就是计时到这个值就归零
TMR2IF=0;//先清零,
TMR2=0;
initnum++;//加一
if(initnum<motor)
{
RC3=1;
RC4=0;
}
else
{
RC3=0;
RC4=1;
}
if(initnum==0xc8)//判断值加1是否不等于200
{
initnum=0;
}
}
/
1、推荐用单片机程序就可以轻松的实现,特别是有些单片机就有PWM模块,直接输入数据就能得到你想要的脉冲宽度的PWM波形。
2、也可以用比较器来做,一端输入三角波,另一端输入直流电平,改变直流值就可以输出不同脉冲宽度的PWM波形。
你的问题涉及到硬件,应该说清楚
一般来说 PWM调速程序的步骤是:
1 先写一个固定的PWM产生函数 例如多用定时
器优先级要高点 这样PWM质量较好 2修改定时器常数 定时器常数可以放到一个固定的地址单元 在其他的程序段时直接修改该单元数值即可实现调速
一般的调速都是基于PID调速的 更详细的资料你在找找
/ 利用定时器控制产生占空比可变的 PWM 波
// 按K1,PWM值增加,则占空比减小,电机减速。
// 按K2,PWM值减小,则占空比增加,电机加速。
// 当PWM值增加到最大值或减小到最小值时,蜂鸣器将报警。
//
#include<reg51h>
#include<intrinsh>
sbit K1 =P1^4 ; //PWM值增加键
sbit K2 =P1^5 ; //PWM值减少键
sbit BEEP =P3^7 ; //蜂鸣器
unsigned char PWM=0x7f ; //赋初值
void Beep();
void delayms(unsigned char ms);
void delay(unsigned char t);
//
void main()
{
P1=0xff;
TMOD=0x21 ;
TH0=0xfc ; //1ms延时常数
TL0=0x66 ; //频率调节
TH1=PWM ; //脉宽调节
TL1=0 ;
EA=1;
ET0=1;
ET1=1;
TR0=1 ;
while(1)
{
do{
if(PWM!=0xff)
{PWM++ ;delayms(10);}
else Beep() ;
}
while(K1==0);
do{
if(PWM!=0x02)
{PWM-- ;delayms(10);}
else Beep() ;
}
while(K2==0);
}
}
//
// 定时器0中断服务程序 (频率)
//
void timer0() interrupt 1
{
TR1=0 ;
TH0=0xfc ;
TL0=0x66 ;
TH1=PWM ;
TR1=1 ;
P0=0x00 ; //启动输出
}
//
// 定时器1中断服务程序 (脉宽)
//
void timer1() interrupt 3
{
TR1=0 ;
P0=0xff ; //结束输出
}
//
//蜂鸣器子程序
//
void Beep()
{
unsigned char i ;
for (i=0 ;i<100 ;i++)
{
delay(100) ;
BEEP=!BEEP ; //Beep取反
}
BEEP=1 ; //关闭蜂鸣器
delayms(100);
}
//
// 延时子程序
//
void delay(unsigned char t)
{
while(t--) ;
}
//
// 延时子程序
//
void delayms(unsigned char ms)
{
unsigned char i ;
while(ms--)
{
for(i = 0 ; i < 120 ; i++) ;
}
}
//
上桥臂PWM输出,下桥臂常闭。你要是做电机的话这个就会好理解了。
用库函数不是有个TIM_CCxN配置的函数。给TIM_CCx配置一个CCR的值。把互补通道这个关掉就好了。
脉冲宽度调制(PWM),是对脉冲宽度的控制。
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样, STM32 最多可以同时产生 30 路 PWM 输出!
本实验是利用 TIM3 的通道 2,把通道 2 重映射到 PB5, 产生 PWM 来控制 DS0 的亮度。
TIM3_CH2 默认是接在 PA7上面的,而我们的 DS0 接在 PB5 上面,可以通过重映射功能,把 TIM3_CH2映射到 PB5 上。
给你发一个我以前的,产生PWM输出的在定时time0中断里进行判断,你进行一些更改吧
;FINT0 EQU 20H1 ;全局标志位
;;;;;;;;定时时间;;;;;;;
time0_h EQU 40H;#0ffh 定时器高位
time0_l EQU 41H;#0f6h 定时器低位
PWM_TIME EQU 42H;#0x0c9总脉宽的数据
t_0 EQU 30H;进入定时中断的次数
motor_r EQU 31H;右电机PWM数据 大于#64H反转小于#64H正转
motor_l EQU 32H;左电机PWM数据 大于#64H反转小于#64H正转
;;;;;;;;声音;;;;;;;;;;;
sound bit P2^0;声音端口
;;;;;;;;电机控制;;;;;;;
PWM1 bit P2^1;右电机速度
PWM2 bit P2^2;左电机速度
EN1 bit P2^6;右电机使能
EN2 bit P2^7;左电机使能
;;;;;;;启动安扭;;;;;;;;
start bit P3^2;开始按键
;;;;;;;输入;;;;;;;;;;;;
S1 bit P1^4;IN1输入 传感器1输入
S2 bit P1^5;IN2输入 传感器2输入
S3 bit P1^6;IN3输入 传感器3输入
S4 bit P1^7;IN4输入 传感器4输入
;;;;;;输出;;;;;;;;;;;;
out1 bit P1^0;OUT1输出
out2 bit P1^1;OUT2输出
out3 bit P1^2;OUT3输出
out4 bit P1^3;OUT4输出
;;;;;;机构电机;;;;;;;;;;
J_Z bit P2^3;机构电机正转 01 10 11
J_F bit P2^4;机构电机反转
ORG 0000H ;程序开始
AJMP MAIN ;跳转到主程序
ORG 0003H ;中断0开始地址
AJMP INT_0 ;跳转到中断0子程序
ORG 000BH ;T0中断入口地址
AJMP INT_T0 ;跳转到定时中断0子程序
ORG 0100H ;主程序开始地址
MAIN: ;主程序标号
CLR EN1 ;关电机始能
CLR EN2
CLR EA ;关总始能
CALL DLY_200MS ;延时
CALL INIT ;初始化
JB start,$ ;查询开始键
CALL DLY_200MS ;
CLR sound ;发声
CALL DLY_200MS
SETB sound ;停止发声
SETB EA ;开全局中断
MOV R0,#20H
CALL motorr_z
MOV R0,#20H
CALL motorl_z
MAIN_M:
JNB S1,TURNLEFT
JNB S2,TURNRIGHT
MOV R0,#20H
CALL motorr_z
CALL motorl_z
JMP MAIN_M
;===================================
TURNLEFT:
JB S1,MAIN_M
CALL DELAY
JB S1,MAIN_M
MOV R0,#30H
CALL motorr_z
CLR EN2
JMP MAIN_M
;===================================
TURNRIGHT:
JB S2,MAIN_M
CALL DELAY
JB S2,MAIN_M
MOV R0,#30H
CALL motorl_z
CLR EN1
JMP MAIN_M
;===================================
STOP:
CLR EN2
CLR EN1
RET
;===================================
;;电机1正转
motorr_z:
MOV A,R0
ADD A,#64H
MOV motor_r,A
SETB EN1
RET
;===================================
;;电机1反转
motorr_f:
MOV A,#64H
SUBB A,R0
MOV motor_r,A
SETB EN1
RET
;===================================
;;电机2正转
motorl_z:
MOV A,#64H
SUBB A,R0
MOV motor_l,A
SETB EN2
RET
;===================================
;;电机2反转
motorl_f:
MOV A,R0
ADD A,#64H
MOV motor_l,A
SETB EN2
RET
;===============初始化==============
INIT:
MOV SP,#60H
MOV TMOD, #21H
;MOV SCON, #52H
MOV TCON, #69H
;MOV TH1, #FDH
MOV 40H,#0ffh
MOV 41H,#0f6h
MOV TH0,time0_h
MOV TL0,time0_l
MOV 42H,#0x0c9 ;1---201 大于100反转小于100正转
SETB EX0 ;INT0中断开
CLR IT0 ;INT0下降沿触发(为0则为低电平触发)
SETB TR0
SETB ET0
RET
;==============T0中断子程序
INT_T0:
PUSH ACC
PUSH PSW
CLR TR0
MOV TH0,time0_h
MOV TL0,time0_l
INC t_0
MOV A,t_0
CLR C
SUBB A,motor_r ;pwm1
JC PWM_2
CLR PWM1
PWM_2:
MOV A,t_0
CLR C
SUBB A,motor_l
JC HIGHT
CLR PWM2
HIGHT:
MOV A,t_0
CJNE A,#0C9H,EXIT
CLR A
MOV t_0,A
SETB PWM1
SETB PWM2
EXIT:
SETB TR0
POP PSW
POP ACC
RETI
;;=========================外中断
INT_0:
CLR EN1
CLR EN2
CLR EA
;CLR FINT0
JMP $
RETI
DLY_200MS:
MOV R5,#01H
DLY_200MS1:
MOV R6,#00H
DLY_200MS2:
MOV R7,#00H
DLY_200MS3:
NOP
DJNZ R7,DLY_200MS3
DJNZ R6,DLY_200MS2
DJNZ R5,DLY_200MS1
RET
DELAY: MOV R5,#20 ;
D2: MOV R7,#248
DJNZ R7,$
DJNZ R5,D2
RET
END
以上就是关于如何用pic单片机写PWM信号的产生全部的内容,包括:如何用pic单片机写PWM信号的产生、怎样产生PWM波形、怎样用汇编语言编写pwm电机调速程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)