Вт дек 25, 2018 17:13:16
Чт мар 28, 2019 08:13:33
//Настраиваем вывод таймера OC0A (PD6) на вывод
PORTD&= ~(1<<PIND6); //Значение по умолчанию 0.
DDRD|= (1<<DDD6); //Вывод PD6 - выход
//Настраиваем Таймер0
TCCR0A|= (1<<WGM01); //Выставляем режим CTC
TCCR0A|= (1<<COM0A0); //Инвертируем значение OC0A (PD6) по срабатыванию таймера.
OCR0A=0xFA; //Выставляем значение счетчика (к примеру 0xFA)
TCCR0B|= (1<<CS02)|(1<<CS00); //Ставим предделитель на значение 1024. CS02=1. CS00=1. Запускаем генерацию
Пн апр 01, 2019 18:33:07
Пн апр 01, 2019 18:53:40
Пн апр 01, 2019 18:58:55
// Для R (PB4), т.к. OCR1B аппаратно привязан к ней
TCCR1B = (1 << ICNC1) | (1 << WGM11); // phase correct PWM mode
OCR1B = 0x10; // initial PWM pulse width
TCCR1C = (1 << CS01); // clock source = CLK/8, start PWM
// Для R (PD5), т.к. OCR0B аппаратно привязан к ней
TCCR0B = (1 << FOC0A) | (1 << WGM02); // phase correct PWM mode
OCR0B = 0x10; // initial PWM pulse width
TCCR1C = (1 << CS01); // clock source = CLK/8, start PWM
Вт апр 02, 2019 01:54:24
// Для R (PB4), т.к. OCR1B аппаратно привязан к ней
TCCR1A = (1 <<COM1B1) | (1 << WGM11); // phase correct PWM mode ICR1
OCR1B = 0x10; // initial PWM pulse width
TCCR1B = (1 << WGM13)|(1 << CS11); // clock source = CLK/8, start PWM
// TCCR1B = (1 << ICNC1) | (1 << WGM11); // phase correct PWM mode
// OCR1B = 0x10; // initial PWM pulse width
// TCCR1C = (1 << CS01); // clock source = CLK/8, start PWM
Вт апр 02, 2019 21:36:28
Могли бы помочь через аппаратный (желательно, но можно и программный) ШИМ контроллера Attiny2313A сделать анимацию RGB-ленты (плавное перетекание цветов друг в друга, любое их смешивание, лишь бы плавное)? Схема, код, а также предпринимавшиеся действия описаны здесь.
Чт апр 04, 2019 14:30:40
Могли бы помочь через аппаратный (желательно, но можно и программный) ШИМ контроллера Attiny2313A сделать анимацию RGB-ленты (плавное перетекание цветов друг в друга, любое их смешивание, лишь бы плавное)? Схема, код, а также предпринимавшиеся действия описаны здесь.
Чт апр 04, 2019 17:46:29
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
int
main(void)
{
CLKPR = (1 << CLKPCE);
CLKPR = (0 << CLKPCE) | (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
DDRB = (0 << DDB7) | (0 << DDB6) | (0 << DDB5) | (1 << DDB4) | (1 << DDB3) | (1 << DDB2) | (0 << DDB1) | (0 << DDB0);
// Mode: Fast PWM top=0xFF
// OC0A output: Inverted PWM
// OC0B output: Disconnected
TCCR0A = (1 << COM0A1) | (1 << COM0A0) | (0 << COM0B1) | (0 << COM0B0) | (1 << WGM01) | (1 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (0 << CS00);
// Mode: Fast PWM top=0x00FF
// OC1A output: Inverted PWM
// OC1B output: Inverted PWM
TCCR1A = (1 << COM1A1) | (1 << COM1A0) | (1 << COM1B1) | (1 << COM1B0) | (0 << WGM11) | (1 << WGM10);
TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
OCR1AL = 200;
OCR1BL = 127;
OCR0A = 64;
// Analog Comparator: Off
ACSR = (1 << ACD) | (0 << ACBG) | (0 << ACO) | (0 << ACI) | (0 << ACIE) | (0 << ACIC) | (0 << ACIS1) | (0 << ACIS0);
// Main loop
while (1)
{
}
}
Сб ноя 23, 2019 21:04:41
Вс ноя 24, 2019 01:26:51
Чт ноя 28, 2019 19:47:48
// Подключение семисегментных индикаторов с помощью сдвигового регистра 74HC595.
// Простой частотометр на Attiny13.
#define F_CPU 9600000UL //
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned int edgecounter = 0, counter = 0, n;
// Обработчик прерывания по переполнению Т0, вызывается 4000 раз в секунду
ISR(TIM0_OVF_vect){
TCNT0 = 6; // Счетчик Т0 начинает считать с 6, т.к. 1MHz/(256-6) = 4000Hz
counter++;
}
// Обработчик внешнего прерывания
ISR(INT0_vect){ edgecounter++; }
// Массив значениий для семисегментного индикатора
char SEGMENTE[] = {
//--0-----1-----2-----3-----4-----5----6-----7-----8-----9----пусто
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00 };
// Функция вывода данных через регистр
void write_display(unsigned char *data, unsigned char nbytes) {
unsigned char mask,i;
for(i = 0; i < nbytes; i++) {
mask = 0x80;
for(char k = 0; k < 8; k++) {
// сравниваем каждый бит с единицей
if(data[i] & mask) {
PORTB |= (1 << PB0); // DATA 1
PORTB |= (1 << PB2); // CLK 1
PORTB &= ~(1 << PB2); // CLK 0
}
else {
PORTB &= ~(1 << PB0); // DATA 0
PORTB |= (1 << PB2); // CLK 1
PORTB &= ~(1 << PB2); // CLK 0
}
mask = mask >> 1; // сдвигаем биты
}
}
// защелкиваем регистр (Пин 12 на 74HC595)
PORTB |= (1 << PB1); // ST_CP
PORTB &= ~(1 << PB1);
}
int main(void)
{
DDRB = 0b00000111;
PORTB = 0x00; // Настраиваем входы/выходы
TCCR0B |= (1 << CS01); // Предделитель на 8, частота таймера 1 MHz
TIMSK0 |= (1 << TOIE0) ; // включение прерывания нулевого таймера по переполнению
GIMSK |= (1 << INT0); // Разрешаем внешнее прерывание на входе INT0
MCUCR |= (1 << ISC01)|(1 << ISC00); // Внешнее прерывание формируется по переднему фронту
//_delay_ms(20);
//---------
sei(); // Глобально разрешаем прерывания
unsigned char display[4];
while(1) {
// Выводим показания
if(counter == 4000){
//display[0] = SEGMENTE[(edgecounter/1000)];
//display[1] = SEGMENTE[((edgecounter/100)%10)];
//display[2] = SEGMENTE[((edgecounter/10)%10)];
//display[3] = SEGMENTE[(edgecounter%10)];
display[0] = SEGMENTE[(edgecounter/10)%10];
display[1] = SEGMENTE[8];
display[2] = SEGMENTE[9];
display[3] = SEGMENTE[6];
write_display(display,4);
counter = 0;
edgecounter = 0;
}
}
}
Пт ноя 29, 2019 04:24:26
Вс дек 22, 2019 18:04:04
/*----- ATtiny25/45/85 ---- F_CPU 8 MHz ----------*/
#define Prescaler_No (1<<CS00) //No prescaling)
#define Prescaler_8 (1<<CS01)
#define Prescaler_64 (1<<CS01)|(1<<CS00)
#define Prescaler_256 (1<<CS02)
#define Prescaler_1024 (1<<CS00)|(1<<CS02);
/*----------*/
#include "main.h"
volatile uint32_t ips = 0;
void INT0_init( void )//настройка внешнего прерывния INT0
{
GIMSK = (1<<INT0);//Разрешаем внешнее прерывание на входе INT0
MCUCR = (1 << ISC01); //Прерывание по восходящему фронту
};
void TIM0_COMPA_init(void ){
TCNT0 = 0; //Очищаем счетный регистр (на ваякий случай)
OCR0A = (256-1)-0;//Регистр сравнения, (256-1)-число
TCCR0A = (1<<WGM01);// Сброс при совпадении.
TIFR = (1<<OCF0A); // Регистр флагов прерываний таймера счетчика // clear any pending interrupts;
TIMSK = (1<<OCIE0A); //Разрешение прерывания по совпадению таймера/счётчика 0A
TCCR0B = Prescaler_1024;// Делитель частоты
};
ISR(INT0_vect)//External Interrupt
{
ips++;// На порт PB2 подаем импульсы _П_П_П_П_П_
};
ISR(TIM0_COMPA_vect)//прерывание по совпадению
{
MAX7219_display_number(ips);//выводим на дисплей цифры
ips=0;
};
int main (void)
{
DDRB = 0xFF; // configure PORTB as output
PORTB_OUT(4); // Настраиваем 4 пин порта B на выход
PORTB_IN(2);
MAX7219_init();
MAX7219_set_intensity(8);
INT0_init();
TIM0_COMPA_init();
sei();// Разрешить глобальные прерывания
while (1){ /*-----*/ }
return 0;
};
/* Счетчик импульсов. ATtiny25/45/85 F_CPU 8 MHz.
Подаём на PB2 импульсы с частотой 50 kHz
На индикаторе получаем;
50000/(8000000/1024/255) = 1632
фактическое значение = 1614
*/
Пн дек 23, 2019 05:26:32
Пн дек 23, 2019 12:24:18
Пн дек 23, 2019 20:15:57
Вт дек 24, 2019 10:24:04
Ср дек 25, 2019 19:08:39
; объявляем регистр флагов
.def flags = R19 ; различные флаги
; объявляем флаг
.equ timer2_ready = 4 ; таймер отработал заданное время
; объявляем "старший байт" таймера2
.def count_256 = R20 ; старший байт для Таймера2, счетчик "полных оборотов" таймера
; объявляем регистры, где будет находится требуемое время таймера (задержка)
.def delayL = R21 ; задержка, младший байт
.def delayH = R22 ; задержка, старший байт
; прерывание таймера2, режим СТС
timer2_CTC:
; сохраним регистры, которые использует прерывание
sbrc flags, timer2_ready
; если задержка выполнена, то идем на выполнение "тела" прерывания
rjmp work
; тестируем байты задержки
test_delay:
; проверяем старший байт на ноль
tst delayH
; если старший байт задержки равен нулю, то сразу идем на задание младшего байта задержки
breq set_delayL
; сравним счетчик "полных оборотов" со старшим байтом задержки
cp count_256, delayH
; если меньше, то идем на задание "полного оборота"
brlo set_256
; счетчик "полных оборотов" стал равен старшему байту, проверяем младший байт на ноль
tst delayL
; если младший байт равен нулю, то задержка состоит только из старшего байта и выполнена полностью
; поэтому идем на выполнение "тела" прерывания
breq work
; иначе сбрасываем счетчик "полных оборотов"
clr count_256
; и идем на задание младшего байта задержки
rjmp set_delayL
; задание "полного оборота"
set_256:
; увеличиваем счетчик "полных оборотов"
inc count_256
ser R16
; задаем 255 - "полный оборот"
out OCR2, R16
; и выходим из прерывания
rjmp end_timer2
; задание младшего байта задержки
set_delayL:
out OCR2, delayL
; поставим бит (флаг), что задержка выполнена. точнее, будет выполнена после отработки младшего байта
sbr flags, 1<<timer2_ready
; конец прерывания таймера2
end_timer2:
; восстановим регистры, которые использует прерывание
reti
work:
; сбросим бит (флаг) готовности задержки
cbr flags, 1<<timer2_ready
; "тело" прерывания
; идем на задание задержки для следующего цикла таймера
rjmp test_delay
Ср дек 25, 2019 19:14:31