Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Расчет таймера для RC5
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
den_sad
Нужна помошь, никак не могу понять как добиться частоты 38килогерц на выходе.. вот листинг программы
Использую Мега8 на кварце 7.3728Мгц
CODE

/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7a Professional
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date : 23.05.2011
Author : F4CG
Company : F4CG
Comments:


Chip type : ATmega8
Program type : Application
Clock frequency : 8,000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*****************************************************/

#include <mega8.h>
// Standard Input/Output functions
#include <stdio.h>
#include <delay.h>


#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Receiver buffer
#define RX_BUFFER_SIZE 22

#define PulseON TCCR1B=0x40;TCCR1A=0x05
#define PulseOFF TCCR1B=0;TCCR1A=0
//*************************************************************************

char VOL_UP[6] = {0x50,0x04,0x68,0x32,0x11,0x1F}; // 50 04 68 32 11 1F
char VOL_DN[6] = {0x50,0x04,0x68,0x32,0x10,0x1E};
//char SEEK_UP[6] = {0x50,0x04,0x68,0x3B,0x21,0x26};

char RAD_CDC[5] = {0x68,0x03,0x18,0x01,0x72}; //Ты включен?
//char RAD_CDC_play[7] = {0x68,0x05,0x18,0x38,0x00,0x00,0x4D}; //Ты играешь? 680518380000
char RAD_CDC_play[7] = {0x68,0x05,0x18,0x38,0x01,0x00,0x4C}; //Ты играешь? 68 05 18 38 01 00 4C стоп воспр

char CDC_RAD[6] = {0x18,0x04,0x68,0x02,0x00, 0x76}; //Ответ drk.xty
char CDC_STAT[12] = {0x18,0x0A,0x68,0x39,0x02,0x09,0x00,0x3F,0x00,0x01,0x01,0x77}; //Статус я играю

//39 00 09 00 3F 00 dd tt
//*************************************************************************
int RxRecieveEnable;
int RxCnt;
int RxPacketSize;

int ParseEnable;
char RxBuff[20];
char ch;
int ledON;


// IR JVC
// int start = 320;
// int pause = 160;
// int togle=20;
// END IR JVC
int JVC_VOLUP[16]={1,0,0,0,1,1,1,1,1,0,0,0,0,1,0,0};
// Vol+ 10001111 10000100


void SendHI(void)
{
ledON=1;
delay_us(400); //********** Здесь задержка должны быть 526vrc но почему то при delay_us(526) задержка по осцилографу больше

ledON=0;
delay_us(1200);
}
void SendLOW(void)
{
ledON=1;
delay_us(400);

ledON=0;
delay_us(400);
}

void SendStart(void)
{
ledON=1;
delay_us(6400); //********** Здесь задержка должны быть8.4 мс но почему то при delay_ms(8.4) задержка по осцилографу около 12-14 мс


ledON=0;
delay_us(3200);



}


void SendJVC_volUP(void)
{

int i;
SendStart();
for (i=0;i<16; i++) {
if (JVC_VOLUP[i]==0) {SendLOW();}
else {SendHI();}
}


// This flag is set on USART Receiver buffer overflow


// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{


ch = UDR;
if((ch == 0x68 | ch == 0x50 | ch ==0x18) & (RxRecieveEnable == 0))
{
RxRecieveEnable = 1;
RxCnt = 0;
RxPacketSize = 0;
RxBuff[0] = ch;
}
else if(RxRecieveEnable==1)
{


if(RxCnt==0)
{


if((ch & 0x80) == 0)
{
RxPacketSize = ch;
RxBuff[1] = RxPacketSize;
RxCnt++;
}
}
else if(RxCnt>0) //
{


RxBuff[RxCnt+1] = ch;
RxCnt++;
if(RxCnt > RxPacketSize) //
{

RxRecieveEnable = 0;
RxCnt = 0;
RxPacketSize = 0;
ParseEnable = 1; //????? ?????????? ???????? ?????

}
}


}



}



// Write a character to the USART Transmitter
#ifndef _DEBUG_TERMINAL_IO_
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar(char c)
{
while ((UCSRA & DATA_REGISTER_EMPTY)==0);
UDR=c;
}
#pragma used-
#endif



int AnalizeMFL(void)
{
int n;
int razmer;
int volup=0; //?? ??????? ??????????
int voldn=0;

razmer=RxBuff[1]+2;
for (n=0;n<razmer;n++) //??????????? ??????????? ?????
{

if (RxBuff[n]==VOL_UP[n]) //50 04 68 32 11 1F

{
volup=volup+1;
}


if (RxBuff[n]==VOL_DN[n]) //50 04 68 32 10 1E
{
voldn=voldn+1;
}


}


if (volup==razmer)
{
SendJVC_volUP();
// послать команду громкость +
}
if (voldn==razmer)
{
// PORTD.6=!PIND.6;
// послать команду громкость -
}
return n;

}

int AnalizeRAD(void)
{
int n;
int razmer;
int ROLL=0;
int STAT=0;

razmer=RxBuff[1]+2;
for (n=0;n<razmer;n++) //
{

if (RxBuff[n]==RAD_CDC[n]) //{0x68,0x03,0x18,0x01,0x72}; ты включен?

{
ROLL=ROLL+1;
}

if (RxBuff[n]==RAD_CDC_play[n]) //; что ты играешь? {0x68,0x05,0x18,0x38,0x00,0x00,0x4D};

{
STAT=STAT+1;
}



}
n=0;

if (ROLL==razmer) // я включен
{

for (n=0;n<6;n++)
{
putchar(CDC_RAD[n]); //0x18,0x04,0x68,0x02,0x00, 0x76
}
}


if (STAT==razmer) // я играю
{

for (n=0;n<12;n++)
{
putchar(CDC_STAT[n]); // {0x18,0x0A,0x68,0x39,0x02,0x09,0x00,0x3F,0x00,0x01,0x01,0x77}; //Статус
}
}
return n;

}


// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
// Place your code here
TCNT1H=0;
TCNT1L=0;
{PORTD.6=!PIND.6;} //надо чтобы на PD6 была частота 38 килогерц

if (ledON==1)
{PORTD.7=!PIND.7;}
else {PORTD.7=0;}

}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P
PORTB=0xFF;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=P State5=P State4=P State3=P State2=P State1=P State0=P
PORTC=0x7F;
DDRC=0x00;

/// Port D initialization
// Func7=Out Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=0 State6=0 State5=P State4=P State3=P State2=P State1=P State0=P
PORTD=0x3F;
DDRD=0xC0;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 921,600 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x02;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00; ////////////// что надо указать чтобы получить на PD6 была частоту 38 килогерц??
OCR1AH=0x00;
OCR1AL=0x0C;
OCR1BH=0x00;
OCR1BL=0x00;


// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;

TIMSK=0x10;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, Even Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x98;
UCSRC=0xA6;
UBRRH=0x00;
UBRRL=0x2F;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Global enable interrupts
#asm("sei")
ledON=0;

while (1)
{


//**********************************************************************
SendJVC_volUP();
delay_ms(500);

if (ParseEnable==1)
{


switch (RxBuff[0]) {
case 0x68:
{ ParseEnable=0; AnalizeRAD();}

break;

case 0x50:
{
ParseEnable=0; AnalizeMFL();}
break;

case 0x18:
{
ParseEnable=0; }
break;



};


ParseEnable=0;

}




}; //while
}


красным отметил интересующие меня куски кода.. в Итоге 2 вопроса, почему delay.h дает не те задержки что я указываю и как добиться 38 килогерц для модуляции
algidim
Обычно такие вещи таймером, но в режиме PWM, тогда Вам не придется дергать ногу проца… Да вообще, если чтото не понимаете начните с простого именно сформирования 38 кгц, а то смотрю уже какие то прерывания на uart понавешали….
den_sad
Цитата(algidim @ May 30 2011, 14:00) *
Обычно такие вещи таймером, но в режиме PWM, тогда Вам не придется дергать ногу проца… Да вообще, если чтото не понимаете начните с простого именно сформирования 38 кгц, а то смотрю уже какие то прерывания на uart понавешали….

с прерываниями все в порядке - это прием / передача команд по i-bus BMW

Суть проекта управление штатными кнопками не штатной магнитолой эмулируя ее пульт ДУ..
Палыч
Цитата(den_sad @ May 30 2011, 14:45) *
почему delay.h дает не те задержки что я указываю

Несоответствие частот:
Цитата(den_sad @ May 30 2011, 14:45) *
Использую Мега8 на кварце 7.3728Мгц
Код
Clock frequency     : 8,000000 MHz



Цитата(den_sad @ May 30 2011, 14:45) *
как добиться 38 килогерц для модуляции

Для этого желательно использовать выходы таймера OC1A, OC1B или OC2. Как настроить - в DS есть информация и с диаграммами для понимания работы
den_sad
Цитата(Палыч @ May 30 2011, 14:15) *
Несоответствие частот:




Для этого желательно использовать выходы таймера OC1A, OC1B или OC2. Как настроить - в DS есть информация и с диаграммами для понимания работы


возможно, вот только отличия с тем коэфициэнтом как 8\7.3728
Читал, нихрена не понял, прошу рабочие куски кода выделеные красным ,мозг уже взрывается
Палыч
Цитата(den_sad @ May 30 2011, 15:20) *
возможно, вот только отличия с тем коэфициэнтом как 8\7.3728
Сравните частоту Вашего кварца и частоту, установленную в проекте (Menu->Project->Configure->C Compiler->Code Generation->Clock)
den_sad
Цитата(Палыч @ May 30 2011, 14:56) *
Сравните частоту Вашего кварца и частоту, установленную в проекте (Menu->Project->Configure->C Compiler->Clock)

Все ок, но меня больше волнует какие параметры прописать в таймер чтобы генерить 38 килогерц, delay для меня на данном этапе не критично
Палыч
Цитата(den_sad @ May 30 2011, 15:59) *
чтобы генерить 38 килогерц
В начале определитесь: каким методом вы будете генерить эту частоту. Можно, конечно, как это сделано сейчас у Вас - программно, но, гораздо удобнее - аппаратно, для этого используются выходы таймера ОСх.
VladislavS
Для того чтобы получить 38 кГц на PD6 с помощью вот такой процедуры обработки прерываний
Код
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
   PORTD.6=!PIND.6;  
}

Надо настроить таймер, чтобы он делил на 97. Тогда частота на PD6 будет 7372800/97/2 = 38,004 кГц. Таймер настроить так:
Код
  TCCR1A = 0;
  TCCR1B = (1<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10);
  OCR1AH = 0;
  OCR1AL = 97;
  TIMSK = (1<<OCIE1A);


Больше ничего не трогать и курить даташит. Не такой уж он большой и страшный, чтобы не утруждать себя его прочтением.
den_sad
Цитата(VladislavS @ May 30 2011, 18:42) *


Спасибо! Попробую

OCR1AL = 97; Это вроде как надо указывать в HEX коде? А то в DEC равно 151 Или я опять что то путаю...
314
путаете. hex - префикс 0x61 binary - префикс 0b01100001, десятичный без префикса 97. Дальше забота компилятора.
Палыч
Цитата(VladislavS @ May 30 2011, 19:42) *
Надо настроить таймер, чтобы он делил на 97. Тогда частота на PD6 будет 7372800/97/2 = 38,004 кГц. Таймер настроить так
Маленькое замечание: чтобы таймер "делил на 97" в регистр OCR1AL необходимо записать число 96 (см. формулу в DS в пункте "Clear Timer on Compare Match (CTC) Mode").
den_sad
Цитата(314 @ May 31 2011, 23:06) *
путаете. hex - префикс 0x61 binary - префикс 0b01100001, десятичный без префикса 97. Дальше забота компилятора.


Понял.. видать в этом у меня и была ошибка, спасибо!
VladislavS
Цитата(Палыч @ Jun 1 2011, 09:01) *
в регистр OCR1AL необходимо записать число 96

Да, конечно, извиняюсь за дезу sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.