Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
11.12.2008, 07:04
|
#1
|
Почётный гражданин KAZUS.RU
Регистрация: 13.11.2008
Адрес: г.Смоленск
Сообщений: 2,018
Сказал спасибо: 348
Сказали Спасибо 1,024 раз(а) в 552 сообщении(ях)
|
RC5 transmitter
Здравствуйте, есть код, переделал его под CVAVR, но возникла проблема, в некоторых промежутках между импульсами и иногда в конце посылки (после 14 бита) порт переходит в высокое состояние, прямой ток для излучаемого ИК диода в данном случае не допустим.Помогите выловить ошибку или я попросту где то, что то не досмотрел.
Заодно и на форуме появится рабочий кусок для передачи RC5.
Код:
|
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#include ‹avr/sleep.h›
#include "rc5codes.h"
/**
* Device code to send
*/
#define RC5_DEVICE_CODE RC5_DEV_EXPERIMENTAL
/**
* Maximum bit count before transmission is finished. Minimum (as
* protocol standard says) is 64. Higher values yield a lower repetition rate.
*/
#define MAX_BITCOUNT 128
#define RC5_TEMPLATE (0x3000 | (RC5_DEVICE_CODE ‹‹ 6))
volatile uint16_t rc5data = 0;
volatile uint8_t bitcounter = MAX_BITCOUNT;
volatile uint8_t halfbitcounter;
// modulation square wave generation
// compare output mode: toggle OC0A on compare match
// if COM0Ax are *all* unset, the waveform generation is disabled and
// the normal PORTx value is seen on the OC0A pin.
#define ENABLE_MODULATION (TCCR0A |= _BV(COM0A0))
#define DISABLE_MODULATION (TCCR0A &= ~_BV(COM0A0))
// activate half bit timer
#define ENABLE_BIT_TIMER (TCCR1B |= _BV(CS10))
#define DISABLE_BIT_TIMER (TCCR1B &= ~_BV(CS10))
// button control
// MCUCR is setup by default to trigger INT0 on low level, so only external
// interrupt needs to be turned on or off
#define ENABLE_BUTTONS (GIMSK |= _BV(INT0))
#define DISABLE_BUTTONS (GIMSK &= ~_BV(INT0))
ISR(INT0_vect) {
uint8_t buttons = (~PIND) & (_BV(PD0) | _BV(PD1) | _BV(PD3) | _BV(PD4) | _BV(PD5));
uint8_t cmd = 0;
switch(buttons) {
case _BV(PD0):
cmd = RC5_CMD_VOLUME_INC;
break;
case _BV(PD1):
cmd = RC5_CMD_VOLUME_DEC;
break;
case _BV(PD3):
cmd = RC5_CMD_PROGRAM_INC;
break;
case _BV(PD4):
cmd = RC5_CMD_PROGRAM_DEC;
break;
case _BV(PD5):
cmd = RC5_CMD_STANDBY;
break;
}
// assemble rc5 packet from TEMPLATE (2 start bits and device identifier)
// and 6 command bits
rc5data = RC5_TEMPLATE | (cmd & 0x3f);
// activate timer 1 (half bit timer) to write out bitstream
bitcounter = 0;
halfbitcounter = 0;
sleep_disable();
DISABLE_BUTTONS;
ENABLE_BIT_TIMER;
}
ISR(TIMER1_COMPA_vect) {
uint8_t bit = ((rc5data & 0x2000) ›› 13);
uint8_t half = (bit ^ ((halfbitcounter == 0) ? 1 : 0));
// transmit 14 bit rc5 packet
if(half && bitcounter ‹ 14) {
ENABLE_MODULATION;
} else {
DISABLE_MODULATION;
}
if(bitcounter ›= MAX_BITCOUNT) {
// we can now prepare for the next key press
ENABLE_BUTTONS;
DISABLE_BIT_TIMER;
sleep_enable();
} else if(bitcounter == 14) {
// rc5 packet has been transmitted
DISABLE_MODULATION;
}
if(halfbitcounter == 0) {
halfbitcounter++;
} else {
halfbitcounter = 0;
bitcounter++;
rc5data ‹‹= 1; // shift left rc5 data
}
}
int main(void) {
// setup rc oscillator clock divider to div 1
// (=› 8MHz with internal RC oscollator)
CLKPR = _BV(CLKPCE); // enable clock prescale change
CLKPR = 0; // div1 =› 8 MHz
// setup waveform generation to 36kHz on timer 0
TCCR0A |= _BV(WGM01); // Clear timer on compare match
TCCR0B |= _BV(CS00); // timer source is system clock
//OCR0A = 107; // 36kHz @ 8 (7,77) MHz
// verify correct frequency! The internal oscillator is not really accurate
OCR0A = 105;
//OCR0A = 27; // 36kHz @ 1 MHz
DDRB |= _BV(PB2); // port b.2 as output
PORTB &= ~_BV(PB2); // pb2 is lo
// setup half-bit clock (555Hz) on timer1
TCCR1A = 0;
TCCR1B = _BV(WGM12); // Clear timer on compare match
// verify correct frequency! The internal oscillator is not really accurate
OCR1A = 7049; // ~ 889us @ 8MHz
TIMSK |= _BV(OCIE1A); // output compare interrupt enable 1a
// button port is input, pullup enabled
// buttons on PD0,1,3,4,5, int0 on pd2
PORTD = _BV(PD0) | _BV(PD1) | _BV(PD2) | _BV(PD3) | _BV(PD4) | _BV(PD5);
// save energy, disable analog comaprator
ACSR |= _BV(ACD);
// setup external interrupt
ENABLE_BUTTONS;
sei();
// set sleep mode to power down mode (i.e. all functions except external
// level (!) interrupts are disabled. Tiny2313 needs ~ 0.5uA then.
set_sleep_mode( _BV(SM0) | _BV(SM1) );
// enable sleep mode
sleep_enable();
for(;;) {
// sleep and wait for external interrupt (from button press)
sleep_cpu();
}
} |
Код:
|
#include ‹mega32.h›
#include ‹stdio.h›
#include ‹stdlib.h›
#include ‹delay.h›
/**
* Device code to send
*/
#define RC5_DEVICE_CODE 0x07
#define RC5_CMD_VOLUME_INC 0x11
/**
* Maximum bit count before transmission is finished. Minimum (as
* protocol standard says) is 64. Higher values yield a lower repetition rate.
*/
#define MAX_BITCOUNT 128
#define RC5_TEMPLATE (0x3000 | (RC5_DEVICE_CODE ‹‹ 6))
int rc5data = 0;
char bitcounter = MAX_BITCOUNT;
char halfbitcounter;
// modulation square wave generation
// compare output mode: toggle OC0A on compare match
// if COM0Ax are *all* unset, the waveform generation is disabled and
// the normal PORTx value is seen on the OC0A pin.
#define ENABLE_MODULATION TCCR2=0x69
#define DISABLE_MODULATION TCCR2=0x00
// activate half bit timer
#define ENABLE_BIT_TIMER TCCR1B = 0x09
#define DISABLE_BIT_TIMER TCCR1B = 0x00
// button control
// MCUCR is setup by default to trigger INT0 on low level, so only external
// interrupt needs to be turned on or off
#define ENABLE_BUTTONS GICR|=0xC0
#define DISABLE_BUTTONS GICR|=0x40
interrupt [EXT_INT1] void ext_int1_isr(void) {
char buttons = PIND.3;
char cmd = 0;
if(buttons==0) {
cmd = RC5_CMD_VOLUME_INC; // Command codes
}
// assemble rc5 packet from TEMPLATE (2 start bits and device identifier)
// and 6 command bits
rc5data = RC5_TEMPLATE | (cmd & 0x3f);
// activate timer 1 (half bit timer) to write out bitstream
bitcounter = 0;
halfbitcounter = 0;
DISABLE_BUTTONS;
ENABLE_BIT_TIMER;
}
interrupt [TIM1_COMPA] void cmpA_overflow(void) {
char bitt = ((rc5data & 0x2000) ›› 13);
char half = (bitt ^ ((halfbitcounter == 0) ? 1 : 0));
// transmit 14 bit rc5 packet
if(half && bitcounter ‹ 14) {
ENABLE_MODULATION;
} else {
DISABLE_MODULATION;
};
if(bitcounter ›= MAX_BITCOUNT) {
// we can now prepare for the next key press
ENABLE_BUTTONS;
DISABLE_BIT_TIMER;
} else if(bitcounter == 14) {
// rc5 packet has been transmitted
DISABLE_MODULATION;
PORTD.7=0;
}
if(halfbitcounter == 0) {
halfbitcounter++;
} else {
halfbitcounter = 0;
bitcounter++;
rc5data ‹‹= 1; // shift left rc5 data
}
}
void main(void) {
GICR|=0xC0;
MCUCR=0x01;
MCUCSR=0x00;
GIFR=0xC0;
TCCR2=0x00;
TCNT2=0xDE;
OCR2=0x7F;
DDRD.7=1;
PORTD.7=0;
DDRD.2=0;
DDRD.3=0;
PORTD.2=1;
PORTD.3=1;
// setup half-bit clock (555Hz) on timer1
TCCR1A = 0;
TCCR1B = 0x08; // Clear timer on compare match
OCR1A = 7049;
TIMSK = 0x11;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
ENABLE_BUTTONS;
#asm("sei")
// setup external interrupt
while (1)
{
};
} |
|
|
|
|
11.12.2008, 21:31
|
#2
|
Почётный гражданин KAZUS.RU
Регистрация: 13.11.2008
Адрес: г.Смоленск
Сообщений: 2,018
Сказал спасибо: 348
Сказали Спасибо 1,024 раз(а) в 552 сообщении(ях)
|
Что то совсем в тупике, может есть у кого кусок рабочего кода на си для передачи RC5?
|
|
|
|
11.12.2008, 21:49
|
#3
|
Временная регистрация
Регистрация: 06.12.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Какой тупик, тема уже изжевана, всем неинтересно.
http://www.telesys.ru/electronics/projects.php?do=p036
Сам на си писал когда-то.
__________________
разум когда-нибудь победит... (с)
|
|
|
|
11.12.2008, 21:52
|
#4
|
Почётный гражданин KAZUS.RU
Регистрация: 13.11.2008
Адрес: г.Смоленск
Сообщений: 2,018
Сказал спасибо: 348
Сказали Спасибо 1,024 раз(а) в 552 сообщении(ях)
|
Что то я особо там ничего не увидел, тему не раз просматривал, тут разговор идет про передачу RC5 с помощью AVR.Сколько ни искал, а тему рабочего кода для передачи никто не разжевал.
|
|
|
|
11.12.2008, 22:11
|
#5
|
Временная регистрация
Регистрация: 06.12.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Да что там жевать-то.. Бит делится на 2 части. Исключающим или первая часть слагается с 1, вторая с 0 (или наоборот ? не помню). Таким образом, при передаче однородного кода (все нули или все единицы ) получается меандр. очень удобно передавать через трансформатор, например. В то время, когда передается единица, формируется сигнал на ик диод с частотой 36 килогерц - около 4 микросекунд на выдачу, остальное на паузу.
Как вы это будете делать - через шим или программно - Ваше личное дело.
__________________
разум когда-нибудь победит... (с)
|
|
|
|
11.12.2008, 22:37
|
#6
|
Почётный гражданин KAZUS.RU
Регистрация: 13.11.2008
Адрес: г.Смоленск
Сообщений: 2,018
Сказал спасибо: 348
Сказали Спасибо 1,024 раз(а) в 552 сообщении(ях)
|
Спасибо, впринципе все понятно, приведенный выше код и делает описанные вами действия, вот проблема в том, что у меня с этим кодом небольшие проблемы, которые ну ника не могу понять почему происходят.Просто хотелось бы увидеть где может содержаться ошибка...
|
|
|
|
12.12.2008, 01:00
|
#7
|
Временная регистрация
Регистрация: 06.12.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Код:
|
иногда в конце посылки (после 14 бита) |
как-то напрашивается четное-нечетное значение последнего бита команды. Когда команда заканчивается на 1, последний полубит в 0 и тогда все нормально, а когда в 0, то остается 1 и торчит, ничем не сбрасывается. Я бы здесь копал. А если совсем честно, то переписал бы сам функцию. Это было бы быстрее.
__________________
разум когда-нибудь победит... (с)
|
|
|
|
12.12.2008, 01:38
|
#8
|
Почётный гражданин KAZUS.RU
Регистрация: 13.11.2008
Адрес: г.Смоленск
Сообщений: 2,018
Сказал спасибо: 348
Сказали Спасибо 1,024 раз(а) в 552 сообщении(ях)
|
Спасибо, сейчас этим и занимаюсь,пишу код.Мысли по поводу того,что вы сказали, появлялись, но видно как то мимо их пустил, будем разбираться.
|
|
|
|
12.12.2008, 02:15
|
#9
|
Временная регистрация
Регистрация: 11.06.2006
Сообщений: 60
Сказал спасибо: 17
Сказали Спасибо 6 раз(а) в 4 сообщении(ях)
|
Можно так
Код:
|
#define TIME_P 1.778
#define TIME_TLOW TIME_P/2
#define P_1 PORTB=1
#define P_0 PORTB=0
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14
const uint8_t komand[][14]=
{{ 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1},
{ 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1},
{ 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1},
{ 1 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1},
{ 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0},
{ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1},
{ 1 , 1 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 1 , 1}};
for(uint8_t i=0; i‹14; i++){
if (komand[j][i]==1)
{
P_1;
_delay_ms(TIME_TLOW);
P_0;
_delay_ms(TIME_TLOW);
}else{
P_0;
_delay_ms(TIME_TLOW);
P_1;
_delay_ms(TIME_TLOW);
}
} |
Добавлено:
Извиняйте! пропустил что надо 36л генирировать.
|
|
|
|
12.12.2008, 02:20
|
#10
|
Почётный гражданин KAZUS.RU
Регистрация: 13.11.2008
Адрес: г.Смоленск
Сообщений: 2,018
Сказал спасибо: 348
Сказали Спасибо 1,024 раз(а) в 552 сообщении(ях)
|
Спасибо за код, но на delay нерационально получается.
Этот код я видел, вроде где то в форуме видел ссылку на сайт где вы и код декодера привели.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 21:53.
|
|