数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 116|回复: 3

[C51] 电机转速计 这个程序是那里的问题

[复制链接]
发表于 昨天 21:47 来自手机浏览器 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
各位大师麻烦帮忙看下这个程序是那里的问题,帮忙修改下,本人对程序是个小白这个程序是在网上找的,用来测试电机转速的,现在数码管显示正常只显示个位的0,但有霍尔转信号的时候数码管还是一直显示0,不显示转速。
#include <reg51.h>
typedef unsigned char uchar;
typedef unsigned int  uint;
typedef unsigned long ulong;

sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;

sbit sel0 = P3^2;   //千位
sbit sel1 = P3^3;   //百位
sbit sel2 = P3^4;   //十位
sbit sel3 = P3^7;   //个位
sbit HALL_IN = P3^5;

uchar code seg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
#define SEG_BLANK  0xFF
uchar disp_buf[4];

uint rpm = 0;
uint rpm_old = 0;
uint lock_cnt = 0;

//==== 切换参数(滞回防震荡)====
#define SWITCH_RPM    120
#define SWITCH_HYSTER 15
#define RPM_JUMP_LIMIT 40

//==== M/T法参数 ====
uint M_cnt;
uint T_cnt;
bit gate_flag;
bit wait_pulse;
#define GATE_MAX    750
#define TARGET_PULSE 3

//==== T法(周期测速)====
ulong t_period;
bit   t_ready;
uint  t_rpm_tmp;
uint  mt_rpm_tmp;

#define HALL_TICK    8
#define STOP_TIMEOUT 200
#define RPM_MAX      9999
#define T_PERIOD_MAX 1500

uint stop_tick = 0;
uchar stop_flag = 0;
bit hall_last = 1;
uchar hall_timer = 0;
bit tick_2ms = 0;    //2ms时标标记,定时器只置这个标志

//指数平滑滤波
uint filter_exp(uint new_val)
{
    uint out;
    out = (rpm * 7 + new_val * 3)/10;
    return out;
}

//突变限幅防抖
uint jump_limit(uint new_val)
{
    int diff;
    diff = (int)new_val - (int)rpm;
    if(diff > RPM_JUMP_LIMIT)
        return rpm + RPM_JUMP_LIMIT;
    if(diff < -RPM_JUMP_LIMIT)
        return rpm - RPM_JUMP_LIMIT;
    return new_val;
}

//【核心:滞回选择数据源】
uint select_rpm_src(uint t_val, uint mt_val)
{
    if(rpm < (SWITCH_RPM - SWITCH_HYSTER))
    {
        return t_val;
    }
    if(rpm > (SWITCH_RPM + SWITCH_HYSTER))
    {
        return mt_val;
    }
    return rpm;
}

void calc_rpm(uint t_val, uint mt_val)
{
    uint src_rpm;
    uint rpm_tmp;
    uint qian,bai,shi,ge;

    src_rpm = select_rpm_src(t_val, mt_val);
    rpm_tmp = jump_limit(src_rpm);
    rpm_tmp = filter_exp(rpm_tmp);
    rpm = rpm_tmp;

    if(rpm == rpm_old)
    {
        lock_cnt++;
        if(lock_cnt > 20) lock_cnt = 0;
    }
    else
    {
        lock_cnt = 0;
        rpm_old = rpm;
    }

    if(rpm == 0)
    {
        disp_buf[0] = SEG_BLANK;
        disp_buf[1] = SEG_BLANK;
        disp_buf[2] = SEG_BLANK;
        disp_buf[3] = 0;
    }
    else
    {
        qian = rpm / 1000;
        bai  = (rpm / 100) % 10;
        shi  = (rpm / 10) % 10;
        ge   = rpm % 10;

        disp_buf[0] = qian;
        disp_buf[1] = bai;
        disp_buf[2] = shi;
        disp_buf[3] = ge;

        if(disp_buf[0] == 0)
        {
            disp_buf[0] = SEG_BLANK;
            if(disp_buf[1] == 0)
            {
                disp_buf[1] = SEG_BLANK;
                if(disp_buf[2] == 0)
                {
                    disp_buf[2] = SEG_BLANK;
                }
            }
        }
    }
}

void Timer0_Init(void)
{
    TMOD |= 0x01;
    TH0 = 0xF8;
    TL0 = 0x30;
    ET0 = 1;
    TR0 = 1;
    EA = 1;
}

//定时器只产生2ms标志,不读霍尔!
void Timer0_ISR() interrupt 1
{
    TH0 = 0xF8;
    TL0 = 0x30;
    tick_2ms = 1;
}

void IO_Init(void)
{
    P1M1 = 0x00;
    P1M0 = 0xFF;
    P3M1 &= ~((1<<2)|(1<<3)|(1<<4)|(1<<7));
    P3M0 |=  ((1<<2)|(1<<3)|(1<<4)|(1<<7));
    P3M1 &= ~(1<<5);
    P3M0 &= ~(1<<5);
}

void disp_scan(void)
{
    static uchar scan_cnt = 0;
    sel0 = 1; sel1 = 1; sel2 = 1; sel3 = 1;
    P1 = 0x00;

    if(disp_buf[scan_cnt] != SEG_BLANK)
        P1 = seg[disp_buf[scan_cnt]];
    else
        P1 = 0x00;

    switch(scan_cnt)
    {
        case 0: sel0 = 0; break;
        case 1: sel1 = 0; break;
        case 2: sel2 = 0; break;
        case 3: sel3 = 0; break;
    }
    scan_cnt++;
    if(scan_cnt >= 4) scan_cnt = 0;
}

void main(void)
{
    stop_tick = 0;
    stop_flag = 0;
    M_cnt = 0;
    T_cnt = 0;
    gate_flag = 1;
    wait_pulse = 0;
    hall_last = 1;
    hall_timer = 0;
    rpm_old = 0;
    lock_cnt = 0;
    t_ready = 0;
    t_period = 0;
    t_rpm_tmp = 0;
    mt_rpm_tmp = 0;
    tick_2ms = 0;

    calc_rpm(0,0);
    IO_Init();
    Timer0_Init();

    while(1)
    {
        disp_scan();

        //==== 2ms时标处理(定时器标记)====
        if(tick_2ms)
        {
            tick_2ms = 0;
            stop_tick ++;

            if(t_ready == 0)
            {
                t_period++;
                if(t_period > T_PERIOD_MAX)
                {
                    t_period = 0;
                    t_ready = 0;
                }
            }

            if(gate_flag == 1)
            {
                T_cnt ++;
                if(T_cnt >= GATE_MAX && wait_pulse == 0)
                {
                    wait_pulse = 1;
                }
            }

            if(hall_timer > 0)
            {
                hall_timer--;
            }

            //停机超时归零
            if(stop_tick >= STOP_TIMEOUT)
            {
                if(stop_flag == 0)
                {
                    stop_flag = 1;
                    stop_tick = 0;
                }
                else
                {
                    stop_flag = 0;
                    stop_tick = 0;
                    M_cnt = 0;
                    T_cnt = 0;
                    wait_pulse = 0;
                    t_ready = 0;
                    t_period = 0;
                    t_rpm_tmp = 0;
                    mt_rpm_tmp = 0;
                    calc_rpm(0,0);
                }
            }
        }

        //==== 主循环轮询霍尔边沿(和测试程序一样,不漏脉冲)====
        if(hall_timer == 0)
        {
            if(hall_last == 1 && HALL_IN == 0)
            {
                stop_tick = 0;
                stop_flag = 0;

                //T法计算
                if(t_ready == 1)
                {
                    t_ready = 0;
                    if(t_period > 0)
                    {
                        t_rpm_tmp = 60000UL / (t_period * 2UL);
                        if(t_rpm_tmp > RPM_MAX) t_rpm_tmp = RPM_MAX;
                        calc_rpm(t_rpm_tmp, mt_rpm_tmp);
                    }
                    t_period = 0;
                }
                else
                {
                    t_ready = 1;
                    t_period = 0;
                }

                //M/T脉冲计数
                if(gate_flag == 1)
                {
                    M_cnt ++;
                    if((M_cnt >= TARGET_PULSE) && (wait_pulse == 0))
                    {
                        wait_pulse = 1;
                    }
                    if(wait_pulse == 1)
                    {
                        ulong temp;
                        temp = (ulong)M_cnt * 30000UL / T_cnt;
                        if(temp > RPM_MAX) temp = RPM_MAX;
                        mt_rpm_tmp = (uint)temp;
                        calc_rpm(t_rpm_tmp, mt_rpm_tmp);
                        M_cnt = 0;
                        T_cnt = 0;
                        wait_pulse = 0;
                    }
                }
                hall_timer = HALL_TICK;
            }
        }
        hall_last = HALL_IN;
    }
}
#include <reg51.h>
typedef unsigned char uchar;
typedef unsigned int  uint;
typedef unsigned long ulong;

sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;

sbit sel0 = P3^2;   //千位
sbit sel1 = P3^3;   //百位
sbit sel2 = P3^4;   //十位
sbit sel3 = P3^7;   //个位
sbit HALL_IN = P3^5;

uchar code seg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
#define SEG_BLANK  0xFF
uchar disp_buf[4];

uint rpm = 0;
uint rpm_old = 0;
uint lock_cnt = 0;

//==== 切换参数(滞回防震荡)====
#define SWITCH_RPM    120
#define SWITCH_HYSTER 15
#define RPM_JUMP_LIMIT 40

//==== M/T法参数 ====
uint M_cnt;
uint T_cnt;
bit gate_flag;
bit wait_pulse;
#define GATE_MAX    750
#define TARGET_PULSE 3

//==== T法(周期测速)====
ulong t_period;
bit   t_ready;
uint  t_rpm_tmp;
uint  mt_rpm_tmp;

#define HALL_TICK    8
#define STOP_TIMEOUT 200
#define RPM_MAX      9999
#define T_PERIOD_MAX 1500

uint stop_tick = 0;
uchar stop_flag = 0;
bit hall_last = 1;
uchar hall_timer = 0;
bit tick_2ms = 0;    //2ms时标标记,定时器只置这个标志

//指数平滑滤波
uint filter_exp(uint new_val)
{
    uint out;
    out = (rpm * 7 + new_val * 3)/10;
    return out;
}

//突变限幅防抖
uint jump_limit(uint new_val)
{
    int diff;
    diff = (int)new_val - (int)rpm;
    if(diff > RPM_JUMP_LIMIT)
        return rpm + RPM_JUMP_LIMIT;
    if(diff < -RPM_JUMP_LIMIT)
        return rpm - RPM_JUMP_LIMIT;
    return new_val;
}

//【核心:滞回选择数据源】
uint select_rpm_src(uint t_val, uint mt_val)
{
    if(rpm < (SWITCH_RPM - SWITCH_HYSTER))
    {
        return t_val;
    }
    if(rpm > (SWITCH_RPM + SWITCH_HYSTER))
    {
        return mt_val;
    }
    return rpm;
}

void calc_rpm(uint t_val, uint mt_val)
{
    uint src_rpm;
    uint rpm_tmp;
    uint qian,bai,shi,ge;

    src_rpm = select_rpm_src(t_val, mt_val);
    rpm_tmp = jump_limit(src_rpm);
    rpm_tmp = filter_exp(rpm_tmp);
    rpm = rpm_tmp;

    if(rpm == rpm_old)
    {
        lock_cnt++;
        if(lock_cnt > 20) lock_cnt = 0;
    }
    else
    {
        lock_cnt = 0;
        rpm_old = rpm;
    }

    if(rpm == 0)
    {
        disp_buf[0] = SEG_BLANK;
        disp_buf[1] = SEG_BLANK;
        disp_buf[2] = SEG_BLANK;
        disp_buf[3] = 0;
    }
    else
    {
        qian = rpm / 1000;
        bai  = (rpm / 100) % 10;
        shi  = (rpm / 10) % 10;
        ge   = rpm % 10;

        disp_buf[0] = qian;
        disp_buf[1] = bai;
        disp_buf[2] = shi;
        disp_buf[3] = ge;

        if(disp_buf[0] == 0)
        {
            disp_buf[0] = SEG_BLANK;
            if(disp_buf[1] == 0)
            {
                disp_buf[1] = SEG_BLANK;
                if(disp_buf[2] == 0)
                {
                    disp_buf[2] = SEG_BLANK;
                }
            }
        }
    }
}

void Timer0_Init(void)
{
    TMOD |= 0x01;
    TH0 = 0xF8;
    TL0 = 0x30;
    ET0 = 1;
    TR0 = 1;
    EA = 1;
}

//定时器只产生2ms标志,不读霍尔!
void Timer0_ISR() interrupt 1
{
    TH0 = 0xF8;
    TL0 = 0x30;
    tick_2ms = 1;
}

void IO_Init(void)
{
    P1M1 = 0x00;
    P1M0 = 0xFF;
    P3M1 &= ~((1<<2)|(1<<3)|(1<<4)|(1<<7));
    P3M0 |=  ((1<<2)|(1<<3)|(1<<4)|(1<<7));
    P3M1 &= ~(1<<5);
    P3M0 &= ~(1<<5);
}

void disp_scan(void)
{
    static uchar scan_cnt = 0;
    sel0 = 1; sel1 = 1; sel2 = 1; sel3 = 1;
    P1 = 0x00;

    if(disp_buf[scan_cnt] != SEG_BLANK)
        P1 = seg[disp_buf[scan_cnt]];
    else
        P1 = 0x00;

    switch(scan_cnt)
    {
        case 0: sel0 = 0; break;
        case 1: sel1 = 0; break;
        case 2: sel2 = 0; break;
        case 3: sel3 = 0; break;
    }
    scan_cnt++;
    if(scan_cnt >= 4) scan_cnt = 0;
}

void main(void)
{
    stop_tick = 0;
    stop_flag = 0;
    M_cnt = 0;
    T_cnt = 0;
    gate_flag = 1;
    wait_pulse = 0;
    hall_last = 1;
    hall_timer = 0;
    rpm_old = 0;
    lock_cnt = 0;
    t_ready = 0;
    t_period = 0;
    t_rpm_tmp = 0;
    mt_rpm_tmp = 0;
    tick_2ms = 0;

    calc_rpm(0,0);
    IO_Init();
    Timer0_Init();

    while(1)
    {
        disp_scan();

        //==== 2ms时标处理(定时器标记)====
        if(tick_2ms)
        {
            tick_2ms = 0;
            stop_tick ++;

            if(t_ready == 0)
            {
                t_period++;
                if(t_period > T_PERIOD_MAX)
                {
                    t_period = 0;
                    t_ready = 0;
                }
            }

            if(gate_flag == 1)
            {
                T_cnt ++;
                if(T_cnt >= GATE_MAX && wait_pulse == 0)
                {
                    wait_pulse = 1;
                }
            }

            if(hall_timer > 0)
            {
                hall_timer--;
            }

            //停机超时归零
            if(stop_tick >= STOP_TIMEOUT)
            {
                if(stop_flag == 0)
                {
                    stop_flag = 1;
                    stop_tick = 0;
                }
                else
                {
                    stop_flag = 0;
                    stop_tick = 0;
                    M_cnt = 0;
                    T_cnt = 0;
                    wait_pulse = 0;
                    t_ready = 0;
                    t_period = 0;
                    t_rpm_tmp = 0;
                    mt_rpm_tmp = 0;
                    calc_rpm(0,0);
                }
            }
        }

        //==== 主循环轮询霍尔边沿(和测试程序一样,不漏脉冲)====
        if(hall_timer == 0)
        {
            if(hall_last == 1 && HALL_IN == 0)
            {
                stop_tick = 0;
                stop_flag = 0;

                //T法计算
                if(t_ready == 1)
                {
                    t_ready = 0;
                    if(t_period > 0)
                    {
                        t_rpm_tmp = 60000UL / (t_period * 2UL);
                        if(t_rpm_tmp > RPM_MAX) t_rpm_tmp = RPM_MAX;
                        calc_rpm(t_rpm_tmp, mt_rpm_tmp);
                    }
                    t_period = 0;
                }
                else
                {
                    t_ready = 1;
                    t_period = 0;
                }

                //M/T脉冲计数
                if(gate_flag == 1)
                {
                    M_cnt ++;
                    if((M_cnt >= TARGET_PULSE) && (wait_pulse == 0))
                    {
                        wait_pulse = 1;
                    }
                    if(wait_pulse == 1)
                    {
                        ulong temp;
                        temp = (ulong)M_cnt * 30000UL / T_cnt;
                        if(temp > RPM_MAX) temp = RPM_MAX;
                        mt_rpm_tmp = (uint)temp;
                        calc_rpm(t_rpm_tmp, mt_rpm_tmp);
                        M_cnt = 0;
                        T_cnt = 0;
                        wait_pulse = 0;
                    }
                }
                hall_timer = HALL_TICK;
            }
        }
        hall_last = HALL_IN;
    }
}
 楼主| 发表于 昨天 21:53 来自手机浏览器 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 10 小时前 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 5 小时前 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|数码之家-技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2026-11-2 19:28 , Processed in 0.249600 second(s), 11 queries , Gzip On, Redis On.

Powered by Discuz!

© MyDigit.Net Since 2006

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