Страница 1 из 1
Грабли с граббером сигнала на Atmega8
Добавлено: Пн июн 02, 2014 17:13:49
alexparser
Доброго дня!
Есть линия по которой передается цифровой сигнал (данные в HEX), логическая 1 первые 3/4 периода +5V, вторые 1/4 0V. Период составляет 1/4 ms.
Имею тестовый код, который должен вести подсчет возрастающих фронтов.
Проблема в том, что код не успевает корректно считать.
Вместо 10 фронтов на выходе получаю 1.
Камень Atmega8A бегает на 16 мегагерц (фьюзы выставлены правильно, питание +5V).
Вывод результата в UART делаю по таймеру раз в ~2 сек.
Вопрос - почему код не успевает обрабатывать фронты?
Код: Выделить всё
for(;;){
while ((PINB & (1<<0))==0); // ждем передний фронт
while (PINB & (1<<0)); // ждем задний фронт
frontCount++;
}
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Пн июн 02, 2014 18:23:30
ИС-пытатель
А расскажите, пожалуйста, в цикле for у Вас какое условие выполнения или выхода?
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Пн июн 02, 2014 18:30:05
alexparser
ИС-пытатель писал(а):А расскажите, пожалуйста, в цикле for у Вас какое условие выполнения или выхода?
Нет условия для выхода, как видно из кода это вечный цикл.
Вывод результата в UART делаю по таймеру раз в ~2 сек. и после вывода обнуляю счетчик.
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Пн июн 02, 2014 19:55:58
ИС-пытатель
А если вечный цикл так обозначить:
Это решит проблему?
Покажите весь код, плиз! )
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Пн июн 02, 2014 21:57:43
uk8amk
Задача может быть решена аппаратно:
один таймер в режиме внешнего тактирования, другой для измерения временных интервалов.
Касательно вашей программы - косяк где-то в том коде, который вы не показываете.
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Вт июн 03, 2014 00:05:20
alexparser
uk8amk писал(а):Касательно вашей программы - косяк где-то в том коде, который вы не показываете.
Выкладываю код, он конечно далек от идеала, но явного косяка я не нахожу.
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#define SPEED 9600
volatile unsigned int front_cnt = 0;
void serial_init(unsigned int bittimer)
{
// set baud rate
UBRRH = (unsigned char) (bittimer >> 8);
UBRRL = (unsigned char) bittimer;
// set the framing to 8N1
UCSRC = (1 << URSEL) | (1 << USBS) | (3 << UCSZ0);
// enable transmitter
UCSRB = (1 << TXEN);
return;
}
void serial_write(unsigned char c)
{
while ( !(UCSRA & (1 << UDRE)) );
UDR = c;
return;
}
void serial_write_str(char *s)
{
for(unsigned int i=0; i<strlen(s); i++)
{
serial_write(s[i]);
}
return;
}
void send_timer_reset(unsigned int val)
{
char s[50];
sprintf(&s,"front counts: %u \r\n", front_cnt);
serial_write_str(&s[0]);
return;
}
ISR(TIMER1_OVF_vect)
{
send_timer_reset(0);
front_cnt = 0;
return;
}
void timer_init(void)
{
TCCR1B = (1<<CS12) | (0<<CS11) | (1<<CS10); // divider
TIMSK = (1<<TOIE1); // interrupt if overload
TCNT1 = 0; // start value
sei();
return;
}
void io_init(void)
{
// input pin
DDRB &=!_BV(0);
PORTB&=!_BV(0);
return;
}
// *******************************************************************************
// main
// *******************************************************************************
int main(void)
{
io_init();
serial_init( F_CPU/16/SPEED-1 );
timer_init();
while(1)
{
while ((PINB & (1<<0))==0); // ждем передний фронт
while (PINB & (1<<0)); // ждем задний фронт
front_cnt++;
TCNT1 = 0;
}
return 0;
}
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Вт июн 03, 2014 00:25:08
uk8amk
Код: Выделить всё
while(1)
{
while ((PINB & (1<<0))==0); // ждем передний фронт
while (PINB & (1<<0)); // ждем задний фронт
front_cnt++;
TCNT1 = 0; <<<<<<<<--- вот это зачем?
}
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Вт июн 03, 2014 00:32:31
ИС-пытатель
И еще косяк:
Код: Выделить всё
void io_init(void)
{
// input pin
DDRB &=!_BV(0);
PORTB&=!_BV(0);
return;
}
Не совсем так. Это вот так обозначается:
Код: Выделить всё
void io_init(void)
{
// input pin
DDRB &=~_BV(0);
PORTB&=~_BV(0);
return;
}
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Вт июн 03, 2014 01:13:49
alexparser
uk8amk писал(а):Код: Выделить всё
while(1)
{
TCNT1 = 0; <<<<<<<<--- вот это зачем?
}
Чтобы во время приема сигнала не сработал таймер, обнуляем его.
Код: Выделить всё
void io_init(void)
{
// input pin
DDRB &=~_BV(0);
PORTB&=~_BV(0);
return;
}
Подправил этот кусок кода, но оно никак не повлияло.
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Вт июн 03, 2014 08:14:19
ИС-пытатель
А это и не должно было повлиять.
Сторожевой таймер отключите.
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Вт июн 03, 2014 09:13:34
uk8amk
Таймер и не сработает если у вас интервал между посылками короткий.
Тактирование=16MHz/1024=15625Hz
Переполнение=15625/65536=0.23Гц => 4.3 сек
Не многовато ли?
На всякий случай уберите обнуление таймера в цикле. Убедитесь что хоть как-то оно считает.
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Вт июн 03, 2014 09:59:34
ИС-пытатель
У него по идее таймер должен сработать через 4 секунды после прихода последнего импульса и отправить количество импульсов
Re: Грабли с граббером сигнала на Atmega8
Добавлено: Чт июн 05, 2014 23:54:48
alexparser
Привет братья по разуму!
Был в командировке

, вернулся и пересмотрел все свежим взглядом и о эврика обнаружились грабли, те на которые я так долго наступал, но в упор не видел.
Короче, трабла крылась не в софтверной а в хардверной части.
Перед ногой МК стоял медленный диод.

Re: Грабли с граббером сигнала на Atmega8
Добавлено: Пт июн 06, 2014 08:09:54
Zhevagin
Настолько медленный, что даже импульс длительностью в несколько миллисекунд не открывал его? Может там падение напряжения на диоде сказывалось?