找回密码
 立即注册

QQ登录

只需一步,快速开始

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

写完的单片机实验程序和例程的烧录现象不符,找不出问题

[复制链接]
跳转到指定楼层
楼主
ID:995884 发表于 2021-12-22 21:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
开发板是普中的89C52开发板,学到步进电机的控制这一节,然后要实现的功能是按下KEY1,电机反转方向;按下KEY2,电机加速;按下KEY3,电机减速。实际烧录后出现的问题:
1.是电机只有两档速度可以调,但写代码时是要5档可调的,中间几档好像丢了?
2.如果最后的延时函数换成while(ten_us--),上电后电机不转,只有按下按键才转,但是使用for语句嵌套的延时函数,上电后电机却可以正常转

我已经对着例程和自己的代码研究好久了,没找到问题出在哪儿,往大神赐教


以下为学习时写的单片机代码
#include<reg52.h>
typedef unsigned char uchar;
typedef unsigned int  uint;

/*-------------步进电机控制端口定义------------*/
sbit IN1_D=P1^0;
sbit IN2_C=P1^1;
sbit IN3_B=P1^2;
sbit IN4_A=P1^3;

/*----------------按键控制端口定义-------------*/
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;

/*----------------按键返回值宏定义-------------*/
#define KEY1_PRESS     1
#define KEY2_PRESS     2
#define KEY3_PRESS     3
#define KEY4_PRESS     4
#define KEY_UNPRESS    0

/*----------宏定义步进电机最大最小速度---------*/
#define STEPMOTOR_MAX_SPEED  1
#define STEPMOTOR_MIN_SPEED  5



/*------------------延时函数-------------------*/
void delay_10us(uint ten_us)
{
        while(ten_us--);
}

/*------------------延时函数-------------------*/
void delay_ms(uint ms)
{
        uint i,j;
        for(i=ms;i>0;i--)
                for(j=110;j>0;j--);
}

/*-----------------按键扫描函数-----------------*/
uchar key_scan(uchar mode)
{
        static uchar key=1;
        
        if(mode)key=1;
        if(key=1&&(KEY1==0|KEY2==0|KEY3==0|KEY4==0))
        {
                delay_10us(1000);
                key=0;
                if(KEY1==0)
                        return KEY1_PRESS;
                else if(KEY2==0)
                        return KEY2_PRESS;
                else if(KEY3==0)
                        return KEY3_PRESS;
                else if(KEY4==0)
                        return KEY4_PRESS;
        }
        else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
        {
                key=1;
        }
        return KEY_UNPRESS;
}

/*------------------五线四相步进电机转动控制----------------*/
void step_motor_28BYJ48_send_pulse(uchar step,uchar dir)
{
        uchar temp=step;
        
        if(dir==0)
                temp=7-step;               
        switch(temp)
        {
                case 0:IN4_A=0;IN3_B=0;IN2_C=0;IN1_D=1;break;
                case 1:IN4_A=0;IN3_B=0;IN2_C=1;IN1_D=1;break;
                case 2:IN4_A=0;IN3_B=0;IN2_C=1;IN1_D=0;break;
                case 3:IN4_A=0;IN3_B=1;IN2_C=1;IN1_D=0;break;
                case 4:IN4_A=0;IN3_B=1;IN2_C=0;IN1_D=0;break;
                case 5:IN4_A=1;IN3_B=1;IN2_C=0;IN1_D=0;break;
                case 6:IN4_A=1;IN3_B=0;IN2_C=0;IN1_D=0;break;
                case 7:IN4_A=1;IN3_B=0;IN2_C=0;IN1_D=1;break;
                default:IN4_A=0;IN3_B=0;IN2_C=0;IN1_D=0;break;
        }
}

void main()
{
        uchar key=0;
        uchar dir=1;
        uchar speed=STEPMOTOR_MAX_SPEED;
        uchar step=0;
        
        while(1)
        {
                key=key_scan(0);            //key_scan为按键扫描函数
                if(key==KEY1_PRESS)
                {
                        dir=!dir;               //改变电机旋转方向
                }
                else if(key==KEY2_PRESS)
                {
                        if(speed>STEPMOTOR_MAX_SPEED)  //电机旋转速度加速
                                speed-=1;
                }
                else if(key==KEY3_PRESS)
                {
                        if(speed<STEPMOTOR_MIN_SPEED)  //电机旋转速度减速
                                speed+=1;
                }
               
                step_motor_28BYJ48_send_pulse(step++,dir); //步进电机控制函数
                if(step==8)step=0;                         //重置step为0使步进电机控制函数从第一节拍开始
                delay_10us(speed);                                   //通过控制这个延迟函数控制电机旋转速度
        }

}



然后例程是这样的
#include "reg52.h"

typedef unsigned int u16;        //对系统默认数据类型进行重定义
typedef unsigned char u8;

//定义ULN2003控制步进电机管脚
sbit IN1_A=P1^0;
sbit IN2_B=P1^1;
sbit IN3_C=P1^2;
sbit IN4_D=P1^3;

//定义独立按键控制脚
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;

//使用宏定义独立按键按下的键值
#define KEY1_PRESS        1
#define KEY2_PRESS        2
#define KEY3_PRESS        3
#define KEY4_PRESS        4
#define KEY_UNPRESS        0

// 定义步进电机速度,值越小,速度越快
// 最小不能小于1
#define STEPMOTOR_MAXSPEED        1  
#define STEPMOTOR_MINSPEED        5         


/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能                 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出             : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
        while(ten_us--);        
}

/*******************************************************************************
* 函 数 名       : delay_ms
* 函数功能                 : ms延时函数,ms=1时,大约延时1ms
* 输    入       : ten_us
* 输    出             : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
        u16 i,j;
        for(i=ms;i>0;i--)
                for(j=110;j>0;j--);
}

/*******************************************************************************
* 函 数 名       : step_motor_28BYJ48_send_pulse
* 函数功能                 : 输出一个数据给ULN2003从而实现向步进电机发送一个脉冲
* 输    入       : step:指定步进序号,可选值0~7
                                   dir:方向选择,1:顺时针,0:逆时针
* 输    出             : 无
*******************************************************************************/
void step_motor_28BYJ48_send_pulse(u8 step,u8 dir)
{
        u8 temp=step;
        
        if(dir==0)        //如果为逆时针旋转
                temp=7-step;//调换节拍信号
        switch(temp)//8个节拍控制:A->AB->B->BC->C->CD->D->DA
        {
                case 0: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=0;break;
                case 1: IN1_A=1;IN2_B=1;IN3_C=0;IN4_D=0;break;
                case 2: IN1_A=0;IN2_B=1;IN3_C=0;IN4_D=0;break;
                case 3: IN1_A=0;IN2_B=1;IN3_C=1;IN4_D=0;break;
                case 4: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=0;break;
                case 5: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=1;break;
                case 6: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=1;break;
                case 7: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=1;break;
                default: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=0;break;//停止相序        
        }                        
}

/*******************************************************************************
* 函 数 名       : key_scan
* 函数功能                 : 检测独立按键是否按下,按下则返回对应键值
* 输    入       : mode=0:单次扫描按键
                                   mode=1:连续扫描按键
* 输    出             : KEY1_PRESS:K1按下
                                   KEY2_PRESS:K2按下
                                   KEY3_PRESS:K3按下
                                   KEY4_PRESS:K4按下
                                   KEY_UNPRESS:未有按键按下
*******************************************************************************/
u8 key_scan(u8 mode)
{
        static u8 key=1;

        if(mode)key=1;//连续扫描按键
        if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下
        {
                delay_10us(1000);//消抖
                key=0;
                if(KEY1==0)
                        return KEY1_PRESS;
                else if(KEY2==0)
                        return KEY2_PRESS;
                else if(KEY3==0)
                        return KEY3_PRESS;
                else if(KEY4==0)
                        return KEY4_PRESS;        
        }
        else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)        //无按键按下
        {
                key=1;                        
        }
        return KEY_UNPRESS;               
}

/*******************************************************************************
* 函 数 名       : main
* 函数功能                 : 主函数
* 输    入       : 无
* 输    出             : 无
*******************************************************************************/
void main()
{        
        u8 key=0;
        u8 dir=0;//默认逆时针方向
        u8 speed=STEPMOTOR_MAXSPEED;//默认最大速度旋转
        u8 step=0;

        while(1)
        {                        
                key=key_scan(0);
                if(key==KEY1_PRESS)//换向
                {
                        dir=!dir;   
                }
                else if(key==KEY2_PRESS)//加速
                {
                        if(speed>STEPMOTOR_MAXSPEED)
                                speed-=1;                        
                }
                else if(key==KEY3_PRESS)//减速
                {
                        if(speed<STEPMOTOR_MINSPEED)
                                speed+=1;                        
                }
                step_motor_28BYJ48_send_pulse(step++,dir);
                if(step==8)step=0;               
                delay_ms(speed);                                                
        }               
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:624769 发表于 2021-12-23 15:32 | 只看该作者
        if(mode)key=1;
       if(key=1&&(KEY1==0|KEY2==0|KEY3==0|KEY4==0))
        {
                delay_10us(1000);

  ////////////////////////////////////////  那么多符号,居然用对的和用错的能对半分……, 实在是佩服至极,

        if((key==1)&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))
  

回复

使用道具 举报

板凳
ID:995884 发表于 2021-12-26 20:50 | 只看该作者
188610329 发表于 2021-12-23 15:32
if(mode)key=1;
        if(key=1&&(KEY1==0|KEY2==0|KEY3==0|KEY4==0))
        {

多谢多谢
初学者,找了好几个小时也是在别人提醒下才发现这里判断写成了赋值了
回复

使用道具 举报

地板
ID:995884 发表于 2021-12-26 20:55 | 只看该作者
188610329 发表于 2021-12-23 15:32
if(mode)key=1;
        if(key=1&&(KEY1==0|KEY2==0|KEY3==0|KEY4==0))
        {

再请教一下,为什么这段代码,最后的延时函数用delay_10us这种while(ten_us--)的方式步进电机它不转,用for语句嵌套的才转呢
回复

使用道具 举报

5#
ID:514901 发表于 2021-12-27 09:08 | 只看该作者
1、按键扫描应该加上消抖和松手检测,否则你按一下,单片就判定你按了几十下。
2、步进电机不转的原因很可能是步与步之间延时时间太短
回复

使用道具 举报

6#
ID:990881 发表于 2021-12-27 11:25 | 只看该作者
医用棉签 发表于 2021-12-26 20:55
再请教一下,为什么这段代码,最后的延时函数用delay_10us这种while(ten_us--)的方式步进电机它不转,用 ...

延时太短了,你写的延时10微秒*speed,例程是1毫秒*speed,延时10毫秒可以按键消抖
回复

使用道具 举报

7#
ID:995884 发表于 2022-2-28 22:38 | 只看该作者
东方木青龙 发表于 2021-12-27 11:25
延时太短了,你写的延时10微秒*speed,例程是1毫秒*speed,延时10毫秒可以按键消抖

哦哦,普中这个坑爹教程

视频教程里他可不是这么写的……
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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