与 AVR 连接的超声波传感器
Ultrasonic sensor interfacing with AVR
我正在处理它的一个项目部分,用超声波传感器进行一些读取并通过串行通信发送它,我写了代码,它给出了随机读取,有时给出 0 作为读取,这是我使用的公式为了找到正确的距离!?,或者还有另一个公式,我正在使用带有内部 8MHz 时钟的 Atmega32,有人可以帮助我并知道我的代码有什么问题吗!?。
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
void inti_serial();
static volatile int pulse = 0;
static volatile int change = 0;
int main(void)
{
/* Replace with your application code */
inti_serial();
MCUCR |= (1 << ISC00); //Any logical change on INT0
GICR |= (1 << INT0); //Enable INT0
TCCR1A=0;
sei();
while (1)
{
PORTC |= (1<<0);
_delay_us(15);
PORTC &= ~(1<<0);
while(!(UCSRA & (1<<UDRE)));
UDR = ((pulse/2)*1*(1/F_CPU)*343) ;
_delay_ms(100);
}
}
ISR(INT0_vect){
if (change==1)//when logic from HIGH to LOW
{
TCCR1B=0;//disabling counter
pulse=TCNT1;//count memory is updated to integer
TCNT1=0;//resetting the counter memory
change=0;
}
if (change==0)//when logic change from LOW to HIGH
{
TCCR1B|=(1<<CS10);//enabling counter
change=1;
}
}
void inti_serial()
{
UCSRB |= (1<<TXEN);
UCSRC |= (1<<UCSZ0) | (1<<UCSZ1) | (1<<URSEL);
UBRRL = 0x33;
}
我看到了一些可以改进您开发的选项:
你正在从 ISR 中写入一个样本到变量,你从主循环中连续读取它并输出它。相反,您应该只输出一次新样本(使串行数据更小,更容易专注于实际内容和样本时间)
在考虑正确的公式之前,您应该验证您的抽样机制是否正确。没有关于您的传感器的详细信息,无论如何这里没有人可以判断您的公式。
您可以使用处理器的输入捕获电路,而不是对免费的 运行 计数器进行采样(更准确,由于中断延迟引起的抖动更少)
无需将计数器寄存器重置为零,您可以将两个连续的样本相互减去(由于中断延迟导致的样本抖动较少)
不是从切换标志中推导出边沿,而是向硬件询问引脚的状态或哪个边沿触发了中断(或捕获)
我正在处理它的一个项目部分,用超声波传感器进行一些读取并通过串行通信发送它,我写了代码,它给出了随机读取,有时给出 0 作为读取,这是我使用的公式为了找到正确的距离!?,或者还有另一个公式,我正在使用带有内部 8MHz 时钟的 Atmega32,有人可以帮助我并知道我的代码有什么问题吗!?。
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
void inti_serial();
static volatile int pulse = 0;
static volatile int change = 0;
int main(void)
{
/* Replace with your application code */
inti_serial();
MCUCR |= (1 << ISC00); //Any logical change on INT0
GICR |= (1 << INT0); //Enable INT0
TCCR1A=0;
sei();
while (1)
{
PORTC |= (1<<0);
_delay_us(15);
PORTC &= ~(1<<0);
while(!(UCSRA & (1<<UDRE)));
UDR = ((pulse/2)*1*(1/F_CPU)*343) ;
_delay_ms(100);
}
}
ISR(INT0_vect){
if (change==1)//when logic from HIGH to LOW
{
TCCR1B=0;//disabling counter
pulse=TCNT1;//count memory is updated to integer
TCNT1=0;//resetting the counter memory
change=0;
}
if (change==0)//when logic change from LOW to HIGH
{
TCCR1B|=(1<<CS10);//enabling counter
change=1;
}
}
void inti_serial()
{
UCSRB |= (1<<TXEN);
UCSRC |= (1<<UCSZ0) | (1<<UCSZ1) | (1<<URSEL);
UBRRL = 0x33;
}
我看到了一些可以改进您开发的选项:
你正在从 ISR 中写入一个样本到变量,你从主循环中连续读取它并输出它。相反,您应该只输出一次新样本(使串行数据更小,更容易专注于实际内容和样本时间)
在考虑正确的公式之前,您应该验证您的抽样机制是否正确。没有关于您的传感器的详细信息,无论如何这里没有人可以判断您的公式。
您可以使用处理器的输入捕获电路,而不是对免费的 运行 计数器进行采样(更准确,由于中断延迟引起的抖动更少)
无需将计数器寄存器重置为零,您可以将两个连续的样本相互减去(由于中断延迟导致的样本抖动较少)
不是从切换标志中推导出边沿,而是向硬件询问引脚的状态或哪个边沿触发了中断(或捕获)