基于51单片机的直流电机PWM控制系统

本是学校的一门课程设计内容,分享出来吧,也许会对以后的学妹学弟有帮助呢?

设计思路

直流电机PWM控制系统的主要功能包括:直流电机的加减速、电机的正反转以及电机的启停,并且可以调整电机的转速,还可以方便的读出电机转速的大小,能够很方便的实现电机的智能控制。该直流电机系统由以下电路模块组成:

组成模块
振荡器和时钟电路:这部分电路主要由80C51单片机和一些电容、晶振组成。
设计输入部分:这一模块主要是利用6个独立的按键来实现。
设计控制部分:主要由80C51单片机的外部中断扩展电路组成。
设计显示部分:由LCD1602液晶显示模块组成; 
直流电机PWM控制实现部分:主要由一些二极管、电机和L298直流电机驱动模块组成。

基本原理 

当按键扫描到有输入信号时,通过80C51单片机产生脉宽可调的脉冲信号并输入到L298驱动芯片来控制直流电机工作,从而实现电机的调速功能。再通过分析电机运转发出的脉冲周期计算出电机的速度,送给LCD1602显示。

总体设计框图

方案说明:直流电机PWM调速系统以AT89C51单片机为控制核心,由命令输入模块、LCD显示模块及电机驱动模块组成。单片机在程序控制下,定时不断给直流电机驱动芯片发送PWM波形,L298完成电机正,反转控制;同时单片机不停的将从电机发出的脉冲处理后,送到LCD显示模块去显示转速。整个系统的组成原理图如下图所示。

系统组成框图

系统原理图

系统原理图

程序设计

整个程序由主程序以及9个子程序外加两个中断服务子程序组成。这9个子程序分别是:按键扫描、定时器初始化、LCD初始化、按键消抖、欢迎界面延时、LCD写数据、LCD写命令、LCD速度显示、LCD欢迎界面显示。

按键扫描:用来判断按钮是否被按下,从而实现相关功能。

void BtnSca() 
{
    if ( start == 0 || btnforward == 0 ) 
    {
        backward    = 0;
        forward        = 1;
        Flag        = 1;
        TR0        = 1;
    } else if ( stop == 0 ) 
    {
        backward    = 1;
        forward        = 1;
        Flag        = 0;
        TR0        = 0;
    } else if ( btnbackward == 0 && Flag == 1 ) 
    {
        backward    = 1;
        forward        = 0;
        Flag        = 0;
        /* TR0=1; */
    }
    if ( speedup == 0 ) 
    {
        BtnDelay( 10 );
        /* 消抖 */
        if ( speedup == 0 ) 
        {
            Hcount++;
            if ( Hcount >= Lcount ) 
            {
                Hcount = 16;
            }
        }
        while ( !speedup )
                    ;
        /* 等待键松开 */
    }
    if ( speeddown == 0 ) 
    {
        BtnDelay( 10 );
        /* 消抖 */
        if ( speeddown == 0 ) 
        {
            Hcount--;
            if ( Hcount <= 0 ) 
            {
                Hcount = 0;
            }
        }
        while ( !speeddown );
        /* 等待键松开 */
    }
}

定时器初始化:初始化定时器用,设定相关参数

/****************定时器初始化*****************/
void TInit()
{
    TMOD    = 0x11;                       /* 设置定时器T工作于方式 */
    TH0    = setTHTL / 256;
    TL0    = setTHTL % 256;
    ET0    = 1;                            /* 开定时器中断 */
    EA    = 1;                            /* 开总中断 */

    TH1    = (65536 - 50000) / 256;        /* TH1装初值为65536-50000=15536,即定时50000us,相当于50毫秒。 */
    TL1    = (65536 - 50000) % 256;        /* TL1装初值为65536-50000=15536 */
    EX1    = 1;                            /* 开外部中断1允许 */
    IT1    = 1;                            /* 设置外部中断0下降触发中断 */
    ET1    = 1;                            /* 打开定时器1中断允许 */
    TR1    = 1;                            /* 开定时器1 */
}

LCD初始化:初始化LCD1602面板

void lcd_init()
{
    writecmd( 0x38 );       /* 设置16*2显示模式 */
    writecmd( 0x0c );       /* 开显示 */
    writecmd( 0x01 );       /* 清屏 */
    writecmd( 0x06 );       /* 地址指针+1 */
}

按键消抖:用来消除按键的抖动,防止输入错误信号

/****************延时消抖**********************/
void BtnDelay( i )
{
    for ( j = i; j > 0; j-- )
        for ( k = 125; k > 0; k-- )
            ;
}

欢迎界面延时:起到显示欢迎界面时长的作用,延时到达就擦除

/****************首屏欢迎延时****************/
void delay( void )
{
    unsigned char a, b, c;
    for ( c = 167; c > 0; c-- )
        for ( b = 171; b > 0; b-- )
            for ( a = 1; a > 0; a-- )
                ;
}

LCD写数据:写数据到LCD1602

/* 写数据 */

void writedat( unsigned char wd )
{
    busy();
    RS    = 1;
    RW    = 0;
    P2    = wd;
    EN    = 1;
    EN    = 0;
}

LCD写命令:通过1602的一些端口操作1602相关设置

/* 写命令 */

void writecmd( unsigned char wr )
{
    busy();
    RS    = 0;
    RW    = 0;
    P2    = wr;
    EN    = 1;
    EN    = 0;
}

LCD速度显示:通传入参数,将参数显示在1602上

/* 显示函数 */
void display( unsigned int rate )
{
    unsigned char wan, qian, bai, shi, ge;
    wan    = rate / 10000;
    qian    = rate / 1000 % 10;
    bai    = rate / 100 % 10;
    shi    = rate / 10 % 10;
    ge    = rate % 10;
    v    = 0;
    writecmd( 0x80 | 0x00 );
    while ( dis3[v] != '\0' )
    {
        writedat( dis3[v] );
        v++;
    }
    ;
    writecmd( 0x80 | 0x40 );        /* 显示地址 */
    writedat( '0' + wan );          /* 将字符常量v写入LCD */
    writedat( '0' + qian );
    writedat( '0' + bai );
    writedat( '0' + shi );
    writedat( '0' + ge );
    v = 0;
    while ( dis4[v] != '\0' )
    {
        writedat( dis4[v] );
        v++;
    }
    ;
}

LCD欢迎界面显示:通传入参数,将参数显示在1602上

/****************首屏欢迎词****************/
void displayWelcome()
{
    writecmd( 0x80 | 0x00 );        /* 显示地址 */
    while ( dis1[v] != '\0' )
    {
        writedat( dis1[v] );
        v++;
    }
    v = 0;
    writecmd( 0x80 | 0x40 );        /* 显示地址 */
    while ( dis2[v] != '\0' )
    {
        writedat( dis2[v] );
        v++;
    }
}

附件下载

包括Proteus仿真以及Keil5的工程文件。
蓝奏云下载

打赏
评论区
头像
    头像
    SOMEBODY
      

    楼主大大,蓝奏云连接失效了

      头像
      Veen Zhao
        
      @SOMEBODY

      已更新

    头像
    JefferIF
      

    很强,但不懂

文章目录