Пн окт 05, 2020 13:29:56
//#define F_CPU (9600000uL)
#include "stdint.h"
#include "avr/io.h"
#include "avr/interrupt.h"
#include "util/delay.h"
#include "stdbool.h"
// вспомогательные общие макросы
#define _CONCAT_(x,y) x ## y
/// вспомогательный макрос слияния символов
#define CONCAT(y,x) _CONCAT_(y,x)
// таймеры
// предделители тактовой
#define TIMER_CLK_DIV_1 1
#define TIMER_CLK_DIV_8 2
#define TIMER_CLK_DIV_64 3
#define TIMER_CLK_DIV_256 4
#define TIMER_CLK_DIV_1024 5
#define TIMER_CLK_EXT_FALL 6
#define TIMER_CLK_EXT_RISE 7
#define TIMER_CLK_DIV(x) CONCAT(TIMER_CLK_DIV_,x)
/// предделитель таймера
#define TMR_DIV 8
#define MAX_P 200
#define PHASE_STEP 5
#define MIN_P PHASE_STEP
#define PHASE_OFF (MAX_P + PHASE_STEP)
/// рабочий порт дл¤ выхода на симистор
#define OUTPORT PORTB
/// выходной пин порта дл¤ управлени¤ симистором
#define OUT_PIN _BV(PB0)
/// ”становка сброса дл¤ режима —“—
#define CTC (F_CPU/TMR_DIV/MAX_P/100)
#define noinit __attribute__((section(".noinit")))
/// счетчик для регулирования фазы
volatile uint8_t COUNTER;
/// текущая фаза отпирания симистора
volatile noinit uint8_t out_phase;
/// заданная фаза отпирания симистора
volatile noinit uint8_t sel_phase;
/// флажок включения нагрузки
volatile noinit uint8_t on;
/// длительность выходного импульса управлени¤ симистором 4*50=200us
#define PULSE_LEN 4
/// действие по совпадению канала ј
#define do_comp_A() OUTPORT |= OUT_PIN
/// действие по совпадению канала ¬
#define do_comp_B() OUTPORT &= ~OUT_PIN
#define STARTUP_DELAY 20
#define PULSE_TRIAC 200
#define pwm1_on() { PORTB |= (1<<PB0); }
#define pwm1_off(){ PORTB &= ~(1<<PB0); }
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (1<<ADLAR))
// Read the 8 most significant bits
// of the AD conversion result
uint8_t read_adc(void)
{
// Start the AD conversion
ADCSRA|=(1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCH;
}
/** Прерывание таймера по совпадению канала А.
* Таймер настроен так, что прерывание возникает 200 раз в полупериод сети. 50us
* Обработчик реализует виртуальные регистры совпадения для фазового регулирования.
*/
ISR(TIM0_COMPA_vect)
{
COUNTER++;
// виртуальный регистр совпадения для включения импульса
if(COUNTER == out_phase){
do_comp_A();
}
// виртуальный регистр совпадения для выключения импульса
if(COUNTER == (out_phase + PULSE_LEN)){
do_comp_B();
}
}
/** Прерывание по изменению состояния синхро-пина.
* Возникает по фронту и спаду синхроимпульса, т.е. 100 раз в секунду
* Реализует синхронизацию с сетью.
*/
ISR(PCINT0_vect)
{
COUNTER = 0; // обнуляем счетчик таймера
OUTPORT &= ~OUT_PIN; // выключаем на всякий случай выход
if(on){
// если включено - плавно приближаем текущую фазу к заданной
if(sel_phase > out_phase){
out_phase++;
} else if(sel_phase < out_phase){
out_phase--;
} else if(sel_phase == out_phase) on = 0;
} else out_phase = sel_phase;
}
int main(void){
// Declare your local variables here
// Crystal Oscillator division factor: 1
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
// Input/Output Ports initialization
// Port B initialization
// Function: Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
DDRB=(0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0);
// State: Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0
PORTB=(0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B = TIMER_CLK_DIV(TMR_DIV); // делитель таймера
TCNT0=0x00;
OCR0A = CTC; // порог сброса
OCR0B=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);
// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: On
GIMSK=(0<<INT0) | (1<<PCIE);
MCUCR=(0<<ISC01) | (0<<ISC00);
PCMSK=(0<<PCINT5) | (0<<PCINT4) | (0<<PCINT3) | (1<<PCINT2) | (0<<PCINT1) | (0<<PCINT0);
GIFR=(0<<INTF0) | (1<<PCIF);
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIS1) | (0<<ACIS0);
DIDR0=(0<<AIN0D) | (0<<AIN1D);
// ADC initialization
// ADC Clock frequency: 75,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: Free Running
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0|=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
ADMUX = 3 | ADC_VREF_TYPE;
out_phase = MAX_P;
// Global enable interrupts
sei();
on = 1;
while (1)
{
// Place your code here
sel_phase = ((read_adc()*MAX_P) / 255);
}
}
if(on){
// если включено - плавно приближаем текущую фазу к заданной
if(sel_phase > out_phase){
out_phase++;
} else if(sel_phase < out_phase){
out_phase--;
} else if(sel_phase == out_phase) on = 0;
} else out_phase = sel_phase;
// если включено - плавно приближаем текущую фазу к заданной
if(sel_phase > out_phase){
out_phase++;
} else if(sel_phase < out_phase){
out_phase--;
}
//#define F_CPU (9600000uL / 8)
#include "stdint.h"
#include "avr/io.h"
#include "avr/interrupt.h"
#include "util/delay.h"
#include "stdbool.h"
bool pusk, err;
volatile uint8_t pwm_set;
volatile uint8_t pwm_temp;
#define STARTUP_DELAY 20
#define PULSE_TRIAC 200
#define pwm1_on() { PORTB |= (1<<PB0); }
#define pwm1_off(){ PORTB &= ~(1<<PB0); }
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (1<<ADLAR))
// Read the 8 most significant bits
// of the AD conversion result
uint8_t read_adc(void)
{
// Start the AD conversion
ADCSRA|=(1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCH;
}
ISR(TIM0_COMPA_vect)
{
if(!err) pwm1_on();
_delay_us(PULSE_TRIAC);
pwm1_off();
err = 1;
}
ISR(PCINT0_vect)
{
err = 0;
TCNT0 = pwm_set;
}
int main(void){
// Declare your local variables here
// Crystal Oscillator division factor: 1
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
// Input/Output Ports initialization
// Port B initialization
// Function: Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
DDRB=(0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0);
// State: Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0
PORTB=(0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 18,750 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 9,9733 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0xBA; // 0xBA - 9.6MGz / 8
OCR0B=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);
// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: On
GIMSK=(0<<INT0) | (1<<PCIE);
MCUCR=(0<<ISC01) | (0<<ISC00);
PCMSK=(0<<PCINT5) | (0<<PCINT4) | (0<<PCINT3) | (1<<PCINT2) | (0<<PCINT1) | (0<<PCINT0);
GIFR=(0<<INTF0) | (1<<PCIF);
// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIS1) | (0<<ACIS0);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR0=(0<<AIN0D) | (0<<AIN1D);
// ADC initialization
// ADC Clock frequency: 75,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: Free Running
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0|=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
ADMUX = 3 | ADC_VREF_TYPE;
pwm_temp = ((read_adc()*0xBA) / 255);
pusk = 0; pwm_set=0; err=0;
// Global enable interrupts
sei();
while (1)
{
// Place your code here
if(!pusk) {
for(uint8_t i=0; i<pwm_temp; i++)
{
pwm_set++;
_delay_ms(STARTUP_DELAY);
}
pusk = 1;
} else {
pwm_set = ((read_adc()*0xBA) / 255);
}
}
}
Пн окт 05, 2020 13:44:47
Ср окт 07, 2020 14:28:24
вот код ARV
еще вам один вариант
Ср окт 07, 2020 14:54:42
В протеусе все работает как надо.Serzh2000 писал(а):в принципе в протеусе это тоже видно..
F_CPU (9600000uL)
F_CPU (9600000uL / 8)
Ср окт 07, 2020 15:39:48
Ср окт 07, 2020 16:00:09
Ср окт 07, 2020 17:27:23
Чт окт 08, 2020 11:15:26
Чт окт 08, 2020 15:14:56
Пт окт 09, 2020 06:58:20
Пн дек 13, 2021 13:42:40
Пн дек 13, 2021 18:10:59
я про U2010B
Вт дек 14, 2021 02:32:45
Вт дек 14, 2021 13:19:44
Ср дек 15, 2021 11:41:48
Ср дек 15, 2021 19:08:33
режиме работы контакт 13 переключается на -VS (контакт 11) и контакт 6 на GND (контакт 10) после того, как V6 достигает порога VT100. Конденсатор плавного пуска закорачивается, а угол управления переключается на αmax. Это положение сохраняется до тех пор, пока напряжение питания не отключится. При повторном включении питания двигатель можно снова запустить с функцией плавного пуска. Поскольку состояние перегрузки переключает контакт 13 на контакт 11, можно использовать меньший угол управления, αmax, путем подключения дополнительного сопротивления между контактами 13 и 14.
Чт дек 16, 2021 20:41:28
Ср янв 03, 2024 14:37:21
Ср янв 03, 2024 14:50:40
Ср янв 03, 2024 15:28:42