реклама на сайте
подробности

 
 
> Фазовое управление симисторами
Sadmi
сообщение Aug 30 2011, 09:28
Сообщение #1





Группа: Новичок
Сообщений: 9
Регистрация: 30-08-11
Пользователь №: 66 930



Добрый день. Это мой первый опыт программирования на Си вообще и под МК в частности. Прошу сразу не пинать.
Задача стоит такая: организовать управление восемнадцатью лампами накаливания с плавной регулировкой мощности.
После прохода напряжения через ноль счетчик отсчитывает определенное количество тактов (в зависимости от нужной мощности) и на 100 микросекунд (считает второй таймер) включается соответствующий порт.
Использую Atmega32, AVR Studio 5. Написал код, анализирую в AVS Studio, все работает правильно, загоняю в Протеус ничего не работает. Предполагаю, что что-то не так с прерываниями делаю, но что?
Прошу помощи! Спасибо!

CODE
#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned long u; // переменная - результат АЦП
volatile unsigned long f; // первый нуль - 1, не первый - 0
/* Таблица задержек */
volatile unsigned char tz[25]={20,30,70,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
// Массив мощностей
volatile unsigned char pch[3][17]={
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}, // Номер канала
{0,1,2,4,4,4,4,4,4,4, 4, 4, 4, 4, 4, 4, 4}, // Текущая мощность
{0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0}}; // Флаг установки канала
volatile unsigned char i=0; //
volatile unsigned char t=0;
volatile unsigned char q, fl=0;

/***Обработчик прерываний по окончанию преобразования АЦП***/
ISR (ADC_vect)
{
u = (ADC*11/4);
}

/*** Обработчик прерываний по совпадению таймера ***/
ISR(TIMER0_COMP_vect)
{
//--------------------------------------------------------------------------------------------
for (i=0; i<18; i++) // Перебираем каналы и включаем нужный
{
if (pch[1][i]==t)
{
if (pch[2][i]==0) // Если еще не установлен в текущем периоде
{
pch[2][i]=1;
switch (pch[0][i]) // Определяем линию и порт для установки - 1
{
case 0: PORTD |=1<<0; break;
case 1: PORTD |=1<<1; break;
case 2: PORTD |=1<<2; break;
}
}
}
}
t++;
if (t==25) {t=0;}
OCR0=tz[t]; // Новое значение совпадения

//-------------------------------------------------------------------------------------------
TCNT0=0; //Обнуляем таймер
TCNT2=0; //Обнуляем таймер

}

/***Обработчик прерывания по совпадению таймера (длительность откывающего импульса)***/
ISR(TIMER2_COMP_vect)
{
//Выключаем канал
PORTD=0;
/* switch (t)
{
case 0: PORTD &=~(1<<0); break;
case 1: PORTD &=~(1<<0); break;
case 2: PORTD &=~(1<<2); break;
}
*/ TCNT2=0; //Обнуляем таймер
}

/***Главная функция***/
int main (void)
{
DDRD = 0xFF; // Порт на выход
PORTD = 0x00;

DDRA = 0x00;

/* Настройка АЦП */
ADCSRA = (1 << ADEN) // разрешение работы АЦП
|(1 << ADSC) // запуск преобразования
|(1 << ADATE) // непрерывный режим работы АЦП
|(1 << ADPS2)|(1 << ADPS1)|(0 << ADPS0) // предделитель на 64
|(1 << ADIE); // разрешение прерывания
ADMUX = (1 << REFS1)|(1 << REFS0) // внутренний ИОН 2,56V
|(0 << MUX3)|(0 << MUX2)|(0 << MUX1)|(0 << MUX0); // вход (ADC0) PA1

/* Настройка таймера задержки (мощность канала)*/
TCCR0|=(1<<CS00); //
TCCR0|=(0<<CS01); // Установка предделителя (1024)--------------------------------------!!!
TCCR0|=(1<<CS02); //
OCR0=tz[pch[1][t]]; // Установка значения в регистре совпадения.
TCCR0|=(0<<FOC0)|(1<<COM00)|(1<<WGM01);
TIMSK|=(1<<OCIE0); // Разрешить прерывание по совпадению.

/* Настройка таймера (время открывающего импульса 100мкс)*/
TCCR2|=(1<<CS21); //
TCCR2|=(1<<CS20); // Установка предделителя (32)--------------------------------!!!
TCCR2|=(0<<CS20); //
OCR2=50; // Установка значения в регистре совпадения.
TCCR2|=(0<<FOC2)|(1<<COM20)|(1<<WGM21);
TIMSK|=(1<<OCIE2); // Разрешить прерывание по совпадению.

sei(); //глобальное разрешение прерываний

TCNT0=0;
TCNT2=0;

while(1)
{
if (u<20)
{
f++;
}
else
{
f=0;
}

if (f==1) // Обнаружен проход через нуль
{
t=0;
for (q=0; q<18; q++) //обнуляем флаги установки каналов
{
pch[2][q]=0;
}
TCNT0=0;
TCNT2=0;
PORTD |= 1<<3;
}
else
{
PORTD &= ~(1<<3);
}
}
}


Сообщение отредактировал IgorKossak - Aug 30 2011, 17:55
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
xemul
сообщение Aug 31 2011, 07:58
Сообщение #2



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



А бездумные volatile, unsigned long и *4/11 там, где достаточно 1 бита и сравнения - типа правильно?
Прерывание от АЦП здесь вообще бессмысленно - с тем же успехом можно читать АЦП непосредственно там, где используется (якобы) u.

2Sadmi:
у Вас в прерываниях изменяется только t, вот и оставьте его volatile.
Зачем Вам нужен pch[0][] в виде {0,1,2,3,...}?
Вместо "t++; if (t==25) {t=0;}" логичней будет, н-р, "if (t < 25) t++;", имхо.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 11:51
Рейтинг@Mail.ru


Страница сгенерированна за 0.0139 секунд с 7
ELECTRONIX ©2004-2016