Вс окт 08, 2023 08:15:34
Пн окт 09, 2023 07:47:08
Пн май 27, 2024 19:35:40
Пн май 27, 2024 20:34:42
Пн май 27, 2024 21:19:16
//настройка прерывания TC0
cli(); //выключаем возможное прерывание по переполнению TC0 (работает для millis и micros из chrono.cpp)
TIFR0 = (1<<TOV0); //reset flag int of overflow
OCR0A = 0xF9;
TIMSK0 |= (1 << OCIE0A); //TC0 Output Compare Match A Interrupt Enable (only interrupt, no OC0A pin toggle)
sei();
//прерывание по сравнению значения TC0
ISR (TIMER0_COMPA_vect)
{
//do some...
ADCSRA |= (1<<ADSC); //start conversion
while (ADCSRA & (1<<ADSC)); //wait for conversion to complete
//do some...
}
Пн май 27, 2024 22:07:23
вот эта фраза меня немного в заблуждение ввела.timex писал(а):таймер0 настроен на прерывание по переполнению каждые 8 мкС (125 кГц) (8 МГц / 64);
Вт май 28, 2024 15:05:34
остальные таймеры заняты другими вещами..
хотелка: АЦПировать с частотой в 500 Гц
Ср май 29, 2024 17:53:26
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
//#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 250))
Ср май 29, 2024 21:23:51
Чт май 30, 2024 04:15:25
Да. Сначала TIMER0 COMPA, затем TIMER0 OVF.timex писал(а):...они будут выполнятся оба, согласно их приоритетам, верно?
Чт май 30, 2024 08:59:40
В принципе, верно, если сравнение попадает в период пересчета таймера.timex писал(а):по-идее сначала возникнет прерывание по сравнению (и не важно, успеем ли из него выйти по RETI или нет), а следующим (через 7 тактов, т.к. 256-249=7) возникнет прерывание по переполнению, верно?
Согласно их очередности возникновения. Если же в процесе выполнения обработчика прерывания возникает несколько других прерываний - то да, они будут выполняться согласно их приоритетности, определенной таблицей прерываний. Т.е. чем меньше номер прерывания, тем выше приоритет. И этот приоритет в 8-битных классических АВРках не редактируется.они будут выполнятся оба, согласно их приоритетам, верно?
уважаемая...timex писал(а):спасибо, уважаемый
Чт июн 06, 2024 11:10:11
.include "m32def.inc"
; Определение констант для таймера
.def counter = r16
.def temp = r17
.equ F_CPU = 8000000 ; Частота процессора 8 МГц
.equ DELAY = F_CPU/1024 ; Делитель для 1 секунды
.org 0x00
rjmp init
.org OVF1addr
rjmp timer_interrupt
init:
; Инициализация стека
ldi temp, low(RAMEND)
out SPL, temp
ldi temp, high(RAMEND)
out SPH, temp
; Инициализация портов
ldi temp, 0x00
out DDRA, temp ; Порты A на ввод
ldi temp, 0xFF
out DDRC, temp ; Порты C на вывод
ldi temp, 0xFF
out DDRB, temp ; Порты B на вывод
; Начальное значение счетчика
ldi counter, 9
out PORTC, counter
; Разрешить прерывания
sei
main_loop:
; Проверка нажатия кнопки
sbis PINA, 0
rcall start_timer
rjmp timer_interrupt
start_timer:
; Настройка таймера для задержки в 1 секунду
ldi temp, high(DELAY)
out TCNT1H, temp
ldi temp, low(DELAY)
out TCNT1L, temp
ret
timer_interrupt:
; Уменьшение счетчика и обновление индикатора
dec counter
out PORTC, counter
cpi counter, 0
brne timer_interrupt
; Включение светодиода
sbi PORTB, 0
reti
Пт июн 07, 2024 05:35:50
.include "m32def.inc"
; Определение констант для таймера
.def counter = r16
.def temp = r17
.equ F_CPU = 8000000 ; Частота процессора 8 МГц
.equ DELAY = F_CPU/1024 ; Делитель для 1 секунды
.org 0x00
rjmp init
.org $000E
rjmp timer_interrupt
init:
; Инициализация стека
ldi temp, low(RAMEND)
out SPL, temp
ldi temp, high(RAMEND)
out SPH, temp
; Инициализация портов
ldi temp, 0x00
out DDRA, temp ; Порты A на ввод
SBI PORTA,0 ;включить подтяжку кнопки
ldi temp, 0xFF
out DDRC, temp ; Порты C на выводPINA 0 25
ldi temp, 0xFF
out DDRB, temp ; Порты B на вывод
; Начальное значение счетчика
ldi counter, 9
out PORTC, counter
start_timer:
; Настройка таймера для задержки в 1 секунду
LDI R22,HIGH(DELAY)
OUT OCR1AH,R22
LDI R22,LOW(DELAY)
OUT OCR1AL,R22
LDI R22,1<<OCIE1A
OUT TIMSK,R22
LDI R22,1<<WGM13|1<<WGM12 ;CTC
OUT TCCR1B,R22
; SBR R22,1<<CS10 ;F_CPU/1
SBR R22,1<<CS12|1<<CS10 ;F_CPU/1024
; Разрешить прерывания
sei
main_loop:
; Проверка нажатия кнопки
sbic PINA, 0
rjmp main_loop
CBI PORTB,0 ;выключить светик
OUT TCCR1B,R22
SBIS PORTB,0
RJMP PC-1
sbis PINA, 0
rjmp PC-1
RJMP INIT
;*************************************************
timer_interrupt:
; Уменьшение счетчика и обновление индикатора
dec counter
out PORTC, counter
BRNE OUT_TIME
; Включение светодиода
sbi PORTB, 0
OUT_TIME:
reti
.exit
Пт июн 07, 2024 16:09:47
Вт июл 23, 2024 21:04:40
/* ATmega328P AtmelStudio -std=c++14 */
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include "src\GPIO.h"
GPIO<PIN::PinD2> INT_0;
GPIO<PIN::PinD3> INT_1;
GPIO<PIN::PinC0> ss0;
GPIO<PIN::PinC1> ss1;
GPIO<PIN::PinC2> ss2;
GPIO<PIN::PinC3> ss3;
GPIO<PIN::MOSI> mosi;
GPIO<PIN::MISO> miso;
GPIO<PIN::SCK> sck;
uint16_t transfer16(uint16_t data);
volatile size_t k;
ISR(INT0_vect) {
k = 0;
}
volatile uint16_t p = 3000;
ISR(INT1_vect) {
switch(k) {
case 0: {
ss0.write(0);
transfer16(p);
ss0.write(1);
break;}
case 1: {
ss1.write(0);
transfer16(p);
ss1.write(1);
break;}
case 2: {
ss2.write(0);
transfer16(p);
ss2.write(1);
break;}
case 3: {
ss3.write(0);
transfer16(p);
ss3.write(1);
break;}
}
k++;
}
//================
int main(void){
cli();
ss0.output(); ss0.write(1);
ss1.output(); ss1.write(1);
ss2.output(); ss2.write(1);
ss3.output(); ss3.write(1);
mosi.output(); mosi.write(0);
miso.input(), miso.pullup();
sck.output(); sck.write(0);
/**/
// SPI2X SPR1 SPR0 Тактовая частота SCK
// 1 0 0 fosc/2
// 0 0 0 fosc/4
// 1 0 1 fosc/8
// 0 0 1 fosc/16
// 1 1 0 fosc/32
// 0 1 0 fosc/64
// 1 1 1 fosc/64
// 0 1 1 fosc/128
// ---------- fosc/8 ->
// SPIE
// |SPE
// ||DORD
// |||MSTR
// |||| CPOL
// |||| |CPHA
// |||| ||SPR1
// |||| |||SPR0
// |||| ||||
SPCR = 0b0101'0001;
SPSR |= (1 << SPI2X);
//SPSR &= ~(1 << SPI2X);
INT_0.input(); INT_0.pullup();
INT_1.input(); INT_1.pullup();
EIMSK |= (1<<INT1)|(1<<INT0);
EICRA |= (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00); // Нарастающий фронт INT1, INT0 генерирует прерывание.
sei();
while (1){
}
return 0;
}
// =============
uint16_t transfer16(uint16_t data) {
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
in.val = data;
if ( !( SPCR & (1 << DORD) ) ) {
SPDR = in.msb;
asm volatile("nop");
while (!(SPSR & (1 << SPIF))) ;
out.msb = SPDR;
SPDR = in.lsb;
asm volatile("nop");
while (!(SPSR & (1 << SPIF))) ;
out.lsb = SPDR;
} else {
SPDR = in.lsb;
asm volatile("nop");
while (!(SPSR & (1 << SPIF))) ;
out.lsb = SPDR;
SPDR = in.msb;
asm volatile("nop");
while (!(SPSR & (1 << SPIF))) ;
out.msb = SPDR;
}
return out.val;
}
//============
/* ATtiny88 AtmelStudio -std=c++14 */
#define F_CPU 1000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include "D:\lib\SPI\SPI.hpp"
GPIO<PIN::PinD5> jet;
// SPIE
// |SPE
// ||DORD
// |||MSTR
// |||| CPOL
// |||| |CPHA
// |||| ||SPR1
// |||| |||SPR0
enum {// |||| ||||
spcr = 0b1100'0000 };
SPI spiSlave( spcr );// spi2x = 0
volatile uint16_t duration_us;
ISR(SPI_STC_vect){
duration_us = spiSlave.transfer<uint16_t>(0);
jet.pulseMicroseconds(duration_us);
}
int main(void) {
jet.output();
jet.write(0);
sei(); // enable interrupts
while (1) { }
return 0;
}
//==========
// Генериравание импульса заданной ширины в микросекундах.
// Прерывания отключены во время генерации импульса.
void pulseMicroseconds(uint16_t us){
if( us == 0 ){ return; }
uint8_t sreg = SREG; // F_CPU >= 1000000
__asm__ __volatile__("cli" ::: "memory"); //
sfr->pin |= MASK;
delayMicroseconds(us);
sfr->pin |= MASK;
SREG = sreg; //
__asm__ __volatile__("" ::: "memory"); //
};
// задерживает указанное количество микросекунд
// работает для тактовой частоты 1 MHz и выше
__attribute((always_inline))
static inline void delayMicroseconds(uint16_t us){
// if us is a compile-time constant result is accurate to 1 cycle
if (__builtin_constant_p(us)) {
_delay_us(us);
return;
}
// when us is not known at compile time, delay is accurate to +/- 2us
// plus an overhead of 3 CPU cycles
// когда us неизвестен во время компиляции, задержка составляет +/- 2us
// плюс накладные расходы в 3 цикла процессора
const float fMHz = (F_CPU/1000000.0);
// subtract two for rounding before dividing by 4
// вычтите два для округления перед делением на 4
us -= 2;
delay4us:
// delay 4us per loop, less 4 cycles for overhead
// задержка 4 мкс на цикл, минус 4 цикла накладных расходов
_delay_us(4.0 - (4.0 / fMHz));
asm volatile ("sbiw %[us], 4" : [us]"+w"(us));
asm goto( "brpl %l[delay4us]" :::: delay4us);
}
Чт июл 25, 2024 11:28:30
Чт июл 25, 2024 16:13:23
если не знаешь, как пишется слово, посмотри в словаре.Эйлер Леонард писал(а):инкриминирует
Чт июл 25, 2024 20:58:18
Пт июл 26, 2024 00:35:50
Вт июл 30, 2024 21:05:39
/* ATtiny88 AtmelStudio -std=c++14 */
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include "D:\lib\MegaCore\corefiles\HardwareSerial.h"
#include "D:\lib\SPI\SPI.hpp"
#include "micros2.h"
#include "D:\lib\pin\GPIO.hpp"
GPIO<PIN::PinC0> jet0;
GPIO<PIN::PinC1> jet1;
GPIO<PIN::PinC2> jet2;
GPIO<PIN::PinC3> jet3;
GPIO<PIN::PinD2> INT_0;
GPIO<PIN::PinD3> INT_1;
void INT1_interrupt_attach( void (*funcPtr)(void) );
void (*INT1_interruptCallback)(void);
static void positionCheck(void);
static void Action_4Jet(uint16_t d);
volatile uint16_t duration_us = 0;//8000
volatile uint32_t lastTime0, lastTime1, lastTime2, lastTime3;
ISR(INT0_vect) {
GPIOR0 = 0;
}
ISR(INT1_vect) {
if(!!duration_us){
INT1_interruptCallback();
}
GPIOR0++;
}
// SPIE
// |SPE
// ||DORD
// |||MSTR
// |||| CPOL
// |||| |CPHA
// |||| ||SPR1
// |||| |||SPR0
enum {// |||| ||||
spcr = 0b1100'0000 };
SPI spiSlave( spcr );// spi2x = 0
ISR(SPI_STC_vect){
duration_us = spiSlave.transfer<uint16_t>(0);
Serial.println(duration_us);
}
// ISR Handlers
ISR(TIMER2_COMPA_vect) {
microseconds += micros_resolution;
if(interruptCallback){
interruptCallback(duration_us);
}
}
int main(void){
Serial.begin(57600);//
while(!Serial);
Serial.println("== TEST Slave ==");
jet0.output(); jet0.write(0);
jet1.output(); jet1.write(0);
jet2.output(); jet2.write(0);
jet3.output(); jet3.write(0);
INT_0.input(); INT_0.pullup();
INT_1.input(); INT_1.pullup();
EIMSK |= (1<<INT1)|(1<<INT0); // Разрешение прерывания на входе INT0, INT1
EICRA |= (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00); // Нарастающий фронт INT1, INT0 генерирует прерывание.
INT1_interrupt_attach(positionCheck);
micros_interrupt_attach(Action_4Jet);
micros_init(F_CPU, 100);
while(1){ }
return 0;
}
// ==
static void Action_4Jet( uint16_t d_us ){
if( (micros_get() - lastTime0) >= d_us ){
lastTime0 = micros_get();
jet0.write(0);
}
if( (micros_get() - lastTime1) >= d_us ){
lastTime1 = micros_get();
jet1.write(0);
}
if( (micros_get() - lastTime2) >= d_us ){
lastTime2 = micros_get();
jet2.write(0);
}
if( (micros_get() - lastTime3) >= d_us ){
lastTime3 = micros_get();
jet3.write(0);
}
}
// ==
static void positionCheck(void){
switch(GPIOR0) {
case 0: {
lastTime0 = micros_get();
jet0.write(1);
break;}
case 1: {
lastTime1 = micros_get();
jet1.write(1);
break;}
case 2: {
lastTime2 = micros_get();
jet2.write(1);
break;}
case 3: {
lastTime3 = micros_get();
jet3.write(1);
break;}
}
}
// ==
void INT1_interrupt_attach( void (*funcPtr)(void) ){
INT1_interruptCallback = funcPtr;
}
#ifndef MICROSJET_H
#define MICROSJET_H
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <util/atomic.h>
// Timer2
#if F_CPU > 1000000 // 1MHz - 20MHz
#define CLOCKSEL (1 << CS21)
#define MICROS_PRESCALER 8
#elif F_CPU >= 125000 // 125KHz - 1MHz
#define CLOCKSEL (1 << CS20)
#define MICROS_PRESCALER 1
#else
#error "F_CPU out of range."
#endif
void micros_init(uint32_t f_cpu, uint16_t resolution);
uint32_t micros_get(void);
void micros_resume(void);
void micros_pause(void);
void micros_reset(void);
void micros_add(uint32_t us);
void micros_subtract(uint32_t us);
void micros_interrupt_attach( void (*funcPtr)(uint16_t) );
// ============ implementation ============
// GLOBAL VARIABLES
// Ошибка калибровки. Отрицательное или положительное число
// которое будет добавлено или вычтено из значения регистра таймера.
enum err { MICROS_ERR_CAL = 0 };
// тип (*имя_указателя)(типы_параметров);
void (*interruptCallback)(uint16_t);
volatile uint32_t microseconds;
static uint16_t micros_resolution;
void micros_init(uint32_t f_cpu, uint16_t resolution ){// Timer settings
micros_resolution = resolution; // разрешение
// Clear registers
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = 0;
TCCR2A |= (1 << WGM21); // CTC
TCCR2B |= CLOCKSEL; // Prescaler 8
TIMSK2 |= (1 << OCIE2A); // Output Compare Match A Interrupt Enable
OCR2A = (f_cpu / MICROS_PRESCALER / (1000000 / resolution)) + MICROS_ERR_CAL - 1;
sei(); // enable Global Interrupts
}
// Returns current microseconds
// Возвращает текущие миллисекунды
uint32_t micros_get(){
uint32_t ms;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
ms = microseconds;
}
return ms;
}
// Turn on timer and resume time keeping
// Включите таймер и возобновите отсчет времени
void micros_resume(){
TIMSK2 |= (1 << OCIE2A);
TCCR2B = CLOCKSEL;
power_timer2_enable();
}
// Pause time keeping and turn off timer to save power
// Приостановите отсчет времени и выключите таймер для экономии энергии
void micros_pause(){
TIMSK2 &= ~(1 << OCIE2A);
TCCR2B = 0;
power_timer2_disable();
}
// Reset microseconds count to 0
// Сбросить счетчик миллисекунд до 0
void micros_reset(){
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
microseconds = 0;
}
}
// Add time
// Добавить время
void micros_add(uint32_t ms){
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
microseconds += ms;
}
}
// Subtract time
// Вычесть время
void micros_subtract(uint32_t ms){
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
microseconds -= ms;
}
}
// Attach a custom function to timer interrupt
// Прикрепите пользовательскую функцию к прерыванию таймера
void micros_interrupt_attach( void (*funcPtr)(uint16_t) ){
interruptCallback = funcPtr;
}
#endif // MICROSJET_H