Добрый день.
Разрабатываю дополнение для радиоаппаратуры. Вот кое-что написал прошу Ваших комментариев, по алгоритму, организации кода, что можно улучшить.
Код
/**
Задача:
Необходимо управлять коллекторным двигателем по средствам ШИМ.
Двигатель должен начинать движение с ускорением.
Управление должно происходить в зависимости от входных сигналов.
Входы:
1. Основной сигнал - прямоугольные импульсы амплитудой 5В, длительностью 20 мС,
вехняя часть 1000 - 2000 мкС.
2. Два дискретных датчика - верхнее и нижнее положение.
Выходы:
Два выхода процессора, их комбинации управляют двигателем.
Вверх - по ч.с., вниз против ч.с.
|--------------------------------------------------------|
| |Стоит |Вверх |Вниз |Зафиксирован |
|--------------------------------------------------------|
|Выход1 | 0 1 0 1 |
|--------------------------------------------------------|
|Выход2 | 0 0 1 1 |
|--------------------------------------------------------|
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "AE_Util.h"
#define PULSE_PIN PIND
#define PULSE_PPIN PD2
#define PULSE_MID_WIDTH 188// Средняя длительность импульса 1500/8 = 188.
#define PULSE_WIDTH_TOLER 5 // Допуск по ширине импульса
#define PULSE_QUANTITY 10 // Количество анализируемых импульсов (0...255)
#define MOT_DDR DDRD
#define MOT_PORT PORTD
#define MOT_PIN1 PD4
#define MOT_PIN2 PD5
#define MOT_UP sbi(MOT_PORT, MOT_PIN1); cbi(MOT_PORT, MOT_PIN2)
#define MOT_DOWN cbi(MOT_PORT, MOT_PIN1); sbi(MOT_PORT, MOT_PIN2)
#define MOT_STANDBY cbi(MOT_PORT, MOT_PIN1); cbi(MOT_PORT, MOT_PIN2)
#define SEN_PIN PINA
#define SEN_UP_PIN PA0
#define SEN_DOWN_PIN PA1
enum {S_NO, S_UP, S_DOWN, S_BOTH};
// Глобальные переменные
volatile u8 g_abPUW[PULSE_QUANTITY];// Массив ширин верхней части импульса 1 == 8 мкС.
volatile u8 g_bPulNum;
// Глобальные функции
u8 Measuring();
u8 GetSen();
ISR(INT0_vect)
{
if(PULSE_PIN & (1 << PULSE_PPIN)) // Начало верхней части
{
TCCR0=0x03;
TCNT0=0x00;
}
else // Конец верхней части
{
if(TCCR0 != 0)// Только если таймер предварительно был запущен, чтобы замеры делать с начала импульса
{
g_abPUW[g_bPulNum++] = TCNT0;
TCCR0=0x00;
}
}
}
int main(void)
{
sbi(MOT_DDR, MOT_PIN1);
sbi(MOT_DDR, MOT_PIN2);
// Чтобы входные импульсы стабилизировались
_delay_ms(500);
while(1)
{
if(GetSen() != S_DOWN)
{
MOT_DOWN;
while(GetSen() != S_DOWN);
MOT_STANDBY;
}
else
{
u8 bTol, bMid;
do
{
bMid = Measuring();
if(bMid <= PULSE_MID_WIDTH)
{
bTol = PULSE_MID_WIDTH - bMid;
}
else
{
bTol = bMid - PULSE_MID_WIDTH;
}
}while(bTol < PULSE_WIDTH_TOLER);
MOT_UP;
while(GetSen() != S_UP);
MOT_STANDBY;
_delay_ms(500);
MOT_DOWN;
while(GetSen() != S_DOWN);
MOT_STANDBY;
}
}
return 0;
}
u8 Measuring()
{
g_bPulNum = 0;
TCCR0=0x00;// Таймер выключен
sbi(GICR, INT0);// Разрешаем прерывание INT0
cbi(MCUCR, ISC01);// Прерывание будет происходить при любом изменении уровня на INT0
sbi(MCUCR, ISC00);
sbi(GIFR, INTF0);// Сбросить прерывание INT0
sei();// Глобальное разрешение прерываний
while(g_bPulNum < PULSE_QUANTITY);// Ожидаем необходимое количество импульсов
cli();
cbi(GICR, INT0);
TCCR0 = 0x00;
// Вычисляем среднее значение
u8 b;
int iMid = 0;
for(b = 0; b < PULSE_QUANTITY; b++)
{
iMid += g_abPUW[b];
}
iMid /= PULSE_QUANTITY;
return iMid;
}
u8 GetSen()
{
volatile u8 bRes = SEN_PIN & (1 << SEN_DOWN_PIN);
bRes |= (SEN_PIN & (1 << SEN_UP_PIN));
return bRes;
}