Также можно адаптировать для измерения сдвига фаз трёхфазного напряжения.
Идея программы. У нас за каждый период 158 выборок тока и напряжения. Если напряжение и ток синусоидальные, то можно измерив разницу между временем пересечения напряжения и тока нуля определить сдвиг фаз между ними. При 158 выборок дискретность расчётов будет 360/158=2,278 градусов. Поймав момент когда выборка U стала из отрицательной положительной, (т.е. пересекла 0), начав с этого момента считать кол-во выборок I до того момента пока выборка I, также стала из отрицательной положительной , умножив это кол-во выборок 2,278 я вычислю угол сдвига фаз между синусоидальным напряжением и током.

1 случай я как раз жду момента когда выборка I, изменится из отрицательной в положительную (пересчет 0)
2 случай я жду момента когда выборка I, изменится из
положительной в отрицательную (пересчет 0) и к получившемуся значению кол-ва выборок прибавлю половину выборок за период т.е. добавлю 180 градусов.
Обрабатывать выборки я буду в прерывании заполняющим буфер выборок из программы в статье
http://stormm.ru/2019/04/10/%D0%B1%D0%BB%D0%BE%D0%B3-%D0%BE-%D0%BF%D0%BE%D0%BF%D1%8B%D1%82%D0%BA%D0%B5-%D0%B8%D0%B7%D0%BC%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D0%BA%D0%BE%D1%8D%D1%84%D1%84%D0%B8%D1%86%D0%B8%D0%B5%D0%BD%D1%82-%D0%BC/
//таймер
void TIM2_IRQHandler(void)
{
//A0--->JDR3
//A2--->JDR1
//A3--->JDR2
TIM2->SR &= ~TIM_SR_UIF; //
if(m == 0)
{
BuffADCVoltage1[i] =ADC1->JDR2-offset_voltage;
BuffADCCurrent1[i] =ADC1->JDR1-offset_voltage;
ADCVoltage=BuffADCVoltage1[i];
ADCcurrent=BuffADCCurrent1[i];
i++;
}
else
{
BuffADCVoltage2[i] =ADC1->JDR2-offset_voltage;
BuffADCCurrent2[i] =ADC1->JDR1-offset_voltage;
ADCVoltage=BuffADCVoltage2[i];
ADCcurrent=BuffADCCurrent2[i];
i++;
}
//если U<=0, то устанавливаем метку что можно фиксировать пересечение U нуля,
//из отрицательных значений в положительные
if (ADCVoltage<=0&&wait1==0&&wait2==0&&wait3==0)
{
wait1=1; //метка что можно ловить событие пересечения
k_angle=0; //счтёчик выборок смещения I относительно U
}
//проверяем произошло ли пересечение U нуля,
//если да и U>I (1 случай),то считаем выборки тока до того момента
//когда они станут положительными, угол меньше 180 градусов
//else if и U<I (2 случай),то считаем выборки тока до того момента
//когда они станут отрицательными, угол больше 180 градусов
if (wait1==1&&ADCVoltage>=0&&ADCVoltage>=ADCcurrent)
{
wait2=1;
wait1=0;
wait3=0;
}
else if (wait1==1&&ADCVoltage>=0&&ADCcurrent>=ADCVoltage)
{
wait3=1;
wait1=0;
wait2=0;
}
//wait2
if(wait1==0&&wait2==1&&ADCcurrent>=0)
{
rashet_angle=k_angle;
wait1=0;
wait2=0;
wait3=0;
}
//wait3
else if(wait1==0&&wait3==1&&ADCcurrent<=0)
{
rashet_angle=k_angle+l/2;
wait1=0;
wait2=0;
wait3=0;
}
else if(wait1==0&&(wait2==1||wait3==1))
{
++k_angle;
}
}