Ща напишу общий модуль 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 микросекунд.
Кроме этого сделал посылку разных значков в зависимости от длительности которую посчитал таймер.
Последний раз редактировалось SBorovkov; 26.01.2011 в 04:11.
Я окончательно запутался. Сорри.
В дебри лезть уже не буду, пройду по поверхности:
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;
обнулили и ждем следующее значение?
Сорри. Все сделал, но не работает.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)