打印

如何利用51单片机实现直流电机调速!

[复制链接]
3947|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
弟儿|  楼主 | 2008-12-8 19:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
zq1987731| | 2008-12-8 20:10 | 只看该作者

定时器输出方波的实验做过吧?

通过定时器控制IO输出不同的占空比方波给直流电机就能实现直流电机调速,
简称PWM...

使用特权

评论回复
板凳
弟儿|  楼主 | 2008-12-8 20:18 | 只看该作者

超级感谢2楼的哥们!

使用特权

评论回复
地板
qwertyuiop_mm| | 2008-12-8 22:55 | 只看该作者

PWM+PID.

为了50分的目标而回贴

使用特权

评论回复
5
弟儿|  楼主 | 2008-12-9 10:11 | 只看该作者

还有别的方法吗?

使用特权

评论回复
6
弟儿|  楼主 | 2008-12-9 15:03 | 只看该作者

接下去的程序该如何编?

接下去的程序该如何编? 

我想利用AT89C51实现直流电机调速,我不知道接下去的程序该如何编?希望大家给点编程的思路!

使用定时器0以工作方式2产生周期为100us的连续正方波脉冲,晶振频率为6MHZ
机器周期为2us,以TH0作为重装载的预置寄存器,TL0作为8位计数器,假使计数初值为X,则
求出X=231D=0E7H
TH0=0E7H     TL0=0E7H
程序:
ORG    0000H
AJMP   MAIN
ORG    0003H
AJMP   EXINT0                转向外部中断0
MAIN:MOV    TCON,  #01H      脉冲触发方式
     MOV    IE,     #83H     开放外部中断0,定时器0,其他中断禁止
     MOV    IP,     #01H     外部中断0为高优先级,其余为低优先级
     MOV    TOMD, #02H       设置定时器0为方式2
     MOV    TH0,   #0E7H      保存计数初值
     MOV    TL0,   #0E7H      预置计数初值
     SETB    TR0              启动定时
EXINT0:   JBC     TF0,   LOOP 查询计数溢出
          AJMP    EXINT0
LOOP:     CPL      P1.0       从P1.0口输出方波
          AJMP    EXINT0      重复循环
我想实现3级调速(低速档,中速档和高速档),得开3个中断吗?可是只有   和 INT0 和 INT1 两个外部中断,如何编程?
 
 

使用特权

评论回复
7
zq1987731| | 2008-12-9 17:53 | 只看该作者

以前写着玩的程序,参考一下吧,要想有所进步就不要照抄

;假设你的2个按键(单IO驱动,有上拉电阻,按键按下对应0,未按下对应1)连接对应P1.1,P1.2(加速键,减速键),送入H桥的PWM输出脚为P3.5

PWMH    DATA    30H                ;高电平脉冲的个数
PWM    DATA    31H                ;PWM周期
COUNTER    DATA    32H
TEMP    DATA    33H

    ORG    0
    AJMP    MAIN
    ORG    30H
    AJMP    INTT0

    ORG    8100H
MAIN:    
    MOV    SP,#60H                ;给堆栈指针赋初值
    MOV    PWMH,#02H            ;
    MOV    COUNTER,#01H
    MOV    PWM,#15H
    MOV    TMOD,#02H            ;定时器0在模式2下工作
    MOV    TL0,#38H            ;定时器每200us产生一次溢出
    MOV    TH0,#38H            ;自动重装的值
    SETB    ET0                ;使能定时器0中断
    SETB    EA                ;使能总中断
    SETB    TR0                ;开始计时
KSCAN:    
    JNB    P1.1,K1CHECK            ;扫描KEY1,
    JNB    P1.2,K2CHECK            ;扫描KEY2,如果按下KEY2,跳转到KEY2处理程序
    SJMP    KSCAN                

K1CHECK:
    JB    P1.1,K1HANDLE            ;去抖动,如果按下KEY1,跳转到KEY1处理程序
    SJMP    K1CHECK
K1HANDLE:
    MOV    A,PWMH                
    CJNE    A,PWM,K1H0            ;判断是否到达上边界
    SJMP    KSCAN                ;是,则不进行任何操作
K1H0:
    MOV    A,PWMH
    INC    A
    CJNE    A,PWM,K1H1            ;如果在加1后到达最大值
    CLR    TR0                ;定时器停止
    SETB    P1.0                ;P1.0为高电平
    SJMP    K1H2                
K1H1:
    CJNE    A,#02H,K1H2            ;如果加1后到达下边界
    SETB    TR0                ;重开定时器
K1H2:
    INC    PWMH                ;增加占空比
    SJMP    KSCAN

K2CHECK:
    JB    P1.2,K2HANDLE            ;去抖动,如果按下KEY2,跳转到KEY2处理程序
    SJMP    K2CHECK
K2HANDLE:
    MOV    A,PWMH
    CJNE    A,#01H,K2H0            ;判断是否到达下边界
    SJMP    KSCAN                ;是,则不进行任何操作
K2H0:
    MOV    A,PWMH
    MOV    TEMP,PWM
    DEC    A
    CJNE    A,#01H,K2H1            ;如果在减1后到达下边界
    CLR    TR0                ;定时器停止
    CLR    P1.0                ;P1.0为低电平
    SJMP    K2H2
K2H1:
    DEC    TEMP
    CJNE    A,TEMP,K2H2            ;如果到达上边界
    SETB    TR0                ;启动定时器
K2H2:
    DEC    PWMH                ;降低占空比
    SJMP    KSCAN
    

INTT0:
    PUSH    PSW                ;现场保护
    PUSH    ACC
    INC    COUNTER                ;计数值加1
    MOV    A,COUNTER
    CJNE    A,PWMH,INTT01            ;如果等于高电平脉冲数
    CLR    P1.0                ;P1.0变为低电平
INTT01:    CJNE    A,PWM,INTT02            ;如果等于周期数
    MOV    COUNTER,#01H            ;计数器复位
    SETB    P1.0                ;P1.0为高电平
INTT02:    POP    ACC                ;出栈
    POP    PSW
    RETI
    
    END

===============================C语言写的要比上面的汇编程序可读性强得多==============================
#include "reg52.h"

sbit PWMout=P3^5;
sbit KEY1=P1^1;
sbit KEY2=P1^2;

unsigned char PWMH;            //高电平脉冲的个数
unsigned char PWM;            //PWM周期
unsigned char COUNTER;        //计数器

void INTTO() interrupt 1 
{
    COUNTER++;                    //计数器值加1
    if(COUNTER==PWM)            //如果计数器值等于PWM周期数
    {
        COUNTER=0;                //计数器复位
        PWMout=1;                //PWMout为高电平
    }
    if(COUNTER==PWMH)PWMout=0;    //如果计数器值等于高电平脉冲数,PWMout变为低电平
}

/***********************************************************************
* 名称:DelayS()
* 功能:长软件延时。
* 入口参数:dly延时时间控制
***********************************************************************/
void  DelayS(unsigned int dly)
{  
    unsigned int i;
    for(; dly>0; dly--)
       {  
        for(i=0; i<1000; i++);  
       }
}

void keyCheck(void)
{  
    unsigned char temp;
    if(KEY1==0)
    {
        DelayS(5);
        while(KEY1==0);
        temp=PWMH;
        temp++;
        if(temp>=PWM)temp=2;
        PWMH=temp;            

    }
    if(KEY2==0)
    {
        DelayS(5);
        while(KEY2=0);
        temp=PWMH;
        if(temp>2)temp--;
        else temp=PWM-1;
        PWMH=temp;            
    }
}

main()
{
    PWM=28;
    PWMH=2;    
    COUNTER=0;    
    TMOD=0x02;            //定时器0在模式2下工作
    TL0=0x38;            //定时器每200us产生一次溢出
    TH0=0x38;            //自动重装的值
    ET0=1;                //使能定时器0中断
    EA=1;                //使能总中断
    TR0=1;                //开始计时

    while(1)
    {
        keyCheck();
    }                
}

使用特权

评论回复
8
kidcao1987| | 2008-12-9 19:14 | 只看该作者

ding loushang

ding  loushang

使用特权

评论回复
9
弟儿|  楼主 | 2008-12-10 16:23 | 只看该作者

再次感谢8楼的朋友!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

24

帖子

0

粉丝