Ща напишу общий модуль arduino
Вид для печати
Ща напишу общий модуль arduino
Ругается компилятор на
using namespace IO;
А почему считаем, пока нога в верхнем положении? Мне кажется более правильным считать пока не будет перепада с единицы на ноль. Ведь бит кодируется так: сначала низкий уровень, потом высокий. Обе половинки одинаковые по продолжительности (в теории). Но это половинки одного бита.
Короткий по продолжительности - значит единица. Длинный - ноль.
Всю работу с UART можешь заменить на стандартную Serial.<чего-то>Код:#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint16_t WaveLength;
volatile uint16_t CalcedWaveLength;
#define TCNT2_Const (256-2)
#define UART_BAUD_RATE 115200
#define UART_DOUBLESPEED
#ifdef UART_DOUBLESPEED
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 4UL)) / ((uint32_t)(baudRate) * 8UL) - 1)
#else
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 8UL)) / ((uint32_t)(baudRate) * 16UL) - 1)
#endif
#define UART_TXREADY UDRE0
#define UART_RXREADY RXC0
#define UART_DOUBLE U2X0
#define UDR UDR0
#define UCRA UCSR0A
#define UCRB UCSR0B
#define UCRC UCSR0C
#define UCRC_VALUE ((1<<UCSZ01) | (1<<UCSZ00))
#define RXCIE RXCIE0
#define TXCIE TXCIE0
#define RXEN RXEN0
#define TXEN TXEN0
#define UBRRL UBRR0L
#define UBRRH UBRR0H
#define SIG_UART_TRANS SIG_USART_TRANS
#define SIG_UART_RECV SIG_USART_RECV
#define SIG_UART_DATA SIG_USART_DATA
#define UART_STATUS UCSR0A
void UART_Init(void)
{
UBRRH = (UART_CALC_BAUDRATE(UART_BAUD_RATE)>>8) & 0xFF;
UBRRL = (UART_CALC_BAUDRATE(UART_BAUD_RATE) & 0xFF);
#ifdef UART_DOUBLESPEED
UART_STATUS = ( 1<<UART_DOUBLE );
#endif
UCRB = ((1<<TXEN) | (1<<RXEN));
UCRC = UCRC_VALUE;
}
void UART_SendByte(uint8_t data)
{
while (!(UCRA & (1<<UART_TXREADY)));
UDR = data;
}
void setup(void)
{
TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));// Режим работы таймера/счетчика
TCCR2B &= ~(1<<WGM22);// Режим работы таймера/счетчика
TCCR2B |= (1<<CS20)|(1<<CS21); //(1<<CS21)|(1<<CS20)|(1<<CS22); //установка предделителя 32
ASSR &= ~(1<<AS2); //Выбор источника синхронизации таймера если AS2=0 от системного генератора
TCNT2 = TCNT2_Const; // 16000000/256/100/64=8 tcnt2=256-8=248.
TIMSK2 |= (1<<TOIE2);//Разрешение прерывания по переполнению Т2.
WaveLength=0;
CalcedWaveLength=0;
sei();
UART_Init();
}
void loop (void)
{
for (;CalcedWaveLength==0;);
uint16_t cwl=CalcedWaveLength;
CalcedWaveLength=0;
UART_SendByte(cwl&255);
UART_SendByte(cwl>>8);
}
SIGNAL(TIMER2_OVF_vect)
{
TCNT2=TCNT2_Const;
uint16_t WL=WaveLength;
if ( PIND|(1<<2)!=0)
WL++;
else
{
if (WL!=0)
{
CalcedWaveLength=WL;
WL=0;
}
}
WaveLength=WL;
}
Единственное - слать надо бинарные данные, а не в текстовом виде.
Да - все равно что считать. Сейчас условие, что счет надо проводить описано
if ( PIND|(1<<2)!=0)
это означает, что нога DIGITAL2 находится в верхнем положении.
Вот эти команды что делают?
UART_SendByte(cwl&255);
UART_SendByte(cwl>>8);
Вообще если нужно считать только длительности 50-65 мкс и 95-130 мкс, то спокойно можно таймер поставить на каждые 16 мкс и при длительности импульса 3-4 вызова таймера считать, что пришел 0, при длительности 5-8 - считать, что пришла 1. Если пришло что угодно другое - считать, что пришел мусор.
Шлют в serial последовательно младшую и старшую части счетчика.
UPD:
Тут изменил счетчик на вызов каждые 16 мкс.Код:#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t WaveLength;
volatile uint8_t CalcedWaveLength;
#define TCNT2_Const (256-8)
#define UART_BAUD_RATE 115200
#define UART_DOUBLESPEED
#ifdef UART_DOUBLESPEED
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 4UL)) / ((uint32_t)(baudRate) * 8UL) - 1)
#else
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 8UL)) / ((uint32_t)(baudRate) * 16UL) - 1)
#endif
#define UART_TXREADY UDRE0
#define UART_RXREADY RXC0
#define UART_DOUBLE U2X0
#define UDR UDR0
#define UCRA UCSR0A
#define UCRB UCSR0B
#define UCRC UCSR0C
#define UCRC_VALUE ((1<<UCSZ01) | (1<<UCSZ00))
#define RXCIE RXCIE0
#define TXCIE TXCIE0
#define RXEN RXEN0
#define TXEN TXEN0
#define UBRRL UBRR0L
#define UBRRH UBRR0H
#define SIG_UART_TRANS SIG_USART_TRANS
#define SIG_UART_RECV SIG_USART_RECV
#define SIG_UART_DATA SIG_USART_DATA
#define UART_STATUS UCSR0A
void UART_Init(void)
{
UBRRH = (UART_CALC_BAUDRATE(UART_BAUD_RATE)>>8) & 0xFF;
UBRRL = (UART_CALC_BAUDRATE(UART_BAUD_RATE) & 0xFF);
#ifdef UART_DOUBLESPEED
UART_STATUS = ( 1<<UART_DOUBLE );
#endif
UCRB = ((1<<TXEN) | (1<<RXEN));
UCRC = UCRC_VALUE;
}
void UART_SendByte(uint8_t data)
{
while (!(UCRA & (1<<UART_TXREADY)));
UDR = data;
}
void setup(void)
{
TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));// Режим работы таймера/счетчика
TCCR2B &= ~(1<<WGM22);// Режим работы таймера/счетчика
TCCR2B |= (1<<CS20)|(1<<CS21); //(1<<CS21)|(1<<CS20)|(1<<CS22); //установка предделителя 32
ASSR &= ~(1<<AS2); //Выбор источника синхронизации таймера если AS2=0 от системного генератора
TCNT2 = TCNT2_Const; // 16000000/256/100/64=8 tcnt2=256-8=248.
TIMSK2 |= (1<<TOIE2);//Разрешение прерывания по переполнению Т2.
WaveLength=0;
CalcedWaveLength=0;
sei();
UART_Init();
}
void loop (void)
{
for (;CalcedWaveLength==0;);
uint8_t cwl=CalcedWaveLength;
CalcedWaveLength=0;
if ((cwl>2)&&(cwl<5))
UART_SendByte('0');
else
if ((cwl>=5)&& (cwl<8))
UART_SendByte('1');
else
UART_SendByte('?');
}
SIGNAL(TIMER2_OVF_vect)
{
TCNT2=TCNT2_Const;
uint8_t WL=WaveLength;
if ( PIND|(1<<2)!=0)
WL++;
else
{
if (WL!=0)
{
CalcedWaveLength=WL;
WL=0;
}
}
WaveLength=WL;
}
Считается интервал между таймерами так:
32 такта (это заложено в инициализации)*8 (эта восьмерка участвует в TCNT2_Const).
Итого каждые 256 тактов.
Контроллер делает 16 млн. тактов в секунду. Итого - раз в 16 микросекунд.
Кроме этого сделал посылку разных значков в зависимости от длительности которую посчитал таймер.
Я окончательно запутался. Сорри.
В дебри лезть уже не буду, пройду по поверхности:
void loop (void)
{
for (;CalcedWaveLength==0;);
uint16_t cwl=CalcedWaveLength;
CalcedWaveLength=0;
UART_SendByte(cwl&255);
UART_SendByte(cwl>>8);
}
вот основной цикл программы.
for (;CalcedWaveLength==0;);
здесь мы чего ждем? пока не получим из таймера длительность высокого уровня?
uint16_t cwl=CalcedWaveLength;
что будет в cwl? зачем конвертить порядок бит?
CalcedWaveLength=0;
обнулили и ждем следующее значение?
Сорри. Все сделал, но не работает.