Вопрос - написал программу, которая считывает текущее состояние двух каналов АЦП (на них нацеплены переменные резисторы), вычисляет значение напряжений. По результату выдает направление вращения для моторов и величину ШИМ.
Вот программа:
- Код: Выделить всё • Развернуть
#include <avr/io.h>
//определим каналы ШИМа
#define SHIM1 OCR1A
#define SHIM2 OCR1B
//определим входные каналы для джойстика:
/*0000 ADC0
0001 ADC1
0010 ADC2
0011 ADC3
0100 ADC4
0101 ADC5
0110 ADC6
0111 ADC7*/
#define CHANNEL1 0x00
#define CHANNEL2 0x01
//Програма задержки
void pause (unsigned int a)
{
unsigned int i;
for (i=a;i>0;i--);
}
//функция получает в качестве аргумента номер канала и
//возвращает значение на входе
unsigned int ADC_result(unsigned char adc_input)
{
ADMUX=adc_input | (ADMUX & 0xFF);
//задержка для стабилизации входного напряжения
pause(100);
//начинаем преобразование (ADSC = 1)
ADCSRA = ADCSRA | 0x40;
while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
ADCSRA|=0x10;//устанавливаем ADIF
return ADCW;//ADCW - содержит ADCH и ADCL как нам нужно
}
void main(void)
{
unsigned int i;
//Массив, хранящий в себе пороговые значения вольтажей от джойстика
float voltages[3] = {3.5, 1.5, 0};
//Массив значений мощности ШИМ (без учета знака)
int power[3] = {0xFF, 0x00, 0xFF};
int direction[3] = {1, 0, -1};
//значения вольтажа из соответствующих резисторов
float vl1, vl2;
//направление вращения моторов
// 0 - нет вращения
// 1 - нормальное направление вращения
// -1 - обратное вращение
int dir1, dir2;
DDRB=0x07; //Инициализация PB1 (OC1A) и PB2 (OC1B) как выход, а также PB0 - светодиод
DDRD=0xFF; // все ножки порта D сделать выходами
//зажигаем светодиод
PORTB = PORTB | 0x01;
//Инициализируем ШИМ
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10)|(1<<WGM12); //На выводе OC1A единица, когда OCR1A==TCNT1, восьмибитный ШИМ
TCCR1B=(1<<CS10)|(1<<WGM12);//Делитель=
//Иницилиазируем АЦП
ADMUX = 0xC0;// Выбрали в качестве опорного напряжения внутренний 2.56В с кондером. 1100.0000 = 0xC0
ADCSRA = 0x8D;
while (1)
{
//////////////////////////////////////////////////////////////////////////
// ВОЛЬТАЖ
//////////////////////////////////////////////////////////////////////////
vl1 = 0.0049 * ADC_result(CHANNEL1);
vl2 = 0.0049 * ADC_result(CHANNEL2);
for (i=0; i<2; i++)
{
if (vl1 >= voltages[i])
{
//если вольтаж больше определенного значения из массива, то выбираем соответствующее ему значение мощности
SHIM1 = power[i];
dir1 = direction[i];
break;//сбрасываем цикл, иначе дойдем до самого первого значения
}
}
for (i=0; i<2; i++)
{
if (vl2 >= voltages[i])
{
//если вольтаж больше определенного значения из массива, то выбираем соответствующее ему значение мощности
SHIM2 = power[i];
dir2 = direction[i];
break;//сбрасываем цикл, иначе дойдем до самого первого значения
}
}
//устанавливаем направление вращения
//для ножек PD0 и PD1 (первый мотор) PD2 и PD3 (второй мотор)
// ПЕРВЫЙ МОТОР
// 10 00 - прямое вращение
// 01 00 - обратное
// 00 00 - СТОП
// ВТОРОЙ МОТОР
// 00 10 - прямой
// 00 01 - обратный
// 00 00 - СТОП
PORTD = 0x00;//СТОП обоих моторов по умолчанию dir1=dir2=0
if (dir1 == 1)
{
PORTD = PORTD | 0x08;
}
if (dir1 == -1)
{
PORTD = PORTD | 0x04;
}
if (dir2 == 1)
{
PORTD = PORTD | 0x02;
}
if (dir2 == -1)
{
PORTD = PORTD | 0x01;
}
}
}
Вопроса два:
1. Почему программа реагирует только на изменения ADC1 (ножка PC1)? На первый АЦП, который ADC0 не реагирует ни один мотор. А вот на вторую почему-то реагируют оба мотора.
2. Почему размер такой маленькой программы огромный? Почти 9 килобайт hex-файл. Как уменьшить?
Во вложениях прошивка и плата.