找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2629|回复: 0
打印 上一主题 下一主题
收起左侧

单片机+直流电机调速不能实现降速

[复制链接]
跳转到指定楼层
楼主
5黑币
是利用ad/da控制电枢电流控制转速附件有程序和proteus仿真。
因为是新手,第一次写c程序。设计速度加上去后再减速发现不能达到要求,请各位帮帮忙。

单片机源程序如下:
#include <reg52.h>
#define  digital P0                 //DAC0832 数据管脚
#define  leddat  P1                   //数码管数据管脚
#define   en    1    //电机一圈的脉冲数 根据电机实际参数设定
#define uint unsigned int
#define uchar unsigned char
#define ufloat unsigned float
sbit scl=P3^5;
sbit sda=P3^7;
sbit Y3 = P3^0;              //数码管段选脚定义
sbit Y2 = P3^1;
sbit Y1 = P3^2;
sbit Y0 = P3^3;
sbit Y7 = P2^0;              //数码管段选脚定义
sbit Y6 = P2^1;
sbit Y5 = P2^2;
sbit Y4 = P2^3;
sbit LSA = P2^4;             //138译码器管脚定义
sbit LSB = P2^5;
sbit LSC = P2^6;
sbit  LSG1 = P2^7;
char code Led_dat[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};       //共阴数码管段码 0123456789
long double speed=0;
long int count=0;  //记录脉冲数量
void Delay10us()
{
        unsigned char a,b;
        for(b=1;b>0;b--)
                for(a=2;a>0;a--);

}

void delay()  //延时几微秒。延时函数在很多函数里都要用它。至少要大于4.7us
{;;}          //当你把这个函数写在用它这个函数的前面就不用声明了

void init()  //初始化总线。将总线都拉高以释放
{
        scl=1;
        delay();  //I2C总线使用时一般都要延时5us左右
        sda=1;
        delay();
}

void start() //启始信号。 时钟信号为高电平期间,数据总线产生下降沿。
{            //为什么要下降沿,且sda先要为1。因为先要保证数据线为空才能工作
        sda=1;   //先释放数据总线。高电平释放
        delay();
        scl=1;
        delay();
        sda=0;
        delay();
}

void stop()
{
        sda=0;  //先要有工作状态才能释放,sda=0时在工作状态
        delay();
        scl=1;
        delay();
        sda=1;  //释放数据总线
        delay();
}

void respons()  //应答函数
{
        uchar i=0;
        scl=1;  //每个字节发送完后的第九个时钟信号的开始
        delay();
        while((sda==1)&&(i<255))   //此处i的定义使用了uchar.只要填一个小于255的就行
        i++;                       //此处的sda是从机的
        scl=0; //表示主器件默认从器件已经收到而不再等待。不再等待之后,时钟的高电平过了就是低电平,所以scl=0
               //此时第酒个时钟信号结束
}

void writebyte(uchar d)  //写一字节,每次左移一位
{
        uchar i,temp;
        temp=d;
        for(i=0;i<8;i++)
        {
                temp=temp<<1;
                scl=0;        //数据传输期间要想sda可变,先把时钟拉低。此处要给sda赋值
                delay();
                sda=CY;       //CY为左移移入PSW寄存器中的的CY位。
                delay();
                scl=1;        //sda有数据了。保持数据稳定
                delay();
        }
        scl=0;            //此处是写数据,是属于数据传输过程中。只有在时钟信号为低电平期间
        delay();          //数据总线才可以变化。
        sda=1;            //所以要想释放数据总线,就必须先把时钟拉低
        delay();         
        /*此处释放总线写在末尾是因为调用它时,前面有起始函数释放了总线*/
}

uchar readbyte()
{
        uchar i,k;
        scl=0;
        delay();
        sda=1;
        delay();
        /*此处释放总线放在前面是因为一般都是先写后读,保险起见,释放一下总线*/
        for(i=0;i<8;i++)
        {
                scl=1;     //一个时钟信号的开始
                delay();
                k=(k<<1)|sda;    //实质是把sda的数据,最先传来的放在最高位,依次往下排
                scl=0;    //一个时钟信号结束
                delay();
        }
        return k;
}
void write(uchar addr,uchar dat)
{
        start();          //初始化
        writebyte(0x90);      //调用写一字节函数.PCF8591为1001。此处是给从机发送写信号(最低位是0)
        respons();            //调用应答函数让从机应答
        writebyte(addr);      //写入地址
        respons();            //每写一字节都要应答
        writebyte(dat);
        respons();
        stop();
}

uchar read(uchar addr)
{
        uchar dat;
        start();
        writebyte(0x90);      //从此处的发送地址和方向位0到从机
        respons();            //此处的从机产生应答。属于“伪写”。用于确定和哪台机子通信
        writebyte(addr);
        respons();
        start();
        writebyte(0x91);      //从此处开始,从机向主机写数据。读的方向位为1
        respons();
        dat=readbyte();
        stop();
        return dat;           //读得的数据要返回
}


void delay1(int i)           //延时函数
{
                while(i--);
}

void display(int x,int y)           //数码管操作函数
{

        delay1(100);
        leddat = ~0x00;                       //清屏消隐
        Y0=0;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1;                     //段选1
        leddat = ~Led_dat[x%10];               //取余数 取出个位数
        
        delay1(100);
        leddat = ~0x00;
        Y0=1;Y1=0;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1;                  //段选2
                leddat = ~Led_dat[x/10%10];         //取出十位数
        
        delay1(100);
        leddat = ~0x00;
   Y0=1;Y1=1;Y2=0;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1;                  //段选3
                leddat = ~Led_dat[x/100%10];         //取出百位数
        
        delay1(100);
        leddat = ~0x00;
   Y0=1;Y1=1;Y2=1;Y3=0;Y4=1;Y5=1;Y6=1;Y7=1;                    //段选4
                 leddat = ~Led_dat[x/1000];            //取出千位数
        
        delay1(100);
        leddat = ~0x00;                       //清屏消隐
        Y0=1;Y1=1;Y2=1;Y3=1;Y4=0;Y5=1;Y6=1;Y7=1;                     //段选5
        leddat = ~Led_dat[y%10];               //取余数 取出个位数
        
        delay1(100);
        leddat = ~0x00;
        Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=0;Y6=1;Y7=1;                  //段选6
                leddat = ~Led_dat[y/10%10];         //取出十位数
        
        delay1(100);
        leddat = ~0x00;
   Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=0;Y7=1;                  //段选7
                leddat = ~Led_dat[y/100%10];         //取出百位数
        
        delay1(100);
        leddat = ~0x00;
   Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=0;                    //段选8
                 leddat = ~Led_dat[y/1000];            //取出千位数
}

void timerInit()
{

        TMOD=0x15;                 //模式设置,00000001
        TR0=1;                         //打开计数器
        ET0=1;                         //开计数器0中断
        
        TR1=1;                         //打开计数器
        ET1=1;                         //开计数器0中断
        TH1=(65536-45872)/256;         //50ms
        TL1=(65536-45872)%256;
        TH0=0;
        TL0=0;
        
        EA=1;                         //开总中断
}

uint T0_read()
{
        uchar tl,th1,th2;
        uint val;
        while(1)
        {
                th1=TH0;
                tl=TL0;
                th2=TH0;
                if(th1==th2)
                        break;
        }
        val=th1*256+tl;
        return val;
}



void main()
{
    double dat = 0;
                int dig=0;
          int i;
        int  x_speed=150;   //速度增量
        
         LSA = 0;                //138译码器 YC2输出低
        LSB = 1;
        LSC = 0;
        LSG1 = 1;
        WR = 0;                  //打开dac0830转换 WR输出低
  timerInit();
                while(1)
                {
                        dat=read(0x00);
                        dat = (dat*67)/255 + 17;    //设定的每秒转速    17~84r/s  对应 1020~5040r/min
                                
                          speed = count/en;   //当前速度
                                
                        if(speed < dat) x_speed+=1;    //如果实际速度小于设定速度 速度增量加
                        else x_speed-=1;               //反之则减
                        if(x_speed > 255)x_speed = 255;             //速度增量最大255 最小0
                        if(x_speed < 0) x_speed = 0;
                        digital =x_speed;  //电机输出速度为 设定速度加上速度增量
                        
                        i=10;
                        while(i--)
                        {
                                i--;
                         display(speed*60,dat*60);     //显示当前速度 每分钟转速  
            }
                        
                }
}

void timer_T1() interrupt 3      //定时器中断
{
        static int i = 0;               
        TH1=(65536-45872)/256;         //50ms
        TL1=(65536-45872)%256;
        i++;
    if(i>=20)         //20*50=1000ms  定时1s
                {     
                        TR0=0;                       //关闭计数器 记录脉冲数量
                        count=T0_read();
                  TH0=0;
                        TL0=0;
                        i=0;                //脉冲清零 重新开始计数
                        TR0=1;
                }

}

调速.png (278.03 KB, 下载次数: 100)

调速.png

调速.zip

115.21 KB, 下载次数: 6

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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