如何用pic单片机写PWM信号的产生

如何用pic单片机写PWM信号的产生,第1张

假设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电机调速程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/10088156.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存