51单片机输出几组pwm波形,程序简单,编译没错,但就是不输出,控制舵机

51单片机输出几组pwm波形,程序简单,编译没错,但就是不输出,控制舵机,第1张

你这个程序 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控制灯的亮度的程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存