CodeVision AVR в вопросах и ответах
- Реклама
Re: CodeVision AVR в вопросах и ответах
Кстати вот код,прекрасно отрабатывает даже просто замыканием проводком вместо кнопки,
if(PINB.4==0)df++; // это антидребезг
if(PINB.4==1)df=0;
if(df==3)w++; //переключение часов,будильника,таймера, кнопка time alarm
if(w==6)w=1;
код размещен у меня в обработчике прерывания в 100Гц от таймера2 по совпадению.
как видим задержка обработки кнопки 30 миллисекунд,оптимальное значение.
Видно, что кнопка переключает 5 режимов по кругу.
if(PINB.4==0)df++; // это антидребезг
if(PINB.4==1)df=0;
if(df==3)w++; //переключение часов,будильника,таймера, кнопка time alarm
if(w==6)w=1;
код размещен у меня в обработчике прерывания в 100Гц от таймера2 по совпадению.
как видим задержка обработки кнопки 30 миллисекунд,оптимальное значение.
Видно, что кнопка переключает 5 режимов по кругу.
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: CodeVision AVR в вопросах и ответах
В первую очередь - отформатировать код.ra9ust писал(а):прокомментируете, как что можно улучшить или поменять?
Добавить отступы перед каждым блоком кода (2-4 пробела или табуляция). Кстати, где-то они у вас одного типа, где-то другого, а где-то никакого.
Разнести объявления переменных на разные строчки или убрать кучу названий типа из одной (в строке 29, например, четыре ключевых слова char, когда достаточно одного)
Дать переменным осмысленные имена, а не просто буквы английского алфавита подряд
Массив с кодами цифр (digit) лучше заполнять сдвигами и логическими операциями, примерно так
Код: Выделить всё
#define SEG_A 0
#define SEG_B 1
...
PROGMEM const char digit[]={ //объявление в стиле avr-gcc, мне он привычнее
(1<<SEG_A | 1<<SEG_B | 1<<SEG_C | 1<<SEG_D | 1<<SEG_E | 1<<SEF_F),
(1<<SEG_B | 1<<SEG_C),
...
};Вот это действие мне непонятно. Вы хотите поменять все биты кроме нулевого? Обычно это делается как-то такPORTD=digit[se]|PORTD.0<<0;
Код: Выделить всё
PORTD = (PORTD &~(1<<0) ) | digit[se];
PORTD = (PORTD & 0b11111110) | digit[se];
PORTD = (PORTD & 0xF7) | digit[se];Выкиньте этот автосгенерированный мусор! Лучше разобраться самостоятельно и записать по-человечески. Не говоря о простыне бесполезных комментариев и традиционном отсутствии форматирования.// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x02;
TCCR0B=0x04;
TCNT0=0x00;
OCR0A=0xB7; // динамическая индикация 83 Гц
OCR0B=0x00;
Функция read_adc() сама по себе должна возвращать значение АЦП, почему вы этим не пользуетесь? Ну и использовать числа с плавающей точкой без крайней необходимости не стоит.read_adc(6);
a=(ADCH*0.389); // показатель преобразования из АЦП до 99
Вообще, в main() какая-то каша, на мой взгляд. Без форматирования и комментариев сложно разобраться что же имелось в виду.
В прерывании Int1 напрашивается вынести проверку PC4 во внешний if или использовать массив переменных, что-то вроде if( PINC & (1<<4) )arr[w]++;
Re: CodeVision AVR в вопросах и ответах
Согласен что с нулевым битом мне тоже запись непонятна,хотя и работает,кто то подсказал так сделать, а вот ваш вариант с двоичным представлением порта конечно понятнее,буду знать. А комментарии кол генератора пока не стал убирать,а касаемо регистров таймеров и прочего то в самом начале изучения так и делал расписывая на бумаге регистр и вручную выставлял каждый бит согласно даташиту. С генератором кода однако удобнее да и значения не особо отличаются и мне так проще. Отступы и прочее я необрашал внимания,пока экспериментирую.ацп совсем бегло прочитал особо не вдаваясь поэтому написал пока так лишь бы работало. Еще месяц назад и понятия не имел как устроен контроллер и тем более что то написать на него.
Re: CodeVision AVR в вопросах и ответах
А вот насчет того что функция ацп сама может возвращать, можете примерно написать как оно должно быть применительно к моему варианту?
- Реклама
Re: CodeVision AVR в вопросах и ответах
Ну как-то так
или так
Код: Выделить всё
unsigned char ADC;
f=10;e=11;
ADC=read_adc(6);
a=(ADC*0.389); // показатель преобразования из АЦП до 99
g=a%10; // а больше и не надо,0-100 градусов,(10-50)
h=a/10;
Код: Выделить всё
f=10;e=11;
a=(read_adc(6)*0.389); // показатель преобразования из АЦП до 99
g=a%10; // а больше и не надо,0-100 градусов,(10-50)
h=a/10;
Re: CodeVision AVR в вопросах и ответах
Так а я не использовал плавающую точку, выводятся только целые значения от 00 до 99.
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: CodeVision AVR в вопросах и ответах
0,389 по-вашему не число с плавающей точкой?ra9ust писал(а):Так а я не использовал плавающую точку, выводятся только целые значения от 00 до 99.
Я имел в виду скорее что-то типа такого
a = (unsigned char)( ( (unsigned int)read_adc(6)*100) >>8 );
Перевод в unsigned int нужен для корректного умножения на 100, потому что получается двухбайтное число, а 100/256 составляет как раз 0,39. Только работает на порядки быстрее умножения дробных чисел.
Проще пока не понадобится что-то исправить. С форматированием тоже самое - когда захотите что-то исправить будете мучиться что к чему относится. Ну и выкладывать такое на всеобщее обозрение мне было бы стыдно, надо же уважать тех, кто хочет помочь.ra9ust писал(а):С генератором кода однако удобнее да и значения не особо отличаются и мне так проще. Отступы и прочее я необрашал внимания
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
А 0.389 о это что, про-вашему, если не число с плавающей точкой? Вы представляете, насколько медленно и ресурсоёмко это на 8бит контроллере?
Re: CodeVision AVR в вопросах и ответах
Ну, ладно, мне например несложно искать и исправлять, все-таки каждому свое, а дробное число просто подогнал чтобы под 99 уместить,ну да ладно.Всё это эксперименты...
Re: CodeVision AVR в вопросах и ответах
CV 3.12
простой код, выводит на LCD крякозябры в первой строке, вторая пустая. Если закомментировать первый gotoxy - выводит как надо первую строку, вторую пустую. Как починить?
Код: Выделить всё
lcd_gotoxy(0,0);
lcd_puts(s);
lcd_gotoxy(0,1);
lcd_puts(s);Re: CodeVision AVR в вопросах и ответах
Для начала - показать весь код. Откуда мы знаем, что там у Вас в строке s и как инициализирован дисплей?
Этот пост оказался полезен? Не поленись, нажми
слева!

Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.
слева!Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.
Re: CodeVision AVR в вопросах и ответах
Доброго времени суток.
Помоги, пожалуйста, разобраться.
Стоит задача в измерении частоты импульсов и их длины (продолжительности).
Перечитал много статей, решил воспользоваться материалом отсюда. Таймер в режиме захвата и так далее...
Вышел вот такой код:
Chip type : ATmega8
AVR Core Clock frequency: 16,000000 MHz
*****************************************************/
#include <mega8.h>
#include <alcd.h>
#include <delay.h>
#include <stdio.h>
#define INPUT_PIN PINB.0
// Обьявзяем переменные
unsigned char lcd_buffer_1[16];
unsigned char lcd_buffer_2[16];
unsigned int OverflowP, OverflowF; //счётчик переполнений для таймера 1
unsigned int EdgeR, EdgeF; //время переднего фронта и заднего фронта
unsigned int Pulse1, Pulse2; //время переднего двух фронтов
unsigned long PulseClocks; //количество тактовых импульсов внутри импульса на входе ICP
unsigned long FreqClocks; //количество тактовых импульсов между импульсами на входе INT1
bit FreqFlag = 1; // флаг для измерение частоты
// Переполнения таймера измерения ДЛИНЫ импульса
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
OverflowP++; //инкрементируется количество переполнений
OverflowF++;
}
// Захват импульса
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
//Блок для измерения длительности импульса
if(INPUT_PIN == 1) //если на входе захвата 1 (передний фронт ПОЛОЖИТЕЛЬНОГО импульса)
{
EdgeF = ICR1; //запоминаем значениие счётчика
TCCR1B &= ~(1<<ICES1); //устанавливаем прерывание по спадающему фронту импульса
OverflowP = 0; //обнуляем количество переполнений счётчика
if (FreqFlag == 1) // измеряем частоту
{
Pulse1 = ICR1; // запоминаем значения счётчика при первом импульсе
OverflowF = 0; // сбрасываем счётчик прерываний
FreqFlag = 0; // сбрасываем флаг для подсчёта второго импульса
}
else
{
Pulse2 = ICR1; // запомингаем значения счётчика при втором импульсе
FreqFlag = 1; // устанавливаем флаг для подсчёта второго импульса
/** РАСЧЁТ ЧАСТОТЫ **/
FreqClocks = ((unsigned long)Pulse2 - (unsigned long)Pulse1 + ((unsigned long)OverflowF *65535)); // количество "тиков" в периоде. Один "тик" = 1/16 мкс при 16 МГц
};
}
else //если на входе захвата 0 (задний фронт ПОЛОЖИТЕЛЬНОГО импульса)
{
EdgeR = ICR1; //запоминаем значение счётчика
TCCR1B |= (1<<ICES1); //устанавливаем прерывание по нарастающему фронту импульса
PulseClocks = ((unsigned long)EdgeR - (unsigned long)EdgeF + ((unsigned long)OverflowP *65535)); // количество "тиков" в длине импульса. Один "тик" = 1/16 мкс при 16 МГц.
};
}
void main(void)
{
/** НАСТРОЙКА ТАЙМЕРА **/
TCCR1B |= (1<<ICES1) | (1<<CS10)| (1<<ICNC1);// входной фильтр, прерывание по нарастающему фронту, запуск таймера (такт 1/16 мкс при 16 МГц)
TIMSK |= (1<<TICIE1) | (1<<TOIE1);//разрешить прерывания по захвату и переполнению таймера 1
lcd_init(16);
#asm("sei")
while (1)
{
lcd_gotoxy(0,0);
sprintf(lcd_buffer_1, "Freq = %i Hz", 1000000/(FreqClocks*0.0625));
lcd_puts(lcd_buffer_1);
lcd_gotoxy(0,1);
sprintf(lcd_buffer_2, "Wdt = %i uS", PulseClocks*0.0625);
lcd_puts(lcd_buffer_2);
lcd_clear();
}
}Однако на дисплей выводят значения от -30000 до +30000 и для частоты и для длины импульса (показания примерные).
Пробовал использовать код автора, но, что странно, он тоже не захотел работать.
Генератором импульсов у меня выступает АТтини13 с простым кодом:
{ // 33 гц
PORTB.0 = 1;
delay_ms(10);
PORTB.0 = 0;
delay_ms(20);
}Порт на выход стоит.
Так же, пробовал тактировать кнопкой. Всё та же белеберда на дисплее...
Не могу понять, где сидит проблема...
Подскажите, пожалуйста...
Помоги, пожалуйста, разобраться.
Стоит задача в измерении частоты импульсов и их длины (продолжительности).
Перечитал много статей, решил воспользоваться материалом отсюда. Таймер в режиме захвата и так далее...
Вышел вот такой код:
Спойлер
/*****************************************************Chip type : ATmega8
AVR Core Clock frequency: 16,000000 MHz
*****************************************************/
#include <mega8.h>
#include <alcd.h>
#include <delay.h>
#include <stdio.h>
#define INPUT_PIN PINB.0
// Обьявзяем переменные
unsigned char lcd_buffer_1[16];
unsigned char lcd_buffer_2[16];
unsigned int OverflowP, OverflowF; //счётчик переполнений для таймера 1
unsigned int EdgeR, EdgeF; //время переднего фронта и заднего фронта
unsigned int Pulse1, Pulse2; //время переднего двух фронтов
unsigned long PulseClocks; //количество тактовых импульсов внутри импульса на входе ICP
unsigned long FreqClocks; //количество тактовых импульсов между импульсами на входе INT1
bit FreqFlag = 1; // флаг для измерение частоты
// Переполнения таймера измерения ДЛИНЫ импульса
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
OverflowP++; //инкрементируется количество переполнений
OverflowF++;
}
// Захват импульса
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
//Блок для измерения длительности импульса
if(INPUT_PIN == 1) //если на входе захвата 1 (передний фронт ПОЛОЖИТЕЛЬНОГО импульса)
{
EdgeF = ICR1; //запоминаем значениие счётчика
TCCR1B &= ~(1<<ICES1); //устанавливаем прерывание по спадающему фронту импульса
OverflowP = 0; //обнуляем количество переполнений счётчика
if (FreqFlag == 1) // измеряем частоту
{
Pulse1 = ICR1; // запоминаем значения счётчика при первом импульсе
OverflowF = 0; // сбрасываем счётчик прерываний
FreqFlag = 0; // сбрасываем флаг для подсчёта второго импульса
}
else
{
Pulse2 = ICR1; // запомингаем значения счётчика при втором импульсе
FreqFlag = 1; // устанавливаем флаг для подсчёта второго импульса
/** РАСЧЁТ ЧАСТОТЫ **/
FreqClocks = ((unsigned long)Pulse2 - (unsigned long)Pulse1 + ((unsigned long)OverflowF *65535)); // количество "тиков" в периоде. Один "тик" = 1/16 мкс при 16 МГц
};
}
else //если на входе захвата 0 (задний фронт ПОЛОЖИТЕЛЬНОГО импульса)
{
EdgeR = ICR1; //запоминаем значение счётчика
TCCR1B |= (1<<ICES1); //устанавливаем прерывание по нарастающему фронту импульса
PulseClocks = ((unsigned long)EdgeR - (unsigned long)EdgeF + ((unsigned long)OverflowP *65535)); // количество "тиков" в длине импульса. Один "тик" = 1/16 мкс при 16 МГц.
};
}
void main(void)
{
/** НАСТРОЙКА ТАЙМЕРА **/
TCCR1B |= (1<<ICES1) | (1<<CS10)| (1<<ICNC1);// входной фильтр, прерывание по нарастающему фронту, запуск таймера (такт 1/16 мкс при 16 МГц)
TIMSK |= (1<<TICIE1) | (1<<TOIE1);//разрешить прерывания по захвату и переполнению таймера 1
lcd_init(16);
#asm("sei")
while (1)
{
lcd_gotoxy(0,0);
sprintf(lcd_buffer_1, "Freq = %i Hz", 1000000/(FreqClocks*0.0625));
lcd_puts(lcd_buffer_1);
lcd_gotoxy(0,1);
sprintf(lcd_buffer_2, "Wdt = %i uS", PulseClocks*0.0625);
lcd_puts(lcd_buffer_2);
lcd_clear();
}
}
Пробовал использовать код автора, но, что странно, он тоже не захотел работать.
Генератором импульсов у меня выступает АТтини13 с простым кодом:
Спойлер
while (1){ // 33 гц
PORTB.0 = 1;
delay_ms(10);
PORTB.0 = 0;
delay_ms(20);
}
Так же, пробовал тактировать кнопкой. Всё та же белеберда на дисплее...
Не могу понять, где сидит проблема...
Подскажите, пожалуйста...
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Re: CodeVision AVR в вопросах и ответах
Разбейте программу на кусочки. Получите сперва нужное значение частоты. Переменным, изменяющимся в разных прерываниях, на всякий пожарный лучше поставить модификатор volatile.DataLife писал(а): Не могу понять, где сидит проблема...
Re: CodeVision AVR в вопросах и ответах
Вопрос новичка - подскажите, вот эти библиотеки http://arduino.ru/forum/proekty/modbusr ... i-owen-plc можно заюзать в CodeVision ?
И нужен ли для них какой-то особый микроконтроллер или подойдет любой AVR типа ATMEGA328P
или можно юзать среду разработки Arduino для любых AVR ?
И нужен ли для них какой-то особый микроконтроллер или подойдет любой AVR типа ATMEGA328P
или можно юзать среду разработки Arduino для любых AVR ?
Re: CodeVision AVR в вопросах и ответах
Как отредактировать существующий проект через генератор кода ?
Т.е. Имеется проект. Хочу внести изменения в программе при помощи генератора проекта. Захожу в КодеВизард. Открываю .cwp файл. Вношу изменения. Теперь если сгенерировать код (Generate, Save and Exit), то в IDE будет "чистая" программа сгенерированная КодеВизардом. Мне надо, что бы был мой код с соответствующими изменениями. Если просто вставлять в свой код то что сгенерировал КодеВизард, то файлы .cwp и .prj будут без изменений.
Т.е. Имеется проект. Хочу внести изменения в программе при помощи генератора проекта. Захожу в КодеВизард. Открываю .cwp файл. Вношу изменения. Теперь если сгенерировать код (Generate, Save and Exit), то в IDE будет "чистая" программа сгенерированная КодеВизардом. Мне надо, что бы был мой код с соответствующими изменениями. Если просто вставлять в свой код то что сгенерировал КодеВизард, то файлы .cwp и .prj будут без изменений.
-
BEST-83154
- Прорезались зубы
- Сообщения: 218
- Зарегистрирован: Ср дек 02, 2015 15:06:01
Re: CodeVision AVR в вопросах и ответах
вот тут вписан вольтметр,амперметр,ваттметр,таймер и разложения чисел
и мне хотелось бы видеть еще и замер емкости акб в А/Ч
кто может помогите!!!
и мне хотелось бы видеть еще и замер емкости акб в А/Ч
кто может помогите!!!
- Вложения
-
- 45.c
- (5.22 КБ) 363 скачивания
- rxstart1
- Вымогатель припоя
- Сообщения: 508
- Зарегистрирован: Пт фев 22, 2013 18:00:43
- Откуда: Беларусь, г. Гомель
Re: CodeVision AVR в вопросах и ответах
Люди нужна помощь. Впервые столкнулся с этим зверем DS18B20 в общем то опросил стандартными функциями, температуру показывает, но динамическая индикация начинает дико тупить, вместо 100гц 1-2Гц. Есль ли какой нибудь простой выход или надо самому писать опрос этого термодатчика? И это 100% из-за опроса датчика. как только отключаю функции опроса все ОК.
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: CodeVision AVR в вопросах и ответах
Насколько мне известно, библиотека использует задержку типа delay(т.е. тупой простой МК). Я сам библиотекой для DS ни разу не пользовался. Попробуйте использовать библиотеку в основном теле программы и нырять в прерывания на короткое время, может что даст, если конечно библиотека не запрещает прерывания.
Есть интересный метод работы с 1-wire, через UART, т.е. аппаратно. Но там придется задействовать оба пина UART. Поищите, в инете полно инфы по этому поводу.
Есть интересный метод работы с 1-wire, через UART, т.е. аппаратно. Но там придется задействовать оба пина UART. Поищите, в инете полно инфы по этому поводу.
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
Думаю, дело в том, что динамическая развёртка реализована не на прерывании таймера (в отдельном, по сути, потоке), а тупо на задержках в основном цикле. Поэтому любое использование задержек, в том числе и библиотеки датчика, превращает динамическую задержку в тыкву.
Реализуйте развёртку на любом таймере, и проблема в принципе не возникнет.
Реализуйте развёртку на любом таймере, и проблема в принципе не возникнет.



