Страница 1 из 3
atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:09:15
okmonster
привет
у меня проблема
микроконтролер атмега32
нужно запустить прерывания по таймеру
сразу два , но если я запускаю один то все норм а если два то происходит что то не ладное, вся функция майн запускается заново очень быстро
/***Настраиваем таймер***/
TCCR1A = 0x00;
TCCR1B = (1 << CS12)|(0 << CS11)|(1 << CS10)|(1 << WGM12); //предделитель clk/1024, режим таймера СТС
TCNT1=0x00;
OCR1A=7905; // выбор коэффициента деления
TIMSK=(1 << OCIE1A); // разрешение прерывания по совпадению
TCCR0 = 0x00;
TCCR0 = (1 << CS12)|(0 << CS11)|(1 << CS10)|(1 << WGM12); //предделитель clk/1024, режим таймера СТС
TCNT0=0x00;
OCR0=7905; // выбор коэффициента деления
TIMSK=(1 << OCIE0); // разрешение прерывания по совпадению
asm ("sei"); // Разрешение прерываний
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:12:10
Cat
Это что за индийские коды?:
TIMSK=(1 << OCIE1A);
TCCR1B = (1 << CS12)|(0 << CS11)|(1 << CS10)|(1 << WGM12);
А это вообще "пушка" TIMSK=(1 << OCIE1A);
Не проще ли нормально вписать в регистры числа, вместо этого изврата?
Всякие чудеса быдлокодинга видел, но такое впервые. Какие-то кривые разрозненные участки кода, по которым непонятно когда, где и как они исполняются.
Какое ТЗ? Можно нормально сформировать требуемую задачу? А то "хочу включить прерывания"... Какие? в меге 32 21 вектор, если не ошибаюсь
вся функция майн запускается заново очень быстро
Заново она запускаться может только при сбросе контроллера.
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:20:28
Engineer_Keen
Cat писал(а):Это что за индийские коды:
Не проще ли нормально вписать в регистры числа, вместо этого изврата?
Всякие чудеса быдлокодинга видел, но такое впервые.

Вот те раз, а я то думал это для читаемости кода и сам так теперь пишу

Кто еще не согласен?
okmonster писал(а):
сразу два , но если я запускаю один то все норм а если два то происходит что то не ладное, вся функция майн запускается заново очень быстро
Вы сначала пишите в TIMSK один бит для включения прерывания по 1-му таймеру, а после настройки 0-го таймера у вас этот бит затирается командой TIMSK=(1 << OCIE0), в итоге работает только последнее прерывание. Нужно либо TIMSK|=(1 << OCIE0), либо записывать только в конце: TIMSK=(1 << OCIE0)|(1 << OCIE1A)
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:21:02
ploop
Не проще ли нормально вписать в регистры числа, вместо этого изврата?
Это типа как? TIMSK=0xXX ? Вообщето такую запись и называют "индийскими кодами"

Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:22:29
okmonster
Cat писал(а):Это что за индийские коды?:
TIMSK=(1 << OCIE1A);
TCCR1B = (1 << CS12)|(0 << CS11)|(1 << CS10)|(1 << WGM12);
А это вообще "пушка" TIMSK=(1 << OCIE1A);
Не проще ли нормально вписать в регистры числа, вместо этого изврата?
Всякие чудеса быдлокодинга видел, но такое впервые.
Какое ТЗ? Можно нормально сформировать требуемую задачу? А то "хочу включить прерывания"... Какие? в меге 32 21 вектор, если не ошибаюсь
вся функция майн запускается заново очень быстро
Заново она запускаться может только при сбросе контроллера.
мне нужно запускать две функции с определенной частотой
вот я и пытаюсь запускать их по таймеру
пытался сделать вот по этой статье
http://radioparty.ru/index.php/prog-avr ... 34-lesson6
сам просто еще только начинаю изучать все это дело
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:24:32
Cat
Ну хотите максимально усложнить читабельность кода - дело ваше, только не удивляйтесь что никто не захочет читать ваши нагромождения операций в тех местах, где достаточно просто вписать число в регистр.
// External Interrupt(s) initialization
GICR=0b01000000;// включено внешнее прерывание 0 (1 0 2)//будем в коде периодически выключать прерывание 1
MCUCR=0b00001010;// внешнее прерывание 0 и 1 по спаду
MCUCSR=0x00; //второе прерывание не задействовано
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0b01000100;//прерывание по переполнению таймера 1 и 2
ADMUX=0b11000000; //Внутренний ИОН. выравнивание справа, нулевой вход
ADCSRA=0b10000110; // ацп включен, частота кварц/64
SPCR=0b01010000; // мастер. Фронт - нарастающий, выборка по фронту
SPSR=1; // удвоение частоты SPI
Так читабельнее?
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:29:20
Cat
ploop писал(а):
Это типа как? TIMSK=0xXX ? Вообщето такую запись и называют "индийскими кодами"

Хз, хотя в том же ДШ на мегу 32 пример инициализации на Си
PORTB = (1<<PB7)|(1<<PB6)|(1<<PB1)|(1<<PB0);
А обвинить даташитописателей в криворукости сложновато.
Я что-то не понимаю ?
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:31:07
Engineer_Keen
Cat писал(а):
MCUCR=0b00001010;// внешнее прерывание 0 и 1 по спаду
Так читабельнее?
Ога, и вспоминай потом, какой бит в MCUCR Sleep Enable, а какие включили... Хорошо если даташит или студия перед глазами.
Или например SPI из слейва в мастер переключить? Знаете какой бит отвечает за это наизусть? Сможете без даташита переключить?
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:31:34
ploop
Так читабельнее?
Я фигею!
Не, ну если вы можете держать в голове порядковый номер каждого бита и информацию, за что он отвечает - то да. Но тогда зачем вам компилятор? Проще машинные коды выучить и писать HEX прямо в блокноте...
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:31:57
okmonster
почему то если я вообще начинаю использовать 0 счетчик или второй то у меня в Proteus начинается какой то ребут функции майн она крутится очень быстро
а если использую 1 счетчик то все норм.
если одновременно два то тоже крутится майн
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:34:43
Engineer_Keen
Код целиком приведите уже

Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:35:40
Cat
ploop писал(а):Так читабельнее?
Я фигею!
Не, ну если вы можете держать в голове порядковый номер каждого бита и информацию, за что он отвечает - то да. Но тогда зачем вам компилятор? Проще машинные коды выучить и писать HEX прямо в блокноте...
Эээээ... я много работаю с мегами, в меге32 и 16 большинство регистров действительно знаю наизусть каждый бит... и при записи вида РЕГИСТР=0bxxxxxxxx сразу вижу как отконфигурировано и что.
Засем можно считать что я тупанул, можете закидать помидорчиками.

Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:36:05
okmonster
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <string.h>
#include <avr/interrupt.h>
#define RS PC2
#define EN PC0
#define DATA 3 // Подключаем к порту PD0 ножку данных сдвигового регистра
#define CLK 4 // Подключаем к порту PD1 ножку тактовых импульсов сдвигового регистра
#define Latch 5 // Подключаем к порту PD1 ножку защёлки сдвигового регистра
int u,ut;
int i,io,id,data_sekund=0,data_status=0,data_minut=0,data_byf;
int ttt=1;
int qwertyNAVIG[8][3] = {
{1,500,530},// вверх
{2,255,265}, // вниз
{3,125,135}, // влево
{4,1000,1025}, // вправо
{5,340,350}, // ok
{6,140,155}, //bat1
{7,160,180},//bat2
{8,200,220} //bat3
};
int qwertyN[10][3] = {
{1,1010,1024},
{2,130,150},
{3,120,129},
{4,500,510},
{5,165,175},
{6,108,115},
{7,330,350},
{8,195,210},
{9,94,105},
{0,250,260}
};
int qwertyM[5];
int qwertyQ,qwertyR,qwertyNOMER=0,qwertyRESULT,qwertyPRINT;
void send_data (unsigned int data){
int i;
for (i=0;i<16;i++){
if ((data&0x8000)==0x00) PORTB&=~_BV(DATA); // Выставляем данные на PD0
else PORTB|=_BV(DATA);
asm("nop");
PORTB|=_BV(CLK); // Импульс на CLK
asm("nop");
PORTB&=~_BV(CLK);
asm("nop");
data=(data<<1);
}
PORTB|=_BV(Latch); // Импульс на Latch clock
asm("nop");
PORTB&=~_BV(Latch);
}
/***Функция записи команды в LCD***/
void lcd_com(unsigned char p) //'p' байт команды
{
PORTB &= ~(1 << RS); // RS = 0
PORTB |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD = p; // вывод команды на шину DB0-7 LCD
//_delay_us(40); // длительность сигнала EN
PORTB &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(40); // пауза для выполнения команды
}
/***Функция записи данных в LCD***/
void lcd_dat(unsigned char p) //'p' байт команды
{
PORTB |= (1 << RS)|(1 << EN); //RS = 1, EN = 1 (начало записи команды в LCD)
PORTD = p; //вывод команды на шину DB0-7 LCD
_delay_us(20); // длительность сигнала EN
PORTB &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(20); // пауза для выполнения команды
}
/***Функция инициализации LCD***/
void lcd_init(void)
{
lcd_com(0x08); // полное выключение дисплея
lcd_com(0x38); // 8 бит 2 строки
_delay_us(1400);
lcd_com(0x38); // 8 бит 2 строки
_delay_us(1400);
lcd_com(0x38); // 8 бит 2 строки
lcd_com(0x38);
lcd_com(0x01); // очистка дисплея
_delay_us(1400);
lcd_com(0x06); // сдвиг курсора вправо
lcd_com(0x0C); // включение дисплея, мигающий курсор
}
void Write( char s[], int sped)
{
int i = 0;
for ( i = 0; i < strlen(s); i++ )
{
lcd_dat(s);
_delay_ms( sped );
}
}
void WriteLCD( char s[])
{ lcd_com(0x80);
int i = 0;
for ( i = 0; i < strlen(s); i++ )
{
if(i==20){lcd_com(0xC0);}
if(i==40){lcd_com(0x94);}
if(i==60){lcd_com(0xD4);}
lcd_dat(s);
}
}
void start(void)
{
lcd_com(0xC2);
Write("START VAKUMNAYA",200);
lcd_com(0x9B);
Write("PECHKA",200);
_delay_ms( 100000 );
_delay_ms( 100000 );
lcd_com(0x01);
_delay_ms( 100000 );
_delay_ms( 100000 );
}
// Опорное напряжение - ножка AREF
#define ADC_VREF_TYPE 0b00000000
unsigned int ADCRead(unsigned char adc_input) // Read the AD conversion result
{
ADMUX = adc_input | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
_delay_us(10);
// Start the AD conversion
ADCSRA |= 0x40;
while ((ADCSRA & 0x10) == 0); // Wait for the AD conversion to complete
ADCSRA |= 0x10;
return ADCW;
}
/***Процедура обработки прерывания по Таймеру 1***/
ISR (TIMER1_COMPA_vect)
{
if(data_status==0){
data_sekund++;
if (data_sekund==61){data_minut++;data_sekund=0;}
}
}
/***Процедура обработки прерывания по Таймеру 0***/
ISR (TIMER0_COMPA_vect)
{
ttt=ttt+1;
}
int main()
{
ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(0 << ADPS1)|(1 << ADPS0);
char text[19][1] = {"0","1","2","3","4","5","6","7","8","9" };
//старт LCD ************************************************
DDRB |= (1 << PC2)|(1 << PC1)|(1 << PC0)|(1 << PC3)|(1 << PC4)|(1 << PC5); // PC0-3 выходы
PORTB = 0x00; // лог. 0 на выходе
DDRD = 0xFF; // PD0-7 выходы
PORTB = 0x00;
lcd_init();
//start();
send_data (0b0111111111111111);
//WriteLCD("P= Pz= T= Tz= status: Time=");
/***Настраиваем таймер***/
TCCR1A = 0x00;
TCCR1B = (1 << CS12)|(0 << CS11)|(1 << CS10)|(1 << WGM12); //предделитель clk/1024, режим таймера СТС
TCNT1=0x00;
OCR1A=7905; // выбор коэффициента деления
//TIMSK=(1 << OCIE1A); // разрешение прерывания по совпадению
TCCR0 = 0x00;
TCCR0 = (0 << CS12)|(0 << CS11)|(1 << CS10)|(1 << WGM12); //предделитель clk/1024, режим таймера СТС
OCR0=10; // выбор коэффициента деления
//TIMSK=(1 << OCIE0); // разрешение прерывания по совпадению
TIMSK=(1 << OCIE0)|(1 << OCIE1A);
asm ("sei"); // Разрешение прерываний
int displey=0,displey_r=10000,displey_v=10;
lcd_com(0x0D);
while(1){
if (displey==0)
{
if (displey_r!=0) {WriteLCD("* Start * Test * Settings * Exit"); displey_r=0;}
if(displey_v==10){lcd_com(0x80);}
if(displey_v==20){lcd_com(0xC0);}
if(displey_v==30){lcd_com(0x94);}
if(displey_v==40){lcd_com(0xD4);}
ut=ttt;
for ( i = 0; i <7; i++ )
{
io=ut%10;//if(io==0){lcd_dat(text[8][1]);}
ut=ut/10;
lcd_dat(text[io-1][1]);
}lcd_com(0x04);
}
}
}
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:38:32
Cat
okmonster писал(а):
в Proteus начинается какой то ребут ....н
Сторожевую собаку отключите!!!!!

Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:39:54
okmonster
Cat писал(а):okmonster писал(а):
в Proteus начинается какой то ребут ....н
Сторожевую собаку отключите!!!!!

чего?
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:40:48
Cat
Watchdog не запускали? В схеме на ресет не приходит 0? Нужно искать источник перезагрузки МК в симуляторе
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:44:15
okmonster
Cat писал(а):Watchdog не запускали? В схеме на ресет не приходит 0? Нужно искать источник перезагрузки МК в симуляторе
нет не приходит
а что такое Watchdog как его запускать?
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:45:57
Engineer_Keen
Watchdog следит чтоб МК не завис, если он включен, его нужно периодически сбрасывать иначе он сбросит контроллер. Но у вас он не включен, так что не парьтесь.
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:48:24
ploop
Засем можно считать что я тупанул, можете закидать помидорчиками.
Да ладно, сам когда начинал писал битами.
Пооффтоплю немного, но автору тоже полезно будет.
Названия типа CS12 - это сокращения от полных наименований. И по сути это константы с порядковым номером бита.
Например тот же CS12 - Clock Source Timer 1 bit 2 или "Второй бит источника тактирования таймера 1" Это запоминается на раз, и после пары-тройки проектов уже в даташит заглядывать не надо.
Разумеется в контроллер попадает готовое число, которое вычисляется на этапе компиляции. Единственный минус - писать чуть длиннее, но по времени гораздо короче, чем искать номера битов в даташите.
Re: atmega32 прерывание по таймеру
Добавлено: Чт мар 22, 2012 14:52:57
okmonster
что то проблема так и не решается(
с 0 таймером даже в одиночку ничего не работает
прилагаю все файлы мои