CodeVision AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 375
Зарегистрирован: Чт июн 24, 2010 20:58:59

Сообщение ra9ust »

Ок.
Вложения
clock arduino 16.c
(9.73 КБ) 326 скачиваний
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 375
Зарегистрирован: Чт июн 24, 2010 20:58:59

Сообщение ra9ust »

Кстати вот код,прекрасно отрабатывает даже просто замыканием проводком вместо кнопки,

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 режимов по кругу.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

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(6);
a=(ADCH*0.389); // показатель преобразования из АЦП до 99
Функция read_adc() сама по себе должна возвращать значение АЦП, почему вы этим не пользуетесь? Ну и использовать числа с плавающей точкой без крайней необходимости не стоит.
Вообще, в main() какая-то каша, на мой взгляд. Без форматирования и комментариев сложно разобраться что же имелось в виду.
В прерывании Int1 напрашивается вынести проверку PC4 во внешний if или использовать массив переменных, что-то вроде if( PINC & (1<<4) )arr[w]++;
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 375
Зарегистрирован: Чт июн 24, 2010 20:58:59

Сообщение ra9ust »

Согласен что с нулевым битом мне тоже запись непонятна,хотя и работает,кто то подсказал так сделать, а вот ваш вариант с двоичным представлением порта конечно понятнее,буду знать. А комментарии кол генератора пока не стал убирать,а касаемо регистров таймеров и прочего то в самом начале изучения так и делал расписывая на бумаге регистр и вручную выставлял каждый бит согласно даташиту. С генератором кода однако удобнее да и значения не особо отличаются и мне так проще. Отступы и прочее я необрашал внимания,пока экспериментирую.ацп совсем бегло прочитал особо не вдаваясь поэтому написал пока так лишь бы работало. Еще месяц назад и понятия не имел как устроен контроллер и тем более что то написать на него.
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 375
Зарегистрирован: Чт июн 24, 2010 20:58:59

Сообщение ra9ust »

А вот насчет того что функция ацп сама может возвращать, можете примерно написать как оно должно быть применительно к моему варианту?
Реклама
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Ну как-то так

Код: Выделить всё

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;
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 375
Зарегистрирован: Чт июн 24, 2010 20:58:59

Сообщение ra9ust »

Так а я не использовал плавающую точку, выводятся только целые значения от 00 до 99.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

ra9ust писал(а):Так а я не использовал плавающую точку, выводятся только целые значения от 00 до 99.
0,389 по-вашему не число с плавающей точкой?
Я имел в виду скорее что-то типа такого
a = (unsigned char)( ( (unsigned int)read_adc(6)*100) >>8 );
Перевод в unsigned int нужен для корректного умножения на 100, потому что получается двухбайтное число, а 100/256 составляет как раз 0,39. Только работает на порядки быстрее умножения дробных чисел.
ra9ust писал(а):С генератором кода однако удобнее да и значения не особо отличаются и мне так проще. Отступы и прочее я необрашал внимания
Проще пока не понадобится что-то исправить. С форматированием тоже самое - когда захотите что-то исправить будете мучиться что к чему относится. Ну и выкладывать такое на всеобщее обозрение мне было бы стыдно, надо же уважать тех, кто хочет помочь.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

А 0.389 о это что, про-вашему, если не число с плавающей точкой? Вы представляете, насколько медленно и ресурсоёмко это на 8бит контроллере?
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 375
Зарегистрирован: Чт июн 24, 2010 20:58:59

Сообщение ra9ust »

Ну, ладно, мне например несложно искать и исправлять, все-таки каждому свое, а дробное число просто подогнал чтобы под 99 уместить,ну да ладно.Всё это эксперименты...
Встал на лапы
Сообщения: 148
Зарегистрирован: Ср дек 29, 2010 21:19:03

Сообщение c717411 »

CV 3.12

Код: Выделить всё

lcd_gotoxy(0,0);
lcd_puts(s); 
lcd_gotoxy(0,1);
lcd_puts(s);
простой код, выводит на LCD крякозябры в первой строке, вторая пустая. Если закомментировать первый gotoxy - выводит как надо первую строку, вторую пустую. Как починить?
Друг Кота
Аватара пользователя
Сообщения: 3059
Зарегистрирован: Пн май 11, 2009 14:15:00
Откуда: СПб

Сообщение *Trigger* »

Для начала - показать весь код. Откуда мы знаем, что там у Вас в строке s и как инициализирован дисплей?
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.
Вымогатель припоя
Аватара пользователя
Сообщения: 601
Зарегистрирован: Пт фев 13, 2009 20:58:13
Откуда: Донецк

Сообщение DataLife »

Доброго времени суток.
Помоги, пожалуйста, разобраться.

Стоит задача в измерении частоты импульсов и их длины (продолжительности).
Перечитал много статей, решил воспользоваться материалом отсюда. Таймер в режиме захвата и так далее...

Вышел вот такой код:
Спойлер/*****************************************************
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 с простым кодом:
Спойлерwhile (1)
{ // 33 гц
PORTB.0 = 1;
delay_ms(10);
PORTB.0 = 0;
delay_ms(20);

}
Порт на выход стоит.
Так же, пробовал тактировать кнопкой. Всё та же белеберда на дисплее...
Не могу понять, где сидит проблема...
Подскажите, пожалуйста...
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Встал на лапы
Сообщения: 148
Зарегистрирован: Ср дек 29, 2010 21:19:03

Сообщение c717411 »

DataLife писал(а): Не могу понять, где сидит проблема...
Разбейте программу на кусочки. Получите сперва нужное значение частоты. Переменным, изменяющимся в разных прерываниях, на всякий пожарный лучше поставить модификатор volatile.
Встал на лапы
Сообщения: 88
Зарегистрирован: Чт мар 27, 2008 12:05:14

Сообщение maxn »

Вопрос новичка - подскажите, вот эти библиотеки http://arduino.ru/forum/proekty/modbusr ... i-owen-plc можно заюзать в CodeVision ?
И нужен ли для них какой-то особый микроконтроллер или подойдет любой AVR типа ATMEGA328P
или можно юзать среду разработки Arduino для любых AVR ?
Мучитель микросхем
Сообщения: 403
Зарегистрирован: Ср янв 26, 2011 17:00:30

Сообщение prw07 »

Как отредактировать существующий проект через генератор кода ?
Т.е. Имеется проект. Хочу внести изменения в программе при помощи генератора проекта. Захожу в КодеВизард. Открываю .cwp файл. Вношу изменения. Теперь если сгенерировать код (Generate, Save and Exit), то в IDE будет "чистая" программа сгенерированная КодеВизардом. Мне надо, что бы был мой код с соответствующими изменениями. Если просто вставлять в свой код то что сгенерировал КодеВизард, то файлы .cwp и .prj будут без изменений.
Прорезались зубы
Сообщения: 218
Зарегистрирован: Ср дек 02, 2015 15:06:01

Сообщение BEST-83154 »

вот тут вписан вольтметр,амперметр,ваттметр,таймер и разложения чисел
и мне хотелось бы видеть еще и замер емкости акб в А/Ч
кто может помогите!!!
Вложения
45.c
(5.22 КБ) 363 скачивания
Вымогатель припоя
Аватара пользователя
Сообщения: 508
Зарегистрирован: Пт фев 22, 2013 18:00:43
Откуда: Беларусь, г. Гомель

Сообщение rxstart1 »

Люди нужна помощь. Впервые столкнулся с этим зверем DS18B20 в общем то опросил стандартными функциями, температуру показывает, но динамическая индикация начинает дико тупить, вместо 100гц 1-2Гц. Есль ли какой нибудь простой выход или надо самому писать опрос этого термодатчика? И это 100% из-за опроса датчика. как только отключаю функции опроса все ОК.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Насколько мне известно, библиотека использует задержку типа delay(т.е. тупой простой МК). Я сам библиотекой для DS ни разу не пользовался. Попробуйте использовать библиотеку в основном теле программы и нырять в прерывания на короткое время, может что даст, если конечно библиотека не запрещает прерывания.
Есть интересный метод работы с 1-wire, через UART, т.е. аппаратно. Но там придется задействовать оба пина UART. Поищите, в инете полно инфы по этому поводу.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Думаю, дело в том, что динамическая развёртка реализована не на прерывании таймера (в отдельном, по сути, потоке), а тупо на задержках в основном цикле. Поэтому любое использование задержек, в том числе и библиотеки датчика, превращает динамическую задержку в тыкву.

Реализуйте развёртку на любом таймере, и проблема в принципе не возникнет.
Контактная информация:
Ответить

Вернуться в «AVR»