AI8h8k64u进行测距问题?
使用8h单片机(开天斧)连接超声模块进行测距,只测了一下,然后就当机了,无论怎么移动超声模块都是第一次测距结果。把这个代码一点也不改动,刷到stc89c52上,可以正常测距,改变距离立刻有显示。请大家帮忙分析一下,可能哪里出了问题? IO模式和运行速度有区别新手必读:
https://www.stcaimcu.com/thread-16535-1-1.html 请大家帮忙看下,是代码有什么问题吗?
此代码在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;
} DebugLab 发表于 2025-6-7 22:33
IO模式和运行速度有区别
新手必读:
https://www.stcaimcu.com/thread-16535-1-1.html
请帮忙看下代码,这里有什么潜在的问题吗? 这个问题困扰了很长时间,今天终于解决了,主要原因是在定时器0的中断里调用了显示子函数Display(),是他造成的当机。我把这个子程序放在主循环里就好了。但是不知道为什么在STC89C52中,即使在中断中调用了显示子函数仍能正确执行程序!请大家伙帮忙看看是什么具体原因! 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]