你这个程序 conpwm函数的形参 x 和全局变量 x 混淆了
conpwm(value[i]) 只是把时间参数给了 函数的形参x 在函数中用其给定时器赋初值。但是在后来的中断程序中,每次中断又会给定时器重新加载计数值,这个值里面的 x 是那个全局变量 x,而你的程序没有给这个 x 赋时间参数。所以PWM的波形应该不是你所希望的。
#include<reg51h>
sbit P_OUT = P3^7;
sbit UP = P1^0;
sbit DN = P1^1;
unsigned char p = 5, n;
void T0_INT() interrupt 1
{
n++;
if(n > 9) n = 0; //0~9
if(n <= p) P_OUT = 1;
else P_OUT = 0;
}
main()
{
TMOD = 0x02;
TH0 = 156;
TR0 = 1;
IE = 0x82;
while(1) {
if(P < 9 && !UP) {while(!UP); p++;}
if(p > 0 && !DN) {while(!DN); p--;}
}
}
你编译一下,汇编程序,就出来了。
第一,要理解中断在这里的作用是固定的“一小段”时间进入一次。
第二,PWM_ON在程序中的作用很大,它会由0------>CYCLE------>0并且一直循环下去。可以把它看成一个有规律的变化的量。
第三,每进入中断一次count++,满足条件count==PWM_ON或count==CYCLE时改变LED的当前状态。作用是给小灯亮或灭的时间不同。
第四,LED的亮度与其通电时间有关,也可以说成是占空比。上面的条件要理解成是呈线性增加或减小的频率。可以理解成三角波,对应的面积就是通电时间。
不知能不能给你讲明白!
#include <reg52h>
#define uint unsigned int
#define uchar unsigned char
uchar count ,z;
sbit key_1 = P3^7;
sbit key_2 = P3^6;
sbit PWM = P2^0;
void key_control();
void init ();
void create_PWM(uchar);
void delay(uint);
void main ()
{
init ();
while(1);
{
key_control();
create_PWM(count);
}
}
void delay(uint z)
{
uint x,y;
for(x = z;x>0;x--)
for(y = 110;y>0;y--);
}
void init()
{
TMOD = 0x10;
TH1 = (65536-4608)/256;//50sm
TL1 = (65536-4608)%256;
TR1 = 1;
}
void create_PWM(uchar count)
{
static i;
if(TF1 == 1)
{
TF1 = 0;
TH1 = (65536-4608)/256;//50sm
TL1 = (65536-4608)%256;
i++;
if(i == 100) i=0;
if(i <= count) PWM = 1;
else PWM = 0;
}
}
void key_control()
{
if(key_1 ==0)
{
delay(10);
if(key_1 == 0)
{
count+= 5;
if(count >= 100)count = 0;
}
}
if(key_2 ==0)
{
delay(10);
if(key_2 ==0)
{
count-= 5;
if(count <= 0)count =100;
}
}
}
给个我自己写的程序你,我试过了,通过!
#include
#define
uchar
unsigned
char
#define
uint
unsigned
int
sbit
P0_0=P0^0;
uchar
a;
/
TH0和TL0是计数器0的高8位和低8位计数器,
计算办法:TL0=(65536-C)%256;
TH0=(65536-C)/256,
其中C为所要计数的次数即多长时间产生一次中断;
TMOD是计数器工作模式选择,0X01表示选用模式1,
它有16位计数器,最大计数脉冲为65536,最长时间
为1ms65536=65536ms
/
void
init_sys(void);
/系统初始化函数/
void
main
(void)
{
init_sys();
while(1);
}
void
init_sys(void)
{
TMOD=0x01;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET0=1;
TR0=1;
}
void
timer0(void)
interrupt
1
{
TH0=(65536-100)/256;
TL0=(65536-100)%256;
a++;
if(a<=3)
{
P0_0=1;
if(a==3)
//改变低电平持续时间
{
//也即改变占空比
P0_0=~P0_0;
}
}
else
{
P0_0=0;
if(a==5)
//改变周期
{
a=0;
}
}
}
用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比。大致的的编程思路是这样的:T0定时器中断让一个I0口输出高电平,在这个定时器T0的中断当中起动定时器T1,而这个T1是让IO口输出低电平,这样改变定时器T0的初值就可以改变频率,改变定时器T1的初值就可以改变占空比。
用一个定时器时(如定时器T0),首先你要确定PWM的周期T和占空比D,确定了这些以后,你可以用定时器产生一个时间基准t,比如定时器溢出n次的时间是PWM的高电平的时间,则DT=nt,类似的可以求出PWM低电平时间需要多少个时间基准n'。
因为这里我们是产生周期为1ms(1000HZ)的PWM,所以可设置中断的时间基准为001ms,,然后中断100次即为1ms。在中断子程序内,可设置一个变量如time,在中断子程序内,有三条重要的语句:1、当time>=100时,time清零(此语句保证频率为1000HZ),2、当time>n时(n应该在0-100之间变化开),让单片相应的I/O口输出高电平,当time<n时,让单片相应的I/O口输出低电平,此时占空比就为%n。
这是我以前写的用51单片机控制舵机的程序,也是调PWM的,两按键,一个开始一个暂停,自己去琢磨吧,希望对你有帮助
int main(void)
{
P2=0XFF;
P0=0XFF;
// P3=0X00;
// P1=0X00;
lcd1602_init();
TMOD=0x01; //方式1,16位计数器方式
TH0=0xff;
TL0=0xab; //定时01ms
IE=0x82; //开定时器中断
ET0=1;
TR0=1;
EA=1;
while(1)
{
keyscan();
if(keyvalue&m_start)
{
lcd1602_nwd(0x00,1,disply1,13);
if(high_flag)
{
high_flag=0;
if(i_d_flag)
{
hight_votage--;
if(hight_votage<=5)
{
i_d_flag=0;
delays(m_05s);
// delayms(1000);
// hight_votage=5;
}
}
else
{
hight_votage++;
if(hight_votage>=25)
{
i_d_flag=1;
cont_flag=1;
delays(m_05s);
// delayms(1000);
// high_votage=25;
}
}
}
if(cont_flag)
{
cont_flag=0; //圈数计数标志位
date_inc(disply);
lcd1602_nwd(0x00,2,disply,5);
}
if(keyvalue&m_stop)
{
keyvalue=keyvalue&0xe7;
}
}
}
}
void timer0() interrupt 1
{
// TH0=0xfe;
// TL0=0x0b;
TH0=0xff;
TL0=0xa9;
// flag_01ms=1;
t_num++;
// engine_pwm=~engine_pwm;
if(t_num>=200)
{
time_20ms++;
f_keytime=1;
t_num=0;
engine_pwm=1;
flag_pwm=1;
}
if(flag_pwm)t_cont++;
if(flag_pwm&&(t_cont>hight_votage))
{
high_flag=1;
flag_pwm=0;
t_cont=0;
engine_pwm=0;
}
if(f_buzzle)buzzle=~buzzle;
}
定个时间20ms周期的定时器,然后在定时器到达那些点的时候,让自己设的那些变量依次变化。 再根据自己的变量,付给输出端口就可以了。 看着像舵机的
看了你追问的,原来是四路每一路都产生变化的波形。那个也好办。可以通过计算,把这几个波形统一起来成一个周期,比如开始05ms到了,让定的值取反,再加195再取反,再加13Ms再取反,再加187ms再取反然后一直这样把几个都写完。
还有种方法,来改变第一个pwm的设定值。比如放数组里一共5个设定值,分别代表你设定的高电平时间,依次替换第一个定时器里面的中端时间即可。
当然,前两种都差不多,还有一种方法供你扩展:就是用两个定时器,然后按照时间去匹配修改。当然,51单片机那精度就不说了,不太确信可以达标,一个定时器进中断了,另一个就要停一下。。
BTW,个人感觉51的单片机没有很好的pwm模块,这样写了Pwm程序,别的就干不了了。建议用用带epwm模块的mcu,直接调用epwm和epwm中断,节省cpu资源,可以多写很多程序。
以上就是关于51单片机输出几组pwm波形,程序简单,编译没错,但就是不输出,控制舵机全部的内容,包括:51单片机输出几组pwm波形,程序简单,编译没错,但就是不输出,控制舵机、51单片机产生频率为1KHZ,占空比可调的PWM汇编程序,初学者,求完整程序、请教51单片机利用PWM控制灯的亮度的程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)