lnjzbraveheart 发表于 2025-6-7 18:23:46

AI8h8k64u进行测距问题?

使用8h单片机(开天斧)连接超声模块进行测距,只测了一下,然后就当机了,无论怎么移动超声模块都是第一次测距结果。把这个代码一点也不改动,刷到stc89c52上,可以正常测距,改变距离立刻有显示。请大家帮忙分析一下,可能哪里出了问题?

DebugLab 发表于 2025-6-7 22:33:42

IO模式和运行速度有区别
新手必读:
https://www.stcaimcu.com/thread-16535-1-1.html

lnjzbraveheart 发表于 2025-6-8 08:46:56

请大家帮忙看下,是代码有什么问题吗?

此代码在STC89C52下运行完全正常,但是用开天斧时,只测了一次就卡住不动了,不知什么原因?

请高手赐教!

#include <stc8H.H>
#include <math.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

bit flag=0;

sbit DIO = P6^5;                //HC595串行数据口               
sbit RCLK= P6^6;                               
sbit SCLK = P6^7;
                               
sbit LED2=P2^0;                //指示灯

sbit Trig=P2^4;
sbit Echo=P2^5;

unsigned char code DSP[] =
{// 0       1          2           3        4       5          6           7        8       9          A           b        C    d          E    F    -
        0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf,
        0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10
// 0.   1.   2.   3.   4.   5.   6.   7.   8.   9.
};

uchar LED={4,3,2,1};                           //显示缓存区

void Delay10us(void)        //@12.000MHz
{
        unsigned char data i;
        _nop_();
        _nop_();
        i = 30;
        while (--i);
}

float measure()
{   uint time = 0;
    float distance=0.0;
   
    // 发送10us高电平触发信号
    Trig = 1;
    Delay10us();
    Trig = 0;
   
    // 等待回波信号变高
    while(!Echo);
    // 开始计时
    TR1=1;
    while(Echo & !TF1);
    // 停止计时
        TR1=0;
    if(TF1){
          distance=0;
      TF1=0;
        }
        else{
          // 计算时间(us)
          time = TH1<<8|TL1;          
          // 计算距离(cm) 声速340m/s=0.034cm/us
          distance = time * 0.017; // 往返时间/2
    }
        TH1 = 0;
        TL1 = 0;
    return distance;
}

void Timer0_Init(void)                //1毫秒@11.0592MHz
{
        AUXR &= 0x7F;                        //定时器时钟12T模式
        TMOD &= 0xF0;                        //设置定时器模式
        TL0 = 0x66;                                //设置定时初始值
        TH0 = 0xFC;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
        EA = 1;
}


void Snoic_Init(){
        AUXR &= 0xBF;                        //定时器时钟12T模式
        TMOD &= 0x0F;                        //设置定时器模式
        TMOD |= 0x10;                        //设置定时器模式
        TL1 = 0;                                //设置定时初始值
        TH1 = 0;                                //设置定时初始值
        TF1 = 0;                                //清除TF1标志
}


void LED_OUT(unsigned char X)
{
        unsigned char i;
        for(i=8;i>=1;i--)
        {
                X<<=1;
                DIO=CY;       
                SCLK = 0;
                SCLK = 1;
        }
}


void Display()
{
        uchar i;
        for(i=0;i<4;i++){
          LED_OUT(DSP]);                       
          LED_OUT(pow(2,i));               
              RCLK = 0;
          RCLK = 1;
        }
}


void main (void)
{
        int dist;
    P0M0 = 0x00; P0M1 = 0x00;
    P1M0 = 0x00; P1M1 = 0x00;
    P2M0 = 0x10; P2M1 = 0x20;
    P3M0 = 0x00; P3M1 = 0x00;
    P4M0 = 0x00; P4M1 = 0x00;
    P5M0 = 0x00; P5M1 = 0x00;
    P6M0 = 0x00; P6M1 = 0x00;
    P7M0 = 0x00; P7M1 = 0x00;

        Timer0_Init();
        Snoic_Init();
        while(1)
        {
       if(flag)   //每50毫秒测距一次
          {
          flag=0;
                dist =(int)(measure()*10);
          
               LED=dist/1000;
               LED=dist%1000/100;
               LED=dist%100/10+17;
               LED=dist%10;
               LED2=~LED2;               //LED2
          }       
        }
}

void Timer0_Isr(void) interrupt 1
{
        static uchar k;
        k++;
        if(k%3==0){             
          Display();       //3毫秒刷新显示
        }
        if(k%50==0)               //50毫秒测距一次
          flag=1;
        k%=150;
}

lnjzbraveheart 发表于 2025-6-8 08:47:34

DebugLab 发表于 2025-6-7 22:33
IO模式和运行速度有区别
新手必读:
https://www.stcaimcu.com/thread-16535-1-1.html

请帮忙看下代码,这里有什么潜在的问题吗?

lnjzbraveheart 发表于 2025-6-8 13:05:03

这个问题困扰了很长时间,今天终于解决了,主要原因是在定时器0的中断里调用了显示子函数Display(),是他造成的当机。我把这个子程序放在主循环里就好了。但是不知道为什么在STC89C52中,即使在中断中调用了显示子函数仍能正确执行程序!请大家伙帮忙看看是什么具体原因!

DebugLab 发表于 7 天前

lnjzbraveheart 发表于 2025-6-8 13:05
这个问题困扰了很长时间,今天终于解决了,主要原因是在定时器0的中断里调用了显示子函数Display(),是他造 ...

可能是有意外的进位操作CY被修改了,具体需要查看生成的汇编代码
以下是之前写的语音播报超声波测距程序供参考
#include <STC8.H>
#include <intrins.h>
#define         TRIG        P30
#define         ECHO        P31
#define         BUSY        P32
#define                DATA        P33
#define                RST                P54
#define                KEY                P55
#define                BANDGAP        1188UL

//                1                2                3                4                5                6                7                8
//                无                一                二                三                四                五                六                七

//                9                10                11                12                13                14                15                16
//                八                九                十                百                点                当前        设置        距离

//                17                18                19                20                21                22                23                24
//                电压        电流        水位        温度        重量        单价        总价        厘米

//                25                26                27                28                29                30                31                32
//                米                伏                安                度                千克        元                零                滴

bit Error;
unsigned int Distance,Voltage;
unsigned char Lenth,Play_Pointer,Buff_Pointer;
unsigned char Number={31,2,3,4,5,6,7,8,9,10};
unsigned char Buff;
unsigned int Integer,Decimal;

/*----------------------------延时10us@STC-Y6@6MHz----------------------------*/
void Delay_10us(void)
{
        unsigned char i;
        i=18;
        while(--i);
}

/*----------------------------延时x10us----------------------------*/
void Delay_x10us(unsigned char x)
{
        while(x--)
                Delay_10us();
}

void Send(unsigned char x)
{
        unsigned char i;
        RST=1;
        Delay_x10us(10);
        RST=0;
        Delay_x10us(10);
        for(i=0;i<x;i++)
        {
                DATA=1;
                Delay_x10us(10);
                DATA=0;
                Delay_x10us(10);
        }
        Delay_x10us(10);
}

void Speak_Function(unsigned char x)
{
        Buff=x;
        Buff_Pointer++;
}

void Speak_Number(unsigned char x)
{
        unsigned char integer_2,integer_1,integer_0,decimal_1,decimal_2,decimal_3;
        integer_2=(unsigned char)(Integer%1000/100);
        integer_1=(unsigned char)(Integer%100/10);
        integer_0=(unsigned char)(Integer%10);
        decimal_1=(unsigned char)(Decimal%1000/100);
        decimal_2=(unsigned char)(Decimal%100/10);
        decimal_3=(unsigned char)(Decimal%10);
        if(integer_2>0)
        {
                Speak_Function(Number);
                Speak_Function(12);
                if(integer_1==0)
                {
                        if(integer_0!=0)
                        {
                                Speak_Function(Number);
                        }
                }
                else
                {
                        Speak_Function(Number);
                }
        }
        else
        {
                if(integer_1>1)
                {
                        Speak_Function(Number);
                }
        }
        if(integer_1>0)
        {
                Speak_Function(11);
        }
        if(integer_0==0)
        {
                if(integer_2==0&&integer_1==0)
                {
                        Speak_Function(Number);
                }
        }
        else
        {
                Speak_Function(Number);
        }
        switch(x)
        {
                case 1:
                        Speak_Function(13);
                        Speak_Function(Number);
                break;
                case 2:
                        Speak_Function(13);
                        Speak_Function(Number);
                        Speak_Function(Number);
                break;
                case 3:
                        Speak_Function(13);
                        Speak_Function(Number);
                        Speak_Function(Number);
                        Speak_Function(Number);
                break;
                default:
                break;
        }
}

void Speak(void)
{
        if(BUSY&&Lenth>0)
        {
                Send(Buff);
                Play_Pointer++;
                if(Play_Pointer==Lenth)
                {
                        Play_Pointer=0;
                        Lenth=0;
                }
        }
}

void Speak_Distance(unsigned int temp)
{
        Buff_Pointer=0;
        Integer=temp/10;
        Decimal=temp%10*100;
        Speak_Function(32);
        Speak_Function(14);
        Speak_Function(16);
        Speak_Number(1);
        Speak_Function(24);
        Lenth=Buff_Pointer;
}

void Speak_Voltage(unsigned int temp)
{
        Buff_Pointer=0;
        Integer=temp/1000;
        Decimal=temp%1000;
        Speak_Function(32);
        Speak_Function(14);
        Speak_Function(17);
        Speak_Number(3);
        Speak_Function(26);
        Lenth=Buff_Pointer;
}

void Trig(void)
{
        TRIG=1;
        Delay_x10us(100);
        TRIG=0;
}

void Init(void)
{
        AUXR&=0x7F;                //设置定时器0时钟12T模式
        TMOD=0x08;                //设置定时器模式:定时器0受INT0控制,16位自动重载模式
        TF0=0;                        //清除定时器0中断标志
        TH0=0;                        //初始化定时器0
        TL0=0;                        //初始化定时器0
        ET0=1;                        //打开定时器0中断
        EA=1;                        //打开总中断
        P3M0=0x00;                //初始化GPIO模式
        P3M1=0x00;                //初始化GPIO模式
        P5M0=0x00;                //初始化GPIO模式
        P5M1=0x00;                //初始化GPIO模式
        DATA=0;                        //初始化GPIO
        RST=0;                        //初始化GPIO
        TRIG=0;                        //初始化GPIO
        Integer=0;                //初始化变量
        Decimal=0;                //初始化变量
        Error=0;                //初始化变量
        ADCCFG=ADC_RESFMT;                //设置ADC转换结果右对齐,设置ADC时钟
        ADC_CONTR=ADC_POWER|15;        //使能ADC
        Delay_x10us(100);
        ADC_CONTR|=ADC_START;        //启动ADC
        while(!(ADC_CONTR&ADC_FLAG));
        Voltage=ADC_RES<<8|ADC_RESL;
        Voltage=BANDGAP*1024UL/Voltage;
        Speak_Voltage(Voltage);
        ADC_CONTR=0x00;
}

void main(void)
{
        Init();
        while(1)
        {
                if(!KEY&&!Lenth)
                {
                        Error=0;
                        TH0=0;
                        TL0=0;
                        Trig();
                        while(!ECHO);
                        TR0=1;
                        while(ECHO);
                        TR0=0;
                        if(Error)
                                Distance=0;
                        else
                        {
                                Distance=TH0;
                                Distance<<=8;
                                Distance|=TL0;
                                Distance*=0.34645;
                        }
                        Speak_Distance(Distance);
                }
                Speak();
        }
}

void Timer0_ISR(void) interrupt 1
{
        TR0=0;
        TH0=0;
        TL0=0;
        Error=1;
}超声波测距受温度影响,加入温度补偿更精确
excel超声波测距计算:




页: [1]
查看完整版本: AI8h8k64u进行测距问题?