找回密码
 立即注册

QQ登录

只需一步,快速开始

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

PWM控制电机转速 为什么我的程序控制不了?

[复制链接]
跳转到指定楼层
楼主
ID:1167562 发表于 2026-3-9 21:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg52.h>
sbit onn=P1^0;
sbit seet=P1^1;
sbit addd=P1^2;
sbit subb=P1^3;
sbit gass=P1^4;
sbit breakk=P1^5;
sbit IN1=P1^6;
sbit IN2=P1^7;
sbit ENA=P2^0;

//占空比,最大占空比
unsigned char ZKB,high=0,on=0,set=0,add=0,sub=0,sc=0,duty_zkb=0,ZKBB=0,cnt=0;


void Motor_Auto_add();
void Time0_Init(void);
void key_process(unsigned char key_num);
void key_scan();

void Time0_Init(void)
{
        TMOD=0X01;
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        EA=ET0=1;
        TR0=1;
}

void main()
{        IN1=1;
        IN2=0;
        Motor_Auto_add();
        Time0_Init();
        //key_process(unsigned char key_num);
        while(1)
        {               
               
                key_scan();
               
        }
}


//按键扫描
void key_scan()
{
        int i=0;
        //开始建,自增速
        if(onn==0)
                for(i=0;i<200;i++);
                if(onn==0)
                {
                        on=1;//开始标志
                        while(onn==1);
                }
        if(seet==0)
                for(i=0;i<200;i++);
                if(seet==0)
                {
                        set=1;//巡航开始标志
                        duty_zkb=high;//将当前占空比保留
                        while(seet==1);
                }
        if(addd==0)
                for(i=0;i<200;i++);
                if(addd==0)
                {
                        add=1;//加速键标志位
                        while(addd==1);
                }
        if(subb==0)
                for(i=0;i<200;i++);
                if(subb==0)
                {
                        sub=1;//减速标志位
                        while(subb==1);
                }
}

//终端按键扫描执行程序
void key_process(unsigned char key_num)
{
        switch(key_num)
        {
                case 1:
                        high=0;
                        set=0;
                        break;
                case 2:
                        high=0;
                        set=0;
                        break;
                default:
                        break;
        }
}

//电机调速
void Motor_Auto_add()
{
        if(on==1)
        {
                high++;
                high%=100;
        }
        //else
        //{
        //ZKB=0;
        //}
        
        if(set==1)
        {
                high=duty_zkb;
        }
        else if(set==0)
        {high=0;}
        
        if(set==1&&add==1)
        {
                high=high+1;
                if(high==100)
                add=0;
        }
        if(set==1&&sub==1)
        {
                high=high-1;
                if(high<0)
                sub=0;
        }
}



//中断优先
void int0_srv() interrupt 0
{int i=0;
        for(i=0;i<200;i++);
                if(breakk==0)
                {
                        key_process(1);
                        while(breakk==1);
                }
                else if(gass==0)
                {
                        key_process(2);
                        while(gass==1);
                }
}

void time0_srv() interrupt 1
{
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        cnt++;
        cnt%=100;
        if(cnt<high)
        {
                ENA=1;
        }
        else
        {
                ENA=0;
        }
}

我想实现按键控制电机转速,当按键按下时可以保持当前车速,再有按键按下时实现加速或者减速,为什么我的程序控制不了啊????
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:844772 发表于 2026-3-10 09:54 | 只看该作者
错太多了,直说一个吧,将Motor_Auto_add()放入主循环中调用。另外,你调速逻辑不对,但好歹放进去能略微抖动一下。
回复

使用道具 举报

板凳
ID:584814 发表于 2026-3-10 11:00 | 只看该作者
二楼言简意该。可以AI找方案。
回复

使用道具 举报

地板
ID:1074206 发表于 2026-3-10 12:33 来自触屏版 | 只看该作者
把程序copy给ai,然后提问,你会发现新大陆
回复

使用道具 举报

5#
ID:1167562 发表于 2026-3-11 15:46 | 只看该作者
参考各位的意见了,让AI查问题改正后,还是无法实现速度保持。
PWM速度保持到底怎么实现啊?

这是改正后的程序
#include <reg52.h>
sbit onn=P1^0;
sbit seet=P1^1;
sbit addd=P1^2;
sbit subb=P1^3;
sbit gass=P1^4;
sbit breakk=P1^5;
sbit IN1=P1^6;
sbit IN2=P1^7;
sbit ENA=P2^0;

//占空比,最大占空比
unsigned char ZKB,on=0,set=0,add=0,sub=0,duty_zkb=0,cnt=0;
unsigned char high=0;
unsigned int j=0;

void Motor_Auto_add();
void Time0_Init(void);
void key_process(unsigned char key_num);
void key_scan();
void Int0_Init(void);
       
void Int0_Init(void)
{
        IT0=1;//下降沿触发
        EX0=1;// 使能外部中断0
        EA=1;// 开总中断
}
void Time0_Init(void)
{
        TMOD=0X01;//定时器0工作模式1(16位定时器)
        TH0=(65536-1000)/256;// 1ms定时初值(12MHz晶振)
        TL0=(65536-1000)%256;
        ET0=1;   // 使能定时器0中断
        TR0=1;// 启动定时器0
}

void main()
{        IN1=1;// 电机正转方向
        IN2=0;
       
        Int0_Init();//初始化外部中断0
        Time0_Init();//初始化定时器0

        while(1)
        {               
               
                key_scan();
                Motor_Auto_add();// 电机调速逻辑
        }
}


//按键扫描
void key_scan()
{
unsigned int i=0;
        //开始建,自增速
        if(onn==0)
        {
                for(i=0;i<200;i++);
                if(onn==0)
                {
                        on=!on;//开始标志
                        while(onn==0);
                }
        }
        if(seet==0)
        {
                for(i=0;i<200;i++);
                if(seet==0)
                {
                        set=!set;//巡航开始标志
                        if(set)
                        {duty_zkb=high;//将当前占空比保留
                        }

                        while(seet==0);
                }
        }
        if(addd==0)
        {
                for(i=0;i<200;i++);
                if(addd==0)
                {
                        add=1;//加速键标志位
                        while(addd==0);
                }
        }
        if(subb==0)
        {for(i=0;i<200;i++);
                if(subb==0)
                {
                        sub=1;//减速标志位
                        while(subb==0);
                }
        }
}

//终端按键扫描执行程序
void key_process(unsigned char key_num)
{
        switch(key_num)                //电机停转
        {
                case 1:
                        high=0;
                        duty_zkb=0;
                        set=0;
                        on=0;
                        IN1=1;
                        IN2=1;
                        break;
                case 2:
                       
                        on=1;
                        break;
                default:
                        break;
        }
}

//电机调速
void Motor_Auto_add()
{
        if(on==1 && !set)
        {
                j++;
                if(j>=50)//每50ms增加1%占空比
                {
                                j=0;
                                if(high<100)
                                high++;
                }
        }
       
       
        if(on==1 && set==1)
        {
               
                high=duty_zkb;
                //巡航加速
                if(add==1)
                {
                        if(duty_zkb<100)
                                duty_zkb++;
                        add=0;//清除标志位
                }
                if(sub==1)
                {
                        if(duty_zkb>0)
                                duty_zkb--;
                        sub=0;
                }
        }

       
        //未启动,占空比清零
        if(on==0)
        {
                high=0;
                j=0;
        }
}



//中断优先(刹车/油门)
void int0_srv() interrupt 0
{int i=0;
        for(i=0;i<200;i++);
                if(breakk==0)
                {
                        key_process(1);
                        while(breakk==0);
                }
                else if(gass==0)
                {
                        key_process(2);
                        while(gass==0);
                }
}

//定时器中断生成PWM
void time0_srv() interrupt 1
{
        TH0=(65536-1000)/256;
        TL0=(65536-1000)%256;
        cnt++;
        cnt%=100;
        if(cnt<high)
        {
                ENA=1;
        }
        else
        {
                ENA=0;
        }
}


回复

使用道具 举报

6#
ID:857072 发表于 2026-3-11 20:47 来自触屏版 | 只看该作者
我用AI帮你问了一下。#include <reg52.h>  // 引脚定义 sbit onn = P1^0;     // 启动/停止 sbit seet = P1^1;    // 巡航/保持 sbit addd = P1^2;    // 加速 sbit subb = P1^3;    // 减速 sbit gass = P1^4;    // 油门(备用) sbit breakk = P1^5;  // 紧急刹车 sbit IN1 = P1^6;     // 电机方向1 sbit IN2 = P1^7;     // 电机方向2 sbit ENA = P2^0;     // PWM 输出  // 全局变量 unsigned char high = 0;        // 当前占空比 (0-100) unsigned char duty_zkb = 0;    // 巡航保存的基准速度 bit on = 0;                    // 运行标志 (1=运行, 0=停止) bit set = 0;                   // 巡航标志 (1=巡航, 0=非巡航) bit add = 0;                   // 加速标志 (1=等待处理) bit sub = 0;                   // 减速标志 (1=等待处理) unsigned int j = 0;            // 自动增速计时器  // 函数声明 void Time0_Init(void); void key_scan(void); void Motor_Auto_add(void); void int0_srv(void) interrupt 0;  void Time0_Init(void) {     TMOD = 0x01;                 // 定时器0工作模式1 (16位定时器)     TH0 = (65536 - 1000) / 256;  // 1ms定时初值 (12MHz晶振)     TL0 = (65536 - 1000) % 256;     ET0 = 1;                     // 使能定时器0中断     TR0 = 1;                     // 启动定时器0 }  void main() {     IN1 = 1;  // 电机正转     IN2 = 0;          Time0_Init();  // 初始化定时器          while (1) {         key_scan();     // 按键扫描         Motor_Auto_add(); // 电机调速     } }  // 按键扫描 (带消抖) void key_scan() {     unsigned int i;          // 启动/停止键 (onn)     if (onn == 0) {         for (i = 0; i < 200; i++);  // 消抖         if (onn == 0) {             on = !on;  // 切换运行状态             while (onn == 0);  // 等待按键释放         }     }          // 巡航键 (seet)     if (seet == 0) {         for (i = 0; i < 200; i++);         if (seet == 0) {             set = !set;  // 切换巡航模式             if (set) duty_zkb = high;  // 保存当前速度             while (seet == 0);         }     }          // 加速键 (addd) - 按下一次只触发一次     if (addd == 0) {         for (i = 0; i < 200; i++);         if (addd == 0) {             add = 1;  // 标记加速             while (addd == 0);         }     }          // 减速键 (subb) - 按下一次只触发一次     if (subb == 0) {         for (i = 0; i < 200; i++);         if (subb == 0) {             sub = 1;  // 标记减速             while (subb == 0);         }     } }  // 电机调速核心逻辑 (关键修正) void Motor_Auto_add() {     // 巡航模式下:先处理加速/减速,再更新速度     if (set) {         // 1. 处理加速 (修改基准速度)         if (add) {             if (duty_zkb < 100) duty_zkb++;             add = 0;  // 立即清零标志位         }         // 2. 处理减速 (修改基准速度)         if (sub) {             if (duty_zkb > 0) duty_zkb--;             sub = 0;  // 立即清零标志位         }         // 3. 将当前速度更新为最新基准         high = duty_zkb;     }     // 非巡航模式:速度由按键控制 (无自动增速)     else {         if (on) {             // 速度保持为0,直到按下加速键             // (原自动增速逻辑已移除,避免失控)         } else {             high = 0;  // 未运行时速度清零         }     } }  // 外部中断0 (紧急刹车/油门) void int0_srv() interrupt 0 {     if (breakk == 0) {  // 紧急刹车         on = 0;         set = 0;         high = 0;         duty_zkb = 0;         while (breakk == 0);  // 等待释放     }     else if (gass == 0) {  // 油门启动         on = 1;         while (gass == 0);     } }  // 定时器0中断 (PWM生成) void time0_srv() interrupt 1 {     TH0 = (65536 - 1000) / 256;  // 1ms定时     TL0 = (65536 - 1000) % 256;     static unsigned char cnt = 0;     cnt++;     if (cnt >= 100) cnt = 0;  // 100ms周期 (100Hz PWM)          if (cnt < high) {         ENA = 1;  // 占空比内输出高     } else {         ENA = 0;  // 占空比外输出低     } }
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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