Re: CodeVision AVR в вопросах и ответах
Добавлено: Чт окт 13, 2011 10:22:20
у кого есть CVAVR V1. 24.4 Standard , поделитесь пожалуйста
Здесь можно немножко помяукать :)
https://radiokot.ru/forum/
Спасибо , действительно помоглоSubDia писал(а):Ругается, потому как вначале нужно подключить хидер mega8.h:Файл должен находиться в папке inc CVAVR.Код: Выделить всё
#include <MEGA8.H>
1.25.9 подойдёт? Пользуюсь давно, глюков не заметил.levaclaus писал(а):у кого есть CVAVR V1. 24.4 Standard , поделитесь пожалуйста
2 кодевижин вывкидывает такую ошибку если использовать #pragma ruslcd+levaclaus писал(а):всё правильно
2 кодевижион не понимает #pragma rl+, зато понимает #pragma ruslcd+ вот и не совместимость(
2 кодевижион не понимает и #pragma ruslcd+, по крайней мере с версии 2.03.2 кодевижион не понимает #pragma rl+, зато понимает #pragma ruslcd+ вот и не совместимость(
Код: Выделить всё
/**
*
* Пример управления 9 сервами с использованием прерывания и внешнего
* счетчика типа 4017.
*
* Предполагается, что период следования импульсов 20мс,
* длительность импульса от 1 до 2 мс.Хотя у счетчика 10 выходов,
* используется только 9 - десятое состояние используется для
* формирования паузы, доводящей период до 20мс.
*
* Предполагается ATMega16(32) с тактовой частотой 16 МГц. Сервы подключены
* к выводам порта A.
*
* Используется 16-битный таймер, работающий на тактовой частоте процессора
* деленной на 8, при этом разрешение 0,5 мкс. Тактовые импульсы для внешнего
* счетчика формируются аппаратно таймером МК на выходе OC1A.
* Добавив еще один аналогичный обработчик прерываний (по совпадению таймера
* с регистром OCR1B), и еще один счеткик можно увеличить число серв до 18.
*
* При меньшем разрешении (8мкс) можно использовать и 8-битный таймер.
*
**/
#include <avr/io.h>
#include <avr/interrupt.h>
/**
* Массив, хранящий текущие положения серв. Так как период тактовых
* импульсов таймера 500нс, то значения в этом массиве равны длительности
* импульса в микросекундах, умноженной на 2. 3000 для среднего положения,
* 2000 и 4000 для крайних.
**/
uint16_t servo_position[9] = {2000, 2200, 2400, 2600, 2800, 3000, 3200, 3412 , 3600};
volatile uint32_t i;
/**
* Прерывание от таймера
**/
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
/* Номер сервы, для которой формируется импульс.
* Заметьте, что начинаем не с нуля, а с 1, так как первое прерывание
* также формирует тактовый импульс, который устанавливает счетчик
* в состояние 1.
*/
static uint8_t current_servo = 1;
/**
* Время, необходимое для обработки всех серв, заранее неизвестно, и
* может быть любым от 9 до 18 мс. Для обеспечения периода импульсов
* 20мс, используем переменную pause. Начальное значение 40000, что
* соответствует 20мс. После формирования каждого импульса, переменная
* уменьшается на ширину сформированного импульса, и после обработки
* всех серв в ней остается время, оставшееся до завершения 20мс периода
*/
static uint16_t pause = 40000;
/* При совпадении таймера с регистром OCR1A, помимо прерывания, МК также
* изменяет состояние выхода OC1A с 0 на 1, формируя таким образом фронт
* тактового импульса для внешнего счетчика. Чтобы по следующему срабатыванию
* таймера был сформирован новый фронт, принудительно сбрасываем выход OCR1A
*/
TCCR1A |= _BV(FOC1A);
if (current_servo == 9) {
/* Когда current_servo достигает 9 - значит обработаны все сервы, и
* нужно выдержать паузу до окончания 20мс периода */
current_servo = 0;
OCR1A += pause;
pause = 40000;
} else {
/* current_servo от 0 до 7 - настраиваем таймер на срабатывание
* через время, равное ширине импульса. */
OCR1A += servo_position[current_servo];
/* Уменьшаем паузу */
pause -= servo_position[current_servo];
/* Переходим к следующей серве */
current_servo++;
}
}
int main(void)
{
/* Настраиваем используемые выводы МК на режим выхода */
DDRD = 0x60;
/* Формируем сигнал сброса внешнего счетчика */
PORTD |= 0x40;
/* Небольшая пауза перед выдачей первого импульса */
OCR1A = 2000;
/* Таймер в режиме простого счетчика от 0 до 0xFFFF. При совпадении таймера
* с регистром OCR1A состояние вывода OC1A меняется на противоположное. */
TCCR1A = _BV(COM1A0);
/* Предделитель тактовой частоты = 8 */
TCCR1B = _BV(CS11);
/* Прерывание по совпадению таймера с регистром OCR1A */
TIMSK = _BV(OCIE1A);
/* Освобождаем вход сброса внешнего счетчика */
PORTD &= ~0x40;
sei(); /* Разрешаем прерывания */
for(;;) {
i++;
}
}
Код: Выделить всё
#include <mega128.h>
#define OCR3C (*(unsigned int *) 0x82)
#define SERV (DDRE||TCCR3A||TCCR3B||ETIMSK)
unsigned int servo_position[9]={1382, 1382, 1382, 1382, 1382, 1382, 1382, 1382, 7833};
interrupt [TIM3_COMPC] void timer3_compc_isr(void)
{
static unsigned char current_servo=0;
static unsigned int ocr=2000;
ocr+=servo_position
OCR3C=ocr;
if (current_servo==8)
{
current_servo=0;
TCCR3C|=(1<<FOC3C);
TCCR3C|=(1<<FOC3C);
}
else
{
current_servor++;
}
TCCR3C|=(1<<FOC3C);
}
void servo (unsigned char servo, unsigned int pos)
{
if(SERV==OFF){servo_on();}
if (servo>7){servo=7;}
if (pos<50){pos=50;}
if (pos>250){pos=250;}
servo_position[8]+=servo_position[servo];
servo_position[servo]=((pos*74/8)-5);
servo_position[8]-=servo_position[servo];
}
void servo_on (void)
{
DDRE|=((1<<DDE5)|(1<<DDE2));
PORTE&=~((1<<PORTE5)|(1<<PORTE2));
PORTE.2=1;
OCR3C=2000;
TCCR3A=0x04;
TCCR3B=0x02;
ETIMSK|=(1<<OCIE3C);
PORTE.2=0;
}
void main (void)
{
servo(1,200)
}
Вот обработчик прерывания сгенерированный Code Wizard'ом.[TIM3_COMPC]
А что это за прерывание таймера? вы сами придумали?
Код: Выделить всё
// Timer3 output compare C interrupt service routine
interrupt [TIM3_COMPC] void timer3_compc_isr(void)
{
// Place your code here
}
Код: Выделить всё
#define OFF 0
Код: Выделить всё
#define OCR3C (*(unsigned int *) 0x82)
interrupt [TIM3_COMPC] void timer3_compc_isr(void)
{
static unsigned char current_servo=0;
static unsigned int ocr=2000;
ocr+=servo_position
OCR3C=ocr;
if (current_servo==8)
{
current_servo=0;
TCCR3C|=(1<<FOC3C);
TCCR3C|=(1<<FOC3C);
}
else
{
current_servor++;
}
TCCR3C|=(1<<FOC3C);
} Это здесь, надо полагать?korbofos писал(а):Нашёл косяк в переменной ocr досчитав до 64250. В седующих прерываниях её значение остаются прежним.
Убрать её вообщеkorbofos писал(а):Что придумать?
Код: Выделить всё
interrupt [TIM3_COMPC] void timer3_compc_isr(void)
{
static unsigned char current_servo=0;
static unsigned int ocr=2000;
ocr+=servo_position[current_servo];
OCR3CH=(unsigned char)(ocr>>8);
OCR3CL=(unsigned char)ocr;
if (current_servo==8)
{
current_servo=0;
TCCR3C|=(1<<FOC3C);
TCCR3C|=(1<<FOC3C);
}
else
{
current_servo++;
}
TCCR3C|=(1<<FOC3C);
} Конечноkorbofos писал(а):Всем спасибо! зло крылось в #define OCR3C (*(unsigned int *) 0x82)
В водевижене нет 16битной переменной OCR3C, есть OCR3CH, OCR3CL. Хотя в винавр есть есть 16 битная переменная OCR3C...
Вот так всё пошло)))Код: Выделить всё
interrupt [TIM3_COMPC] void timer3_compc_isr(void) { static unsigned char current_servo=0; static unsigned int ocr=2000; ocr+=servo_position[current_servo]; OCR3CH=(unsigned char)(ocr>>8); OCR3CL=(unsigned char)ocr; if (current_servo==8) { current_servo=0; TCCR3C|=(1<<FOC3C); TCCR3C|=(1<<FOC3C); } else { current_servo++; } TCCR3C|=(1<<FOC3C); }
Код: Выделить всё
ocr+=servo_position[current_servo];Код: Выделить всё
ocr+=servo_position;Код: Выделить всё
ocr+=servo_position;Код: Выделить всё
TCCR3C|=(1<<FOC3C);