Технический форум по робототехнике.
Lockdog » 14 июл 2010, 23:37
Есть МК ATtiny2313, настроил таймеры в режим СТС, чтобы тактированние шло либо на ножку PB3, либо PB4, в зависимости от того, какой из входов PD0 или PA1 замкнут на "землю", так же в зависимости от того какая из кнопок на ножках PA0, PD2 нажата, то частота либо понижается, либо повышается.
Но это нифига не работает, прошу помощи.
- Код: Выделить всё • Развернуть
#include <ioavr.h>
#include <intrinsics.h>
int freq[] = {1132, 132, 66, 43, 32, 26, 21, 18, 16, 14, 12};
int i = 0;
void init_timer1_r(void)
{
TCCR1A = 0x00;
TCCR1B = 0x00;
TCCR1A |= (1<<COM1A0); //Режим CTC
TCCR1B = (1<<WGM12)|(1<<CS10);
OCR1A=freq[i];
}
void init_timer1_l(void)
{
TCCR1A = 0x00;
TCCR1B = 0x00;
TCCR1A |= (1<<COM1B0); //Режим CTC
TCCR1B = (1<<WGM12)|(1<<CS10);
OCR1B=freq[i];
}
void timer1_stop(void)
{
OCR1A=0;
OCR1B=0;
__delay_cycles(8000000);
}
//#pragma vector=TIMER1_COMPA_vect
int main( void )
{
DDRD = 0x00;
DDRA = 0x00;
PORTA = 0xFF;
PORTD = 0xFF;
DDRB = 0xFF;
PORTB = 0xFF;
//init_timer1_r();
__enable_interrupt();
while(1)
{
PORTB &= ~(1<<PB2);
if ((PINA & (1<<PA1)) == 0) init_timer1_r();
if ((PIND & (1<<PD1)) == 0) timer1_stop();
if ((PIND & (1<<PD0)) == 0) init_timer1_l();
if ((PINA & (1<<PA0)) == 0)
{
if (i != 10)
{
i++;
OCR1A = freq[i];
OCR1B = freq[i];
}
}
if ((PIND & (1<<PD2)) == 0)
{
if (i != 0)
{
i--;
OCR1A = freq[i];
OCR1B = freq[i];
}
}
}
}
Пишу на IAR, частота - 8 Мгц
- Вложения
-
main.c
- (1.26 КиБ) Скачиваний: 193
blindman » 15 июл 2010, 03:23
OCR1B не может использоваться как максимальное значение счетчика - только OCR1A.
$ilent » 15 июл 2010, 09:51
А что тут __enable_interrupt(); происходит?
Убери кнопки и просто запусти, потом кнопки повесишь.
Lockdog » 15 июл 2010, 10:08
blindman писал(а):OCR1B не может использоваться как максимальное значение счетчика - только OCR1A.
Спасибо, в протеусе всё равно не работает, на железе пока проверить не могу.
Добавлено спустя 2 минуты 59 секунд:$ilent писал(а):А что тут __enable_interrupt(); происходит?
Убери кнопки и просто запусти, потом кнопки повесишь.
на __enable не обращай внимание, осталось от старой процедуры =)
Мне интересно, почему эта конструкция не работает:
- Код: Выделить всё • Развернуть
if ((PINA & (1<<PA0)) == 0)
{
if (i != 10)
{
i++;
OCR1A = freq[i];
}
}
if ((PIND & (1<<PD2)) == 0)
{
if (i != 0)
{
i--;
OCR1A = freq[i];
}
}
$ilent » 15 июл 2010, 11:27
- Ты за одно нажатие на клавишу летаешь по диапазону значений своего: int freq[] = {1132, 132, 66, 43, 32, 26, 21, 18, 16, 14, 12};
Одно нажатие - смещение на одну позицию, а не фиг знает на сколько увеличится твоя int i = 0; переменная.
Lockdog » 15 июл 2010, 11:40
$ilent писал(а):- Ты за одно нажатие на клавишу летаешь по диапазону значений своего: int freq[] = {1132, 132, 66, 43, 32, 26, 21, 18, 16, 14, 12};
Одно нажатие - смещение на одну позицию, а не фиг знает на сколько увеличится твоя int i = 0; переменная.
Хм, почему я по всему диапазону летаю? Разве не на одну позицию и будет смещаться?
$ilent » 15 июл 2010, 12:52
Нет.
"Если нажата кнопка", то падаем ниже.
"Если и не 10", то "и++".
Выходим.
НО!!! кнопка-то ещё нажата!!! Мы же с частотой 8МГц проверяем её!!!
Вот и попадаем опять туда же.
Тебе нужно хотя бы пустой "ждать отпускания кнопки" добавить, между двумя "если".
Lockdog » 15 июл 2010, 13:19
$ilent писал(а):Тебе нужно хотя бы пустой "ждать отпускания кнопки" добавить, между двумя "если".
Вот так: while((PINA & (1<<PA0)) == 0) {} ?
Добавлено спустя 1 минуту 51 секунду:Фиг с этими кнопками, у меня не работает сам таймер.
Сейчас код выглядит так:
- Код: Выделить всё • Развернуть
#include <ioavr.h>
#include <intrinsics.h>
__flash int freq[] = {1132, 132, 66, 43, 32, 26, 21, 18, 16, 14, 12};
int i = 0;
void init_timer1_r(void)
{
TCCR1A &= ~(1<<COM1B0);
TCCR1A |= (1<<COM1A0);//Режим CTC
TCCR1B |= (1<<WGM12)|(1<<CS10);
OCR1A = freq[i];
PORTB |= (1<<PB4);
}
void init_timer1_l(void)
{
TCCR1A &= ~(1<<COM1A0);
TCCR1A |= (1<<COM1B0); //Режим CTC
TCCR1B |= (1<<WGM12)|(1<<CS10);
OCR1A = freq[i];
PORTB |= (1<<PB3);
}
void timer1_stop(void)
{
OCR1A=0;
__delay_cycles(8000000);
}
int main( void )
{
DDRD = 0x00;
DDRA = 0x00;
PORTA = 0xFF;
PORTD = 0xFF;
DDRB = 0xFF;
PORTB = 0x00;
init_timer1_r();
while(1)
{
// if ((PIND & (1<<PD0)) == 0) init_timer1_r();
// if ((PIND & (1<<PD1)) == 0) timer1_stop();
// if ((PINA & (1<<PA1)) == 0) init_timer1_l();
if ((PINA & (1<<PA0)) == 0)
{
while((PINA & (1<<PA0)) == 0) {}
if (i != 10)
{
i = i+1;
OCR1A = freq[i];
}
}
if ((PIND & (1<<PD2)) == 0)
{
while((PINA & (1<<PA0)) == 0) {}
if (i != 0)
{
i = i-1;
OCR1A = freq[i];
}
}
}
}
$ilent » 15 июл 2010, 13:23
ага.
while ((PINA & (1<<PA0)) == 0){}
или
while (!PINA & (1<<PA0)){}
Запусти таймер по-человечески. Останови, запомни СРЕГ, инициализируй, восстанови СРЕГ, разреши прерывания.
И покажи наконец ту функцию. Может ты там забыл забыл разрешить что-то.
Последний раз редактировалось $ilent 15 июл 2010, 13:37, всего редактировалось 1 раз.
blindman » 15 июл 2010, 13:37
while (!PINA & (1<<PA0)){}
Не пойдет
![No :no:](http://roboforum.ru/images/smilies/nea.gif)
Lockdog » 15 июл 2010, 13:58
blindman писал(а):while (!PINA & (1<<PA0)){}
Не пойдет
![No :no:](http://roboforum.ru/images/smilies/nea.gif)
Да опечатался наверное, вот так пойдёт:
while (!(PINA & (1<<PA0)) {}
Добавлено спустя 37 секунд:Помогите с таймером разобраться, плиз
$ilent » 15 июл 2010, 22:53
Вот те для кнопки нормальная обработка:
- Код: Выделить всё • Развернуть
uint8_t key1 = 0;
uint8_t scan_keys (void)
{
uint8_t key_number = 0;
uint16_t i;
if (key1 == 1) //Если произошло нажатие на клавишу 1
{
key1 = 0;
while (!CHECKBIT (KEY_PIN, KEY1_BIT)){}
}
else
{
if (!CHECKBIT (KEY_PIN, KEY1_BIT))
{
for(i=0; i<10000; i++)
{
asm ("nop");
}
if (!CHECKBIT (KEY_PIN, KEY1_BIT))
{
key1 = 1;
key_number = key_left;
init_timer0 (0);
SETBIT (LED_PORT, LED_BIT);
beep(100);
}
}
}
return key_number;
}
А вот для таймера. Делай по образу подобия. У меня считает импульсы на Т1 ноге - переделай под себя:
- Код: Выделить всё • Развернуть
/* Таймер опроса датчика температуры, часов и записи значений в EEPROM.
Таймер работает в режиме CTC с TOP = OCR1A
Принимает на вход значение минут.
Вызывает прерывание по совпадению с регистром компаратора А.
*/
uint8_t init_timer1 (uint8_t minuts)
{
uint16_t secunds = 0;
secunds = ((minuts * 60) - 1);
sreg = SREG; // сохраняем глобальные флаги
cli();
TCCR1B = 0x00;
TCCR1A = 0x00;
TCNT1 = 0x0000;
OCR1A = secunds;
TCCR1B |= (1 << WGM12) | (1 << CS12) | (1 << CS11);
SREG = sreg;
sei(); //re-enable interrupts
return 0;
}
ISR (TIMER1_COMPA_vect)
{
//compare occured TCNT1=OCR1A
beep(150);
}
деф файл:
- Код: Выделить всё • Развернуть
#define BIT(x) (1 << (x))
#define SETBIT(x, y) (x |= y)
#define CLEARBIT(x, y) (x &= ~y)
#define CHECKBIT(x, y) (x & y)
#define INVERT(x, y) (x ^= y)
#define KEY_PORT PORTA
#define KEY_DIR DDRA
#define KEY_PIN PINA
#define KEY1_BIT BIT3
#define KEY2_BIT BIT4
#define KEY3_BIT BIT5
Не забываем про:
- Код: Выделить всё • Развернуть
TIMSK |= (1 << OCIE1A);
Lockdog » 16 июл 2010, 00:26
Мне прерывание по совпадению вызывать не нужно.
$ilent писал(а):А вот для таймера. Делай по образу подобия. У меня считает импульсы на Т1 ноге - переделай под себя:
[code]
uint8_t init_timer1 (uint8_t minuts)
{
uint16_t secunds = 0;
secunds = ((minuts * 60) - 1);
sreg = SREG; // сохраняем глобальные флаги
cli();
TCCR1B = 0x00;
TCCR1A = 0x00;
TCNT1 = 0x0000;
OCR1A = secunds;
TCCR1B |= (1 << WGM12) | (1 << CS12) | (1 << CS11);
SREG = sreg;
sei(); //re-enable interrupts
return 0;
}
Собственно у меня примерно тоже самое
Добавлено спустя 7 минут 8 секунд:Кстати, когда моделю в протеусе, то у меня тактирование на ноги идёт, только, если нажаты обе кнопки на PD0 и PA1
$ilent » 16 июл 2010, 09:09
Если не нужно прерываться, то зачем вообще таймер юзать?
Lockdog » 16 июл 2010, 17:51
$ilent писал(а):Если не нужно прерываться, то зачем вообще таймер юзать?
Мне нужно, чтобы при переполнении таймера менялось состояние пина OC1A или OC1B, а это можно делать и без прерывания.
- Вложения
-
![tmr.jpg (182.55 КиБ) Просмотров: 2604 tmr.jpg](./download/file.php?id=16912&t=1&style=9&sid=9846e1d1e63a6acff88c14e346272f51)