
Методичка (МПС)
.pdf}
void timer0_init(void)
{
TCCR0 = 0x00;
TCNT0 = 0x00;
OCR0 = 0x00;
TCCR0 = 0x00;
}
void adc_init(void)
{
ADCSRA = 0x00;
ADMUX = 0x60;
ADCSRA = 0x00; ADCSRA = 0xCF;
}
0 " 00 " $ $$ , $ % $ 3* "
$ TCCR0 0x4B. " % 3*
" = ( /64)/256 = 488 .
$ -' " & 8-
% clk/128. ) $ & 8) ' 8).
4. ) ! " $
" while(1) % & %
. ' !
:
if((PINA&0x04)==0x04)
{
TCCR0=0x4B;
}
else
{
TCCR0=0x00;
TCNT0=0x00;
PORTB=0x00;
}
- ! , " 00, ! ,
& " 00 & PORTB.
5. ) $ & 8) ' ,
' adc_isr():
CLI(); adc_result=ADCH;
if(adc_result<=5) adc_result=5; else if(adc_result>=250) adc_result=250; OCR0=adc_result;
ADCSRA|=0x40;
SEI();
& & 8) $ ADCH$ $ & & ,
61

& " & " %. ) $ &
$ " 00 OCR0.
6. 0 " 00 ' $ TCNT0 # " "
$ '. : $
&$ 255, $
OCR0. ) TCNT0=OCR0 ' 00,
$ TCNT0 ' 00. ) 00
VT2 VT4, $ #,
VT1 VT3:
CLI(); if((PINA&0x02)==0x02)
{
PORTB=0x08;
}
else
{
PORTB=0x02;
}
SEI();
) 00
VT1 VT3, #. 0
' !-&
' % :
CLI(); if((PINA&0x02)==0x02)
{
PORTB=0x09;
}
else
{
PORTB=0x06;
}
SEI();
0, & 8) $ OCR0 5,
TCNT0=OCR0=5 % VT4,
", & TCNT0=255
VT1, " % TCNT0=5. 0
' % & $ % 2 = <;=; = 0,02, %
&.
) ) 5-"
'
) 4 1… 4. ) 1 4 ' 2 3.
62
& % 2 = 0,5 %
, % 2 = 1 – & % &,
% 2 = 0,5 – & & %.
# 2. & !-&
$ % . , % & $
, $ RP1
.
//------------------------------------------------------------------
//Входы:
//PA0 – сигнал задания на ШИП
//PA1 – задание направления вращения
//PA2 – разрешение на работу преобразователя //Выходы:
//PB0 – управление транзистором VT1 (вход А1)
//PB1 – управление транзистором VT2 (вход B1)
//PB2 – управление транзистором VT3 (вход C1)
//PB3 – управление транзистором VT4 (вход D1)
//Подключение стандартных бибилиотек:
#include <iom32v.h> #include <macros.h>
//Объявление переменных:
unsigned char adc_result=0; unsigned char delay=0;
//Функция инициализации портов ввода/вывода:
void port_init(void)
{ |
|
|
PORTA |
= 0xFE; |
//Порт А инициализируется на ввод данных |
DDRA |
= 0x00; |
|
PORTB |
= 0xF0; |
//Порт В инициализируется на вывод данных |
DDRB |
= 0x0F; |
|
PORTC |
= 0xFF; |
|
DDRC |
= 0x00; |
|
PORTD |
= 0xFF; |
|
DDRD |
= 0x00; |
|
} |
|
|
//Функция инициализации таймера Т0 в режиме ШИМ:
void timer0_init(void)
{
TCCR0 = 0x00; |
|
|
||
TCNT0 |
= 0x00; |
|
|
|
OCR0 |
= |
0x7F; |
//В таймере Т0 задается среднее значение |
127 |
TCCR0 = |
0x00; |
//Запуск таймера – при записи TCCR0=0x4B |
|
}
63
//Функция инициализации аналого-цифрового преобразователя:
void adc_init(void)
{ |
|
ADCSRA = 0x00; |
|
ADMUX = 0x60; |
|
ADCSRA = 0x00; |
|
ADCSRA = 0xCF; |
//АЦП – в режиме однократного преобразования |
} |
//в 8-битном режиме с предделителем 128 |
//Обработка прерывания готовности АЦП: |
|
#pragma interrupt_handler adc_isr:iv_ADC |
|
void adc_isr(void) |
|
{ |
|
CLI(); |
//Запрет всех прерываний |
adc_result=ADCH; |
//Считывание результата преобразования АЦП |
adc_result>>=1; |
//Деление результата пополам и ограничение |
if(adc_result<=5) |
adc_result=5; |
//на минимальном |
else if(adc_result>=122) |
adc_result=122; |
//и максимальном уровнях |
if((PINA&0x02)==0x02) |
//При движении «Вперед» |
|
{ |
|
|
OCR0=0x7F+adc_result; |
//уставка таймера больше 127 |
|
} |
|
|
else |
//При движении «Назад» |
|
{ |
|
|
OCR0=0x7F-adc_result; |
//уставка таймера меньше 127 |
|
} |
|
|
ADCSRA|=0x40; |
//Перезапуск АЦП |
|
SEI(); |
//Разрешение всех прерываний |
|
} |
|
|
//Обработка прерывания по совпадению таймера Т0:
#pragma interrupt_handler timer0_comp_isr:iv_TIM0_COMP void timer0_comp_isr(void)
{ |
|
CLI(); |
//Запрет всех прерываний |
PORTB=0x00; |
//Выключение транзисторов |
for(delay=0;delay<5;delay++) {;} |
//Защита от короткого замыкания |
PORTB=0x09; |
//Включение VT1 и VT4 |
SEI(); |
//Разрешение всех прерываний |
} |
|
//Обработка прерывания по переполнению таймера Т0:
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF void timer0_ovf_isr(void)
{ |
|
CLI(); |
//Запрет всех прерываний |
PORTB=0x00; |
//Выключение транзисторов |
for(delay=0;delay<5;delay++) {;} |
//Защита от короткого замыкания |
PORTB=0x06; |
//Включение VT2 и VT3 |
SEI(); |
//Разрешение всех прерываний |
64
}
//Функция инициализации периферийных устройств:
void init_devices(void)
{ |
|
|
CLI(); |
|
//Запрет всех прерываний |
port_init(); |
//Вызов функции инициализации портов |
|
timer0_init(); |
//Вызов функции инициализации таймера Т0 |
|
adc_init(); |
//Вызов функции инициализации АЦП |
|
MCUCR |
= 0x00; |
|
GICR |
= 0x00; |
//Запрет внешних прерываний |
TIMSK = 0x03; |
//Разрешение прерываний по совпадению и |
|
SEI(); |
|
//переполнению таймера Т0 |
} |
|
|
//Основная функция программы: |
||
void main(void) |
|
|
{ |
|
|
init_devices(); |
//Вызов функции инициализации устройств |
|
while(1) |
|
{ |
|
if((PINA&0x04)==0x04) |
//При подаче сигнала разрешения на работу |
{ |
|
TCCR0=0x4B; |
//Запуск таймера Т0 |
} |
|
else |
//Иначе |
{ |
|
TCCR0=0x00; |
//Остановка таймера Т0 |
TCNT0=0x00; |
|
PORTB=0x00; |
//И выключение транзисторов. |
} |
|
} |
|
} |
|
//------------------------------------------------------------------- |
|
& " $"
&, & $
$ , & $ !$
$ .
65
+ ' - 7. # ! 1 !
5-" ', ' 67 ) "
)
/ " '
+ & $ 3*)-6)0
"
.
# ) '
1.( & " " 3*)- 6)0 .
2.& " $ "
3*)-6)0.
3., & $
& &
" .
# '
) $" & &
& % & , - " & $
$ $ .
0 % & & &
% " " , "
$ $ .
+ " % & "
& , "
" (" , , 2/+),
' $ $
.
" "
3*)-6)0 &$
.
#$ $ $ & &
Atmega32, % " « ». ) & $ $
, 56, $
" .
6 $ "
# " $ , $
ATmega32 « », $ "
. : $ & &$
66
( «Y» «3-& " &»)
' .
$ , & " $
, & %. ) "
.
# 1. , & $ $ $
" , &
% & " '' )*- $ .
//-------------------------------------------------------------------
//Входы:
//PA0 – сигнал задания на ШИП
//PA2 – разрешение на работу преобразователя
//PD3 – подключение сигнала обратной связи с выхода имп. датчика «Y» //Выходы:
//PB0 – управление транзистором VT1 (вход А1)
//PB1 – управление транзистором VT2 (вход B1)
//PB2 – управление транзистором VT3 (вход C1)
//PB3 – управление транзистором VT4 (вход D1)
//Подключение стандартных библиотек:
#include <iom32v.h> #include <macros.h>
//Объявление перменных:
unsigned int pulse=0; unsigned char cycle_cnt=0; signed char Kp=-2; unsigned char Ti=6;
unsigned long int Uvh=0,Uos=0;
signed long int delta=0,delta_i=0,Up=0,Urs=0,Urs_=0;
//Функция инициализации портов ввода/вывода:
void port_init(void)
{ |
|
|
PORTA |
= 0xFE; |
//Порт А инициализируется на ввод данных |
DDRA |
= 0x00; |
|
PORTB |
= 0xF0; |
|
DDRB |
= 0x0F; |
//Порт B инициализируется на вывод данных |
PORTC |
= 0xFF; |
|
DDRC |
= 0x00; |
|
PORTD |
= 0xFB; |
//Бит PD2 готов для работы прерывания INT0 |
DDRD |
= 0x00; |
|
} |
|
|
//Функция инициализации аналого-цифрового преобразователя
void adc_init(void)
{
67
ADCSRA = 0x00; |
|
ADMUX = 0x60; |
|
ADCSRA = 0x00; |
|
ADCSRA = 0xCF; |
//АЦП запускается в 8-битном режиме в режиме |
} |
//одиночного преобразования с предделителем |
|
//clk/128 |
//Функция инициализации 8-разрядного таймера Т0 в режиме ШИМ:
void timer0_init(void)
{
TCCR0 = 0x00;
TCNT0 = 0x00;
OCR0 = 0x00;
TCCR0 = 0x00;
}
//Функция инициализации 16-разрядного таймера Т1:
void timer1_init(void)
{ |
|
|
TCCR1B = 0x00; |
|
|
TCNT1H = 0x00; |
|
|
TCNT1L = 0x00; |
|
|
OCR1AH = 0x1F; |
//Уставка 1 мс при использовании таймера в режиме |
|
OCR1AL = 0x40; |
//СТС без предделителя частоты |
|
OCR1BH = 0x00; |
|
|
OCR1BL = 0x00; |
|
|
ICR1H |
= 0x00; |
|
ICR1L |
= 0x00; |
|
TCCR1A = 0x00; |
|
|
TCCR1B = 0x09; |
//Таймер запускается в режиме CTC без предделителя |
|
} |
|
//частоты |
//Обработка прерывания по готовности АЦП:
#pragma interrupt_handler adc_isr:iv_ADC void adc_isr(void)
{ |
|
CLI(); |
//Запрет всех прерываний |
Uvh=ADCH; |
//Присвоение Uvh значения результата преобразования АЦП |
ADCSRA|=0x40; |
//Перезапуск АЦП |
SEI(); |
//Разрешение всех прерываний |
} |
|
//Обработка прерывания по совпадению таймера Т1:
#pragma interrupt_handler timer0_comp_isr:iv_TIM0_COMP void timer0_comp_isr(void)
{ |
|
CLI(); |
//Запрет всех прерываний |
PORTB=0x08; |
//Включение транзистора VT4 и отключение VT1 |
SEI(); |
//Разрешение всех прерываний |
} |
|
68
//Обработка прерывания по переполнению таймера Т0:
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF void timer0_ovf_isr(void)
{ |
|
CLI(); |
//Запрет всех прерываний |
PORTB=0x09; |
//Включение транзистора VT1 |
SEI(); |
//Разрешение всех прерываний |
} |
|
//Обработка внешнего прерывания INT0 импульсного датчика скорости:
#pragma interrupt_handler int0_isr:iv_INT0 void int0_isr(void)
{ |
|
|
|
|
CLI(); |
//Запрет всех прерываний |
|
||
pulse+=1; |
//Инкремент счетчика импульсов датчика скорости |
|||
SEI(); |
//Разрешение всех прерываний |
|||
} |
|
|
|
|
//Обработка прерывания по совпадению 16-разрядного таймера Т1: |
||||
#pragma interrupt_handler timer1_compa_isr:iv_TIM1_COMPA |
||||
void timer1_compa_isr(void) |
|
|
||
{ |
|
|
|
|
CLI(); |
|
//Запрет всех прерываний |
||
cycle_cnt+=1; |
|
//Счет числа циклов срабатывания Т1 |
||
if(cycle_cnt==100) |
//Когда cycle_cnt доходит до 100 (100 мс) |
|||
{ |
|
|
|
|
Uos=pulse; |
|
//Выполняется подсчет скорости |
||
Uos<<=2; |
|
|
|
|
pulse=0; |
|
//сбрасывается счетчик импульсов датчика скорости |
||
cycle_cnt=0; |
|
//сбрасывается счетчик циклов cycle_cnt |
||
delta=Uvh-Uos; |
//Вычисляется ошибка на входе регулятора скорости |
|||
delta_i=delta; |
|
|
|
|
if(Kp==0) |
|
Up=0; |
|
//Эта ошибка умножается на |
else if(Kp==1) |
|
Up=delta; |
|
//коэффициент пропорционального |
else if(Kp==2) |
|
Up=delta<<1 |
//усиления регулятора скорости |
|
else if(Kp==4) |
|
Up=delta<<2; |
|
|
else if(Kp==8) |
|
Up=delta<<3; |
|
|
else if(Kp==-1) |
Up=delta; |
|
|
|
else if(Kp==-2) |
Up=delta>>1; |
|
||
else if(Kp==-4) |
Up=delta>>2; |
|
||
else if(Kp==-8) |
Up=delta>>3; |
|
||
if(Ti==0) |
|
{delta_i=0;} |
//затем рассчитывается дискрета |
|
else |
|
{delta_i>>=(Ti-1);} //интегрирования |
||
if((PINA&0x04)==0x00) |
//Если сигнал разрешения убран |
|||
{ |
|
|
|
|
delta_i=0; |
|
|
//обнуляется интегральный канал |
|
Urs=Up; |
|
|
//регулятора скорости |
|
Urs_=0; |
|
|
|
|
} |
|
|
|
|
69
else //иначе
{
Urs=Up+delta_i+Urs_; //рассчитывается сигнал на выходе
Urs_=Urs-Up; |
//ПИ-регулятра скорости |
||
} |
|
|
|
if(Urs>=250) |
Urs=250; |
//Выполняется ограничение сигнала |
|
else if(Urs<=5) |
Urs=5; |
//на выходе регулятора |
|
OCR0=Urs; |
|
//и вывод результата на управление |
|
} |
|
|
//транзисторами |
SEI(); |
|
|
//Разрешение всех прерываний |
} |
|
|
|
//Функция инициализации периферийных устройств контроллера: |
|||
void init_devices(void) |
|
||
{ |
|
|
|
CLI(); |
|
//Запрет всех прерываний |
|
port_init(); |
//Вызов функции инициализации портов |
||
timer0_init(); |
//Вызов функции инициализации таймера Т0 |
||
timer1_init(); |
//Вызов функции инициализации таймера Т1 |
||
adc_init(); |
//Вызов функции инициализации АЦП |
||
MCUCR |
= 0x03; |
|
|
GICR |
= 0x40; |
//Разрешение внешнего прерывания INT0 |
|
TIMSK = 0x13; |
//Разрешение прерываний по совпадению Т0 и Т1 |
||
SEI(); |
|
//и по переполнению Т0 |
|
} |
|
|
|
//Главная функция программы:
void main(void) |
|
{ |
|
init_devices(); |
//Вызов функции инициализации устройств |
while(1) |
//Бесконечный цикл |
{ |
|
if((PINA&0x04)==0x04) |
//При подаче сигнала «Разрешение» |
{ |
|
TCCR0=0x4B; |
//Запуск таймера Т0 |
} |
|
else |
//иначе |
{ |
|
TCCR0=0x00; |
//Остановка таймера Т0 |
TCNT0=0x00; |
|
PORTB=0x00; |
//И выключение транзисторов |
} |
|
} |
|
} |
|
//------------------------------------------------------------------- |
|
$ .
1. $ $
7 , & $ :
70