Перегляньте відео нижче, щоб дізнатися, як встановити наш сайт як веб-програму на головному екрані.
Замітка: This feature may not be available in some browsers.
Вооружайся книгой комрадов Хоровца и Хилла и вперед. Дальше в зависимости от направления можно еще путевой литературы почитать, ну и вопросов по задавать, главное помнить о том, что правильно поставленный вопрос - уже половина ответа[emoji1]чуток увлекся радиоэлектроникой. Подскажите в харькове может курсы какие где есть ?)
Подскажите, что это за деталь?
Чото мозги у меня уже закипают. Такая с первого взгляда чудесная студия порет полній бред. 100% робочий код не пашет. Написал в кодвижене, перекинул туда заменив типы данных и прочую мелочь. Это **** какая-то.
#include <avr/interrupt.h>
#include <stdbool.h>
#include <inttypes.h>
#define oSOLENOID_OFF PORTD |= 0x04 // PD2 high
#define oSOLENOID_ON PORTD &= ~0x04 // PD2 low
#define TIMER_ENABLE WDTCSR = (1<<WDIF); WDTCSR = (1<<WDIE)
#define TIMER_DISABLE WDTCSR &= ~(1<<WDIE)
#define PLUS 1
#define MINUS 0
#define HOURS 14
#define MINUTES 25
#define COR_STANDART 40
#define COR_FIRST 10
#define COR_DIRRECTION PLUS
#define TICK_TIMER 197
#define PRESET 1
uint16_t uiPulseTicks = 0;
int8_t cCorrectionFlag = -1;
uint8_t ucTimer = 25;
uint8_t ucSeconds = 55;
uint8_t ucTmpCounter;
bool bMinuteFlag = false;
uint8_t ucMinutes = MINUTES;
uint8_t ucHours = HOURS;
uint8_t ucCorDir = COR_DIRRECTION;
uint8_t ucCorSeconds = COR_STANDART;
uint8_t ucFCorSeconds = COR_FIRST;
uint16_t uiTickTimer = TICK_TIMER;
uint16_t table[] = { 14, 1, 250,
14, 2, 250,
14, 3, 250,
14, 4, 250,
14, 5, 255,
14, 6, 250,
14, 7, 250,
14, 8, 250,
14, 9, 250,
14, 10, 250,
14, 11, 250,
14, 12, 250,
14, 13, 250,
14, 14, 250,
14, 15, 255,
14, 16, 250,
14, 17, 250,
14, 18, 250,
14, 19, 250,
14, 20, 250,
14, 21, 250,
14, 22, 250,
14, 23, 250,
14, 24, 250
};
int main(void)
{
unsigned int i;
PIND |= (1<<PD2); // PD2 out
PORTD |= (1<<PD1);; // pull up for PD1
oSOLENOID_OFF;
for(i=0xffff; i>0; i--);
oSOLENOID_ON;
for(i=0xffff; i>0; i--);
oSOLENOID_OFF;
for(i=0xffff; i>0; i--);
oSOLENOID_ON;
for(i=0xffff; i>0; i--);
oSOLENOID_OFF;
for(i=0xffff; i>0; i--);
oSOLENOID_ON;
for(i=0xffff; i>0; i--);
oSOLENOID_OFF;
// TIMER0
TCCR0A = 0x00;
TCCR0B = 0x03; //prescaller clk/1024
TCNT0 = 0xB1; //5ms interrupt on ovf
TIMSK0 = 0x01; //OVF Interrupt Enabled
PCICR = 0x04; // PCINT 2 channel( e_ints 16-23) ON.
// Our IN 31st pin PD1 is PCINT17.
WDTCSR |= (1<<WDCE) | (1<<WDE); // setting WDT to interrupt every 8sec
WDTCSR = (1<<WDP3) | (1<<WDP0);
sei();
while(1)
{
if(bMinuteFlag)
{
bMinuteFlag = false;
for(ucTmpCounter=0; ucTmpCounter<sizeof(table)/6; ucTmpCounter++)
{
if(table[ucTmpCounter*3] == ucHours)
{
if(table[ucTmpCounter*3 + 1] == ucMinutes)
{
oSOLENOID_ON;
uiPulseTicks += table[ucTmpCounter*3 + 2] *2;
PCIFR |= (1<<PCIF2); // clear PCINT2 flag
PCMSK2 |= (1<<PCINT17); // turn on PCINT17
break;
}
}
}
if(ucHours == 14)
{
if(ucMinutes == 3)
{
if(cCorrectionFlag)
{
if(cCorrectionFlag > 0)
{
if(ucCorDir) ucSeconds = ucCorSeconds;
else
{
ucSeconds = 60 - ucCorSeconds;
ucMinutes--;
}
}
else
{
if(ucCorDir) ucSeconds = ucFCorSeconds;
else
{
ucSeconds = 60 - ucFCorSeconds;
ucMinutes--;
}
}
cCorrectionFlag = 0;
TIMER_ENABLE;
}
}
}
}
}
}
ISR(PCINT2_vect)
{
if(uiPulseTicks > 0) uiPulseTicks--;
else
{
oSOLENOID_OFF;
PCMSK2 &= ~(1<<PCINT17); // turn off PCINT17
}
}
ISR(TIMER0_OVF_vect)
{
TCNT0 = 0xB1; //5ms interrupt on ovf
if(uiTickTimer > 0) uiTickTimer--;
else
{
uiTickTimer = TICK_TIMER;
ucSeconds++;
if(ucSeconds > 59)
{
ucSeconds = 0;
ucMinutes++;
bMinuteFlag = true;
if(ucMinutes > 59)
{
ucMinutes = 0;
ucHours++;
if(ucHours > 23) ucHours = 0;
}
}
}
}
ISR(WDT_vect) // wdt interrupt routline, happens every 8 sec.
{
ucTimer--;
if(!ucTimer)
{
TIMER_DISABLE;
ucTimer = 25;
cCorrectionFlag = 1;
}
}
Все в скинуто в кучу дабы избежать возможных проблем с переназначением переменных и прочей чепухи.
Оно работает в cvavr, но перенесенное в студию з лишь заменой типов данных int -> int16_t и добавлением библиотек с интами и булами, а так же с макросами ISR - болт. И в этом самое противное. Было б что-то серьезное - ладно, а так дрочь какая-то.
Код:#include <avr/interrupt.h> #include <stdbool.h> #include <inttypes.h> #define oSOLENOID_OFF PORTD |= 0x04 // PD2 high #define oSOLENOID_ON PORTD &= ~0x04 // PD2 low #define TIMER_ENABLE WDTCSR = (1<<WDIF); WDTCSR = (1<<WDIE) #define TIMER_DISABLE WDTCSR &= ~(1<<WDIE) #define PLUS 1 #define MINUS 0 #define HOURS 14 #define MINUTES 25 #define COR_STANDART 40 #define COR_FIRST 10 #define COR_DIRRECTION PLUS #define TICK_TIMER 197 #define PRESET 1 uint16_t uiPulseTicks = 0; int8_t cCorrectionFlag = -1; uint8_t ucTimer = 25; uint8_t ucSeconds = 55; uint8_t ucTmpCounter; bool bMinuteFlag = false; uint8_t ucMinutes = MINUTES; uint8_t ucHours = HOURS; uint8_t ucCorDir = COR_DIRRECTION; uint8_t ucCorSeconds = COR_STANDART; uint8_t ucFCorSeconds = COR_FIRST; uint16_t uiTickTimer = TICK_TIMER; uint16_t table[] = { 14, 1, 250, 14, 2, 250, 14, 3, 250, 14, 4, 250, 14, 5, 255, 14, 6, 250, 14, 7, 250, 14, 8, 250, 14, 9, 250, 14, 10, 250, 14, 11, 250, 14, 12, 250, 14, 13, 250, 14, 14, 250, 14, 15, 255, 14, 16, 250, 14, 17, 250, 14, 18, 250, 14, 19, 250, 14, 20, 250, 14, 21, 250, 14, 22, 250, 14, 23, 250, 14, 24, 250 }; int main(void) { unsigned int i; PIND |= (1<<PD2); // PD2 out PORTD |= (1<<PD1);; // pull up for PD1 oSOLENOID_OFF; for(i=0xffff; i>0; i--); oSOLENOID_ON; for(i=0xffff; i>0; i--); oSOLENOID_OFF; for(i=0xffff; i>0; i--); oSOLENOID_ON; for(i=0xffff; i>0; i--); oSOLENOID_OFF; for(i=0xffff; i>0; i--); oSOLENOID_ON; for(i=0xffff; i>0; i--); oSOLENOID_OFF; // TIMER0 TCCR0A = 0x00; TCCR0B = 0x03; //prescaller clk/1024 TCNT0 = 0xB1; //5ms interrupt on ovf TIMSK0 = 0x01; //OVF Interrupt Enabled PCICR = 0x04; // PCINT 2 channel( e_ints 16-23) ON. // Our IN 31st pin PD1 is PCINT17. WDTCSR |= (1<<WDCE) | (1<<WDE); // setting WDT to interrupt every 8sec WDTCSR = (1<<WDP3) | (1<<WDP0); sei(); while(1) { if(bMinuteFlag) { bMinuteFlag = false; for(ucTmpCounter=0; ucTmpCounter<sizeof(table)/6; ucTmpCounter++) { if(table[ucTmpCounter*3] == ucHours) { if(table[ucTmpCounter*3 + 1] == ucMinutes) { oSOLENOID_ON; uiPulseTicks += table[ucTmpCounter*3 + 2] *2; PCIFR |= (1<<PCIF2); // clear PCINT2 flag PCMSK2 |= (1<<PCINT17); // turn on PCINT17 break; } } } if(ucHours == 14) { if(ucMinutes == 3) { if(cCorrectionFlag) { if(cCorrectionFlag > 0) { if(ucCorDir) ucSeconds = ucCorSeconds; else { ucSeconds = 60 - ucCorSeconds; ucMinutes--; } } else { if(ucCorDir) ucSeconds = ucFCorSeconds; else { ucSeconds = 60 - ucFCorSeconds; ucMinutes--; } } cCorrectionFlag = 0; TIMER_ENABLE; } } } } } } ISR(PCINT2_vect) { if(uiPulseTicks > 0) uiPulseTicks--; else { oSOLENOID_OFF; PCMSK2 &= ~(1<<PCINT17); // turn off PCINT17 } } ISR(TIMER0_OVF_vect) { TCNT0 = 0xB1; //5ms interrupt on ovf if(uiTickTimer > 0) uiTickTimer--; else { uiTickTimer = TICK_TIMER; ucSeconds++; if(ucSeconds > 59) { ucSeconds = 0; ucMinutes++; bMinuteFlag = true; if(ucMinutes > 59) { ucMinutes = 0; ucHours++; if(ucHours > 23) ucHours = 0; } } } } ISR(WDT_vect) // wdt interrupt routline, happens every 8 sec. { ucTimer--; if(!ucTimer) { TIMER_DISABLE; ucTimer = 25; cCorrectionFlag = 1; } }
Не работает. Глубоко не копал. В прерывания вваливается. В них провереная логика, но результата нет.
Теоретически возможно, асм листинг не смотрел. Но практически никогда такого не видел. Пишешь в регистры порта - замечательно, нет - так нет, по умолчанию останется высокоомным входом.
И cvavr уважаю сильно как раз за отсутствие вздрочей. Понятные библиотеки, некоторые плюшки типо встроеных макросов, например возвожность писать PORTA.[index] = 1; и быть понятым.
Проспался и нашел таки то, про что ты говорил. Да, порт изначально не настроил перепутав ДДР с ПИН. То есть выход был входом, но будучи поцепленым на мосфет с затвором притянутым через резистор к земле и так нормально работало - 50к внутренней подтяжки вверх как-то открывали его, а 100к вниз закрывали назад при переходе пина в высокоомное состояние.Я уже и не помню точно, так как с АВР-ми и их студией не работал долго, -
но по-моему, изначально, нужно определить работу порта либо на вход, либо на выход, и для этого использовался макрос DDRx, где х - было имя порта. А уже PORTx или PINx, в зависимости от использования, либо переключали, либо "слушали" состояние самого порта.