WinAVR. Не выходит из подпрограммы по переполнению T/C0

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Аватара пользователя
Dako
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Сб июл 30, 2011 05:35:35

WinAVR. Не выходит из подпрограммы по переполнению T/C0

Сообщение Dako »

Помогите товарищи, коты! Всю голову сломал уже. Написал программку для отображения двух цифер на семисегиентных индикаторах. Подпрограмма вызывается по переполнению таймера/счётчика1. Цифры выводятся, но основное тело программы не выполняется, то бишь после окончания программы обработки прерывания, МК неизвестно чем занимается до появления следующего прерывания. По задумке цифры меняются в процессе выполнения основного цикла, по факту отбражаются цифры указанные при инициализации. Помогите, я то я скоро истеричкою сделаюсь! ))

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>

int i = 0 ;
int count = 0 ;
int digit1 = 1 ;
int digit2 = 2 ;

ISR(SIG_OVERFLOW0)
{

if (i==2) i=0 ;

switch(i)
{
case 0:PORTB = digit2;PORTB |= (0<<5);PORTB |= (1<<6);break;
case 1:PORTB = digit1;PORTB |= (1<<5);PORTB |= (0<<6);break;
}

i++ ;
}

int main(void)
{
DDRB = 0xFF ;
PORTB = 0 ;
TIMSK = 0b00000001 ;
TCCR0 = 0b00000010 ;

sei() ;

while(1)
{
digit1++ ;
digit2++ ;
_delay_ms(250) ;
}
}
Реклама
Мастер Ломастер
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город
Контактная информация:

Re: WinAVR. Не выходит из подпрограммы по переполнению T/C0

Сообщение Мастер Ломастер »

1. не истерить
2. читать документацию на WinAVR и язык Си
3. SIG_OVERFLOW не использовать (устарело давно), использовать TIMER0_OVF_vect
4. все переменные, которые используются И в прерывании И в главном цикле должны быть volatile - 100500 раз говорено. у вас, в частности, это как раз digit1 и digit2
битва с дураками проиграна, победители торжествуют. слава победителям!
Реклама
Аватара пользователя
Dako
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Сб июл 30, 2011 05:35:35

Re: WinAVR. Не выходит из подпрограммы по переполнению T/C0

Сообщение Dako »

Большое спасибо за ответ! Всё работает )) Я только начинаю осваивать электронику и программирование - извиняюсь за глупые вопросы
Аватара пользователя
Dako
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Сб июл 30, 2011 05:35:35

DS18B20. Лжёт подлец!

Сообщение Dako »

Что бы не плодить темы продолжу тут. Собираю в общем электроградусник на Меге8, DS18B20 b 2-х семисегментных индикаторах. Семисегментники ожили, показывают адекватно число в обоих разрядах, датчик откликается, даже данные выдает и на температуру реагирует. )) НО - врёт: При комнатной температуре индикатор показывает "03", если коэфициент "0,0625" подогнать и сделать к примеру "0,625", показывает "32", если подержаться за датчик рукой постепенно поднимается до "42", то есть на температуру действительно реагирует. Ещё что смущает: разряды то поочерёдно, то одновременно показывают случайные числа на интервал около секунды, я так полагаю что с датчика неверные числа приходят. Помогите пожалуйста, товарищи коты! Текст программы ниже.

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>

#define W1_PORT PORTC
#define W1_DDR DDRC
#define W1_PIN PINC
#define W1_BIT 0

volatile char count = 0 ;
volatile char digit1 ;
volatile char digit2 ;


//Выводим значение температуры на 2 семисегментных индикатора
ISR(SIG_OVERFLOW0)
{
if (count==2) count=0 ;
switch(count)
{
case 0:PORTB = digit2;PORTB |= (0<<5);PORTB |= (1<<6);break;
case 1:PORTB = digit1;PORTB |= (1<<5);PORTB |= (0<<6);break;
}
count++ ;
}

//функция определяет есть ли устройство на шине
unsigned char w1_find()
{
unsigned char device;
W1_DDR |= 1<<W1_BIT;
_delay_us(485);
W1_DDR &= ~(1<<W1_BIT);
_delay_us(65);

if((W1_PIN & (1<<W1_BIT)) ==0x00)
device = 1;
else
device = 0;
_delay_us(420);
return device;
}
//функция посылает команду на устройство 1-wire
void w1_sendcmd(unsigned char cmd)
{
for(unsigned char i = 0; i < 8; i++)
{
if((cmd & (1<<i)) == 1<<i)
{
W1_DDR |= 1<<W1_BIT;
_delay_us(2);
W1_DDR &= ~(1<<W1_BIT);
_delay_us(65);
}
else
{

W1_DDR |= 1<<W1_BIT;
_delay_us(65);
W1_DDR &= ~(1<<W1_BIT);
_delay_us(5);
}
}
}
//функция читает один байт с устройства 1-wire
unsigned char w1_receive_byte()
{
unsigned char data;
for(unsigned char i = 0; i < 8; i++)
{
W1_DDR |= 1<<W1_BIT;
_delay_us(2);
W1_DDR &= ~(1<<W1_BIT) ;
_delay_us(7);

if((W1_PIN & (1<<W1_BIT)) == 0x00)
data &= ~(1<<i);
else
data |= 1<<i;
_delay_us(50);
}
return data;
}
//функция преобразует полученные с датчика 18b20 данные в температуру
int temp_18b20()
{
unsigned char data[2];
int temp = 0;
if(w1_find()==1)//если есть устройство на шине
{
w1_sendcmd(0xcc);//пропустить ROM код, мы знаем, что у нас одно устройство или передаем всем
w1_sendcmd(0x44);//преобразовать температуру
_delay_ms(750);//преобразование в 12 битном режиме занимает 750ms
w1_find();//снова посылаем Presence и Reset
w1_sendcmd(0xcc);
w1_sendcmd(0xbe);//передать байты ведущему(у 18b20 в первых двух содержится температура)
data[0] = w1_receive_byte();//читаем два байта с температурой
data[1] = w1_receive_byte();
//загоняем в двух байтную переменную
temp = data[1];
temp = temp<<8;
temp |= data[0];
//переводим в градусы
temp *= 0.625;//0.0625 градуса на единицу данных
}
//возвращаем температуру
return temp;
}


int main(void)
{
DDRB = 0xFF ;
TIMSK = 0b00000001 ;
TCCR0 = 0b00000010 ;
char temp ;
sei() ;
while(1)
{
temp = temp_18b20() ;
if(temp > 1000) //если температура <0
{
temp = 4096 - temp ;
temp = -temp ;
}
digit1 = temp/10 ;//выводим на дисплей
digit2 = temp%10 ;
}
}
Реклама
Эиком - электронные компоненты и радиодетали
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»