找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 11045|回复: 11
收起左侧

发一个pwm直流电机调速程序,LCD段码屏显示的程序

[复制链接]
ID:77707 发表于 2015-4-22 13:34 | 显示全部楼层 |阅读模式
写这个程序是要实现,用按键+,-使电机调速,并在LCD段码屏上
出现累加的两位数字显示。
****************************************
段式LCD驱动和电机调速实验            
外部晶体:12MHz                    
作者:dpj555                 
邮箱:            
日期:2015.03.26                  
******************************************/
#include <reg52.h>
#include <stdio.h>
#define uint unsigned int
#define uchar unsigned char
/*管脚定义*/
sbit COM1=P1^7;
sbit COM2=P1^6;
sbit BI_4=P1^5;
sbit RTC_CLK=P1^4;
sbit RTC_IO=P1^3;
sbit RTC_RST=P1^2;   //复用
/*P3口模式寄存器*/
sfr P3M1=0xb1;
sfr P3M0=0xb2;
/* 开机默认显示*/
unsigned char ClockBuffer[8]={0x34,0x12,0x08,0x20,0x03,0x05,0x09};
/********************************
0~9的段码查询表
位序 D7 D6 D5 D4 D3 D2 D1 D0
段   A  B  C  D  E  F  G  DOT
*********************************/
code unsigned char seg_code[10]={~0x03,~0x9f,~0x25,~0x0d,~0x99,~0x49,~0x41,~0x1f,~0x01,~0x09};
unsigned char ScanCoun=0;                  //动态扫描显示位数计数器
unsigned char DisplayBuf[2]={1,2 };               //2位数字对应的显示暂存
/*段码缓冲区*/
unsigned char SegBuf[2]={0x00,0x00};//COM1、COM2 的段码
bit bi_4a=0; //COM1对应的4a
bit bi_4b=0; //COM2对应的4b
/*延时*/
void dly(unsigned char x)
   {unsigned char i;
    for (i=0; i<x; i++);
    }
/*ds1302写1字节*/
void rtc_wt_byte(unsigned char sent_buf)
         {unsigned char i;
          for (i=0; i<8; i++)
              {RTC_CLK=0;
               if (sent_buf&0x01) RTC_IO=1;
               else RTC_IO=0;
               RTC_CLK=1;
               dly(5);
               sent_buf=sent_buf>>1;
               }
              RTC_CLK=0;
              dly(5);
           }
/*ds1302读1字节*/
unsigned char rtc_rd_byte(void)
          {unsigned char i,read_buf;
           RTC_IO=1;         //RTC_IO置1,保证为输入状态
           for (i=0; i<8; i++)
               {read_buf=read_buf>>1;
                       RTC_CLK=0;
                       dly(5);
                if (RTC_IO) read_buf=read_buf|0x80;
                else read_buf=read_buf&0x7f;
                RTC_CLK=1;
                dly(5);
               }
           RTC_CLK=0;
           dly(5);
           return read_buf;
          }
/*ds1302写入时间*/
void rtc_wr_time(unsigned char *p_wt_time)
           {unsigned char i;
            unsigned char tmp1;
            dly(30);
            RTC_RST=1;
            rtc_wt_byte(0xbe);         //burst写入时间
            for (i=0; i<8; i++)
                  {tmp1=*p_wt_time++;
                   rtc_wt_byte(tmp1);
                   }
            RTC_CLK=0;
            RTC_RST=0;
           }
/*ds1302读出时间*/
void rtc_rd_time(unsigned char *p_rd_time)
           {unsigned char i;
            unsigned char tmp1;
            dly(30);
            RTC_RST=1;
            rtc_wt_byte(0xbf);        //burst读取时间
            RTC_IO=1;
            for (i=0; i<8; i++)
                  {tmp1=rtc_rd_byte();
                   *p_rd_time++=tmp1;
                  }
            RTC_CLK=0;
            RTC_RST=0;
           }
/*ds1302初始化*/
void ini_rtc()
         {RTC_CLK=0;
          RTC_RST=0;
          dly(30);
          RTC_RST=1;               
          rtc_wt_byte(0x8e);        //写CONTROL寄存器
          rtc_wt_byte(0x00);        //值:去掉写保护
          RTC_RST=0;                //复位
          RTC_RST=1;                //正常工作
          rtc_wt_byte(0x90);        //写TRICKLE CHARGER寄存器
          rtc_wt_byte(0xa9);        //值:使能充电,串联2个二极管,串联2k欧姆的电阻
          RTC_CLK=0;
          RTC_RST=0;
         }
/***********************************************************************************
把2位数字的SEG放到COM1、COM2 对应的段码
LCD的管脚定义与LED不同,它不是一个COM对应一位数字,而是对应每个数字的一部分SEG
1   2   3   4   5   6   7   8  
<  1f  1a  2f  2a      3f  3a  4f  4a   >          --       ---- COM1
<  1g  1b  2g  2b      2g  3b  4g  4b   >          --       ---- COM2
***********************************************************************************/
void Seg2Seg()
{unsigned char SegXX;

SegBuf[1]=0;
SegBuf[2]=0x08;
bi_4a=0;
bi_4b=0;
SegXX=seg_code[DisplayBuf[0]];      //第1位数字
if (SegXX&0x80) SegBuf[0]|=0x40;
if (SegXX&0x40) SegBuf[1]|=0x40;
if (SegXX&0x20) SegBuf[2]|=0x40;
if (SegXX&0x10) SegBuf[3]|=0x80;
if (SegXX&0x08) SegBuf[2]|=0x80;
if (SegXX&0x04) SegBuf[0]|=0x80;
if (SegXX&0x02) SegBuf[1]|=0x80;
if (SegXX&0x01) SegBuf[3]|=0x40;
  SegXX=seg_code[DisplayBuf[1]];    //第2位数字
if (SegXX&0x80) SegBuf[0]|=0x10;
if (SegXX&0x40) SegBuf[1]|=0x10;
if (SegXX&0x20) SegBuf[2]|=0x10;
if (SegXX&0x10) SegBuf[3]|=0x20;
if (SegXX&0x08) SegBuf[2]|=0x20;
if (SegXX&0x04) SegBuf[0]|=0x20;
if (SegXX&0x02) SegBuf[1]|=0x20;
if (SegXX&0x01) SegBuf[3]|=0x10;
}
/*一个BCD码转化成两个十进制数(如:0x79转化成0x07和0x09)*/
BcdToDec(unsigned char BcdValue,unsigned char *pDecValue)
       {//if (BcdValue>=0x9a||(BcdValue&0x0f)>=0x0a) return 0;
               *pDecValue++=(BcdValue&0xf0)>>2;
        *pDecValue=BcdValue&0x0f;
        //return 1;
       }
//初始化MCS51内部资源
InitInterResource()
       {IE=0;       //关全部中断
        TCON=0;     //清全部中断请求
        IP=0;       //清中断优先级
        TMOD=0x01;  //T0工作方式1(16位定时器)
        TH0=0x00;   //T0定时器辅初值
        TL0=0x00;
        TR0=1;      //允许T0定时
        ET0=1;      //允许T0中断
        EA=0;       //关全局中断
        RTC_RST=0;
       }
void main()
    {   
     InitInterResource();
     ini_rtc();                    //初始化DS1302
     rtc_wr_time(ClockBuffer);     //写入时间初始值
     EA=1;         //开全局中断
     while(1)
        {         
        }
    }
//定时器0中断服务程序,5ms定时器,4位数码管动态显示驱动
void tmr0_p(void) interrupt 1
    {
     TL0=0x78;     //重新定时5ms
     TH0=0xec;
     Seg2Seg();
     P3M1=0x3c;
     P3M0=0x00;
          switch(ScanCoun)                //动态扫描显示
         {

          case 1:                       //COM1正向驱动
          P1= SegBuf[1];
          BI_4= bi_4a;
          COM1=0;            
          P3M1=0x2c;
          P3M0=0x00;
          break;
          case 2:                       //COM1反向驱动
          P1= ~SegBuf[1];
          BI_4= ~bi_4a;
          COM1=1;                  
          P3M1=0x2c;
          P3M0=0x00;
          break;
          case 3:                       //COM2正向驱动
          P1= SegBuf[2];
          BI_4= bi_4b;
          COM2=0;                  
          P3M1=0x34;
          P3M0=0x00;
          break;
          case 4:                       //COM2反向驱动
          P1= ~SegBuf[2];
          BI_4= ~bi_4b;
          COM2=1;                  
          P3M1=0x34;
          P3M0=0x00;
          break;
         }
     ScanCoun++;       //下一位
     if (ScanCoun>2) ScanCoun=0;      
     }
/*使单片机输出PWM调速*/
/************************************************************************
为了使大家彻底掌握此方面,下面再给出一个复杂一点的程序,实现的功能为
通过按键使之可以在0到20级之间调速的程序。
/***********************************************************************/
/* 程序名:PWM直流电机调速 */
/* 晶振:11.00592 MHz CPU型号:STC12C2051 */
/* 直流电机的PWM波控制,可以通过按键控制正反转并在0到20级之间调速 */
/*****************************************************************/
uchar time,count=50,flag=1;//低电平的占空比

sbit PWM1=P3^5;//PWM 通道 1,反转脉冲
sbit PWM2=P3^7;//PWM 通道 2,正转脉冲
sbit key_add=P1^1;//电机加速
sbit key_dec=P1^2;//电机减速
/************函数声明**************/
void delayxms(uint z);
void Motor_turn();
void Motor_add();
void Motor_dec();
void timer0_init();
/****************延时处理**********************/
void delayxms(uint z)//延时xms程序
{
    uint x,y;
        for(y=z;x>0;x--)
        for(y=110;y>0;y--);
/*********主函数********************/
        timer0_init();
        while(1)
        
                Motor_turn();
                Motor_add();
                Motor_dec();
        
}
void Motor_add()//电机加速
{
        if(key_add==0)
        {
                  delayxms(2);//此处时间不能太长,否者会的中断产生冲突
                  if(key_add==0)
                  {
                    count+=5;
                        if(count>=100)
                        {
                                count=0;
                        }
                  }
                  while(!key_add);
        }
}
void Motor_dec()//电机加减速
{
        if(key_dec==0)
        {
                  delayxms(2);//此处时间不能太长,否者会的中断产生冲突
                  if(key_dec==0)
                  {
                    count-=5;
                        if(count>=100)
                        {
                                count=0;
                        }
                  }
                  while(!key_dec);
        }
}

/***********定时器0初始化***********/
void timer0_init()
{
        TMOD=0x01; //定时器0工作于方式1
        TH0=(65536-10)/256;
        TL0=(65536-10)%256;
        TR0=1;
        ET0=1;
        EA=1;
}
/**************定时0中断处理******************/
void timer0_int() interrupt 1
{        
        TR0=0;//设置定时器初值期间,关闭定时器
        TH0=(65536-10)/256;
        TL0=(65536-10)%256;
        TR0=1;        
        if(flag==1)//电机正转
        {
                PWM1=0;
                   time++;
                  if(time<count)
                  {
                    PWM2=1;
                  }
            else
            PWM2=0;
        
            if(time>=100)
            {
                    time=0;
            }
        }
        else //电机反转
        {
                PWM2=0;
                  time++;
            if(time<count)
            {
                    PWM1=1;
            }
            else
                    PWM1=0;
            
            if(time>=100)
            {
                    time=0;
            }
        }
}

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的积分奖励!

查看全部评分

回复

使用道具 举报

ID:1099381 发表于 2023-11-12 04:24 | 显示全部楼层
好资料,整好用的上
回复

使用道具 举报

ID:1095483 发表于 2023-11-10 18:05 | 显示全部楼层

感谢版主
回复

使用道具 举报

ID:71535 发表于 2015-4-24 07:59 | 显示全部楼层
感谢版主加分鼓励
回复

使用道具 举报

ID:76929 发表于 2015-4-24 07:08 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:77707 发表于 2015-4-23 09:14 | 显示全部楼层
感谢版主加分鼓励。
回复

使用道具 举报

ID:77707 发表于 2015-4-23 09:08 | 显示全部楼层
本帖最后由 dpj555 于 2015-4-24 08:14 编辑

更改后的图

Snap5.jpg
回复

使用道具 举报

ID:77707 发表于 2015-4-23 09:06 | 显示全部楼层
gaozhaohong 发表于 2015-4-22 14:33
资料不错 不过简图中的R2R3中间的一颗线 和R4R5中间的一颗线都接在P1.6上吗?

抱歉!错了应该p1.7上有一个,给com2 位供2.5v电压。
回复

使用道具 举报

ID:76408 发表于 2015-4-22 20:42 | 显示全部楼层
图在下面没注意到,对不起
回复

使用道具 举报

ID:76408 发表于 2015-4-22 20:40 | 显示全部楼层
最好有图容易看得懂。
回复

使用道具 举报

ID:61876 发表于 2015-4-22 14:33 | 显示全部楼层
资料不错 不过简图中的R2R3中间的一颗线 和R4R5中间的一颗线都接在P1.6上吗?
回复

使用道具 举报

ID:77707 发表于 2015-4-22 14:09 | 显示全部楼层
再附张简图
Snap2.jpg

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表