TCCR1B = TCCR1B_value; //В настройке таймера
const uint16_t static Timer1Presdcaler(void){ //256,1024
switch(TCCR1B_value & 0b00000111){
case 0b00000000: return 0UL;
case 0b00000001: return 1UL;
case 0b00000010: return 8UL;
case 0b00000011: return 64UL;
case 0b00000100: return 256UL;
case 0b00000101: return 1024UL;
}
return 0;
}
#define Timer1Freq F_CPU/Timer1Presdcaler()
#define Tick2Wait(s) (Timer1Freq*s)
uint32_t tmp=Tick2Wait(60*15); //так-то Tick2Wait() возвращается u32
printf(" F_CPU= %u",tmp>>16);
printf(" F_CPU= %u",tmp);
CheckChargeMult = tmp / my_USHRT_MAX;//тип не мощнее uint16_t
if (CheckChargeMult==0) {
uint16_t currentTime = TCNT1;
OCR1A = (my_USHRT_MAX-currentTime>tmp) ? tmp-(my_USHRT_MAX-currentTime) : tmp;
}
else CheckChargeTrigger=true;
//Код overflow
if (CheckChargeTrigger)
if (CheckChargeMult==0) {
uint16_t currentTime = TCNT1;
OCR1A = (my_USHRT_MAX-currentTime>tmp) ? tmp-(my_USHRT_MAX-currentTime) : tmp;
TIMSK1|=(1<<OCIE1A);//вкл OCR interaption//тут можно проверить, не активирована ли он уже (не занят ли кем-то) if (TIMSK1 & (1<<OCIE1A)) то занят
}
else CheckChargeMult--;
//Код OCR
//PortA=... делаем действие
CheckChargeTrigger=false;
TIMSK1&=~(1<<OCIE1A);//выкл OCR
Сделаем аналог delay_s, но с возможностью параллельно что-то делать в цикле, своего рода задача-бездействие. Для этого нам понадобится таймер. Возьмём Timer1 с его 16битным счётчиком TCNT1.
//задержка на 2
u16 alarm=GetOCR(Tick2Wait(2))-1;//-1 на случай, если TCNT1==alarm даже после исполнения нескольких команд (вдруг таймер ультра-слоупок), из-за этого погрешность в 1 тик.
do{
externalSupplyLevelADC = adc_read_10bit(ADC_MUX_ADC6, ADC_VREF_AREF);
if (externalSupplyLevelADC<externalSupplyLowLevelADC) //смотрим АЦП
{};//что-то делаем
}while(TCNT1!=alarm);
Погрешность 1 тик есть 1/частота таймера. Например, если частота таймера 3600 Hz (это медленный таймер), то погрешность в 1 тик - это 1/3600~0.28 ms. |