Страница 1 из 1
А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 04:44:59
olovo
Итак только начинаю познавать АВР. разобрался с кодом программы программы, откомментировал каждую строчку в меру своего понимания. Поправьте плз если где не так мыслю. извиняюсь за глупый вопрос.
Код: Выделить всё
//модель мегии
#include <mega2313.h>
//частота кристала
#define _hz 4000000
//
//----------
interrupt(SIG_OVERFLOW1) // тут обрабатываем прерывание от таймера
{
//
TCNT1 = 0x10000 - (_hz/1024); // 65536(число переполнения таймера так как он 16бит) - частоту разделив на 1024 получаем 3906 - это насчитает таймер за секунду
PORTB ^= 0x01; //1 - т.е. в регистре у нас 00000001 и на ноге РСВ0 у нас напряжение
//
}
//----------
int main(void)
{
//
DDRB = 0x01; //направление передачи , в регистре 00000001, т.е. нога РСВ0 эявляется выходом
//для мазохизма пользуем сложный таймер Т/С1 в котором есть регистры сравнений
TCCR1A =0; // TCCR1A - заносим в регистр 0, отключаем ШИМ
TCCR1B = 5; // TCCR1B - ставим 5 или 101 (в регисьре значащие 3 разряда 0-2) тем самым устанавливая частоту тактирования таймера системная/10254 это 3906 тактов в секунду при частоте 4000000
TCN1 = 0x10000 - (_hz/1024); // ложим в регистр 61630 что б сработало на следующую секунду после запуска
TIFR = 0; //сбрасываем флаги прерываний
TIMSK = 0x80; // пишем в регистр 10000000 , разрешаем прерывание Т/С1
GIMSK = 0; // запрещаем внешние прерывания
sei(); //прерывания разрешены
while(1); //ждём прерывания таймера (сидим в бесконечном цыкле)
//
}
Re: А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 07:49:54
Engineer_Keen
olovo писал(а)://модель мегии
#include <mega2313.h>

это какая-такая мега??? Может все-таки тини?
Теперь что касается чисто АВР:
olovo писал(а):TCNT1 = 0x10000 - (_hz/1024); // 65536(число переполнения таймера так как он 16бит) - частоту разделив на 1024 получаем 3906 - это насчитает таймер за секунду
TIMER1 - 16 битный, больше чем 0xFFFF в него не положишь, компилятор или ругнется или скорее всего тупо обрежет лишние биты и получите вы там голый 0.
olovo писал(а):тем самым устанавливая частоту тактирования таймера системная/10254
/1024, внимательнее...
olovo писал(а):TIFR = 0; //сбрасываем флаги прерываний
Флаги сбрасываются записью "1", читайте даташит.
olovo писал(а):пишем в регистр 10000000
или 128 или 0х80 или
0b10000000, а то не понятно какая система счисления...
Re: А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 08:03:42
urry
TIMER1 - 16 битный, больше чем 0xFFFF в него не положишь, компилятор или ругнется или скорее всего тупо обрежет лишние биты и получите вы там голый 0.
здесь, кстати, правильно, но применение неверное,конечно.

Для вычисления значения таймера для требуемой частоты при переполнении используется формула
TIMER1 =65536 - Fin/Fout , где Fin - входная частота на таймер с учетом всех пределителей, Fout - требуемая частота.
Re: А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 08:16:03
Engineer_Keen
Да, совсем забыл что так можно частоту настраивать, последнее время просто использую для этого режим СТС...
Re: А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 16:26:41
olovo
Engineer_Keen
1. 10254

имел ввиду 1024
2. TCNT1 = 0x10000 - (_hz/1024); - вот тут прошу пояснить. мои мысли 0х10000 (65536 в десятичной) таймер посчитает 65535 и при следующем +1 обнулится. вот от него и высчитывается необходимое начальное значение таймера чтоб сбрасывался он каждую секунду, вызывая прерывание. и ещё просьба пояснить в чём неправильное использование такой конструкции?
3. TIFR = 0; - тут как понимаю в регистр флагов прерываний пишется как раз таки 0,а ноль во всех системах это ноль. как можно сбросить флаги занеся туда 1?????????
4. за системы счислений впредь буду использовать 0bХХХХХХХХ и 0хХХХХХХХХ
Re: А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 16:27:25
olovo
//модель мегии
#include <tiny2313.h>
тини так указывается? кодю в код вижин 2,6
Re: А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 17:00:16
olovo
Код: Выделить всё
//модель мегии
#include <tiny2313.h>
//частота кристала
#define _hz 4000000
//
//----------
interrupt [SIG_OVERFLOW1] // тут обрабатываем прерывание от таймера
{
//
TCNT1 = 0x10000 - (_hz/1024); // 65536(число переполнения таймера так как он 16бит) - частоту разделив на 1024 получаем 3906 - это насчитает таймер за секунду
PORTB ^= 0x01; //1 - т.е. в регистре у нас 00000001 и на ноге РСВ0 у нас напряжение
//
}
//----------
int main(void)
{
//
DDRB = 0x01; //направление передачи , в регистре 00000001, т.е. нога РСВ0 эявляется выходом
//для мазохизма пользуем сложный таймер Т/С1 в котором есть регистры сравнений
TCCR1A =0; // TCCR1A - заносим в регистр 0, отключаем ШИМ
TCCR1B = 5; // TCCR1B - ставим 5 или 101 (в регисьре значащие 3 разряда 0-2) тем самым устанавливая частоту тактирования таймера системная/1024 это 3906 тактов в секунду при частоте 4000000
TCN1 = 0x10000 - (_hz/1024); // ложим в регистр 61630 что б сработало на следующую секунду после запуска
TIFR = 0; //сбрасываем флаги прерываний
TIMSK = 0x80; // пишем в регистр 10000000 , разрешаем прерывание Т/С1
GIMSK = 0; // запрещаем внешние прерывания
sei(); //прерывания разрешены
while(1); //ждём прерывания таймера (сидим в бесконечном цыкле)
//
}
При компиляции ругается на interrupt [SIG_OVERFLOW1]
Error: C:\Documents and Settings\User\Desktop\ledD.c(7): undefined symbol 'SIG_OVERFLOW1'
Интересно какой же неопределённый символ в SIG_OVERFLOW1??? ведь SIG_OVERFLOW1 как понимаю из умных книжек - как раз таки и есть название прерывания которое инициализирует счетчик Т/С1 при сбросе в 0
Re: А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 17:25:33
Engineer_Keen
olovo писал(а):2. TCNT1 = 0x10000 - (_hz/1024); - вот тут прошу пояснить.
Тут все верно, это я неправильно прочитал...
olovo писал(а):3. TIFR = 0; - тут как понимаю в регистр флагов прерываний пишется как раз таки 0,а ноль во всех системах это ноль. как можно сбросить флаги занеся туда 1?????????
Вот именно так и не можно а нужно. Если нужно сбросить все флаги то писать надо соответственно 0b11111111, такая особенность АВР.
olovo писал(а):Интересно какой же неопределённый символ в SIG_OVERFLOW1???
Может как-то по -другому называется или в другом файле находится?
Re: А правильно ли я понял программу?!
Добавлено: Пт дек 14, 2012 17:49:41
olovo

кто кодит в CV! огромная просьба подсказать где лежат в нём эти файлы
Engineer_Keen писал(а):olovo писал(а):Интересно какой же неопределённый символ в SIG_OVERFLOW1???
Может как-то по -другому называется или в другом файле находится?
Re: А правильно ли я понял программу?!
Добавлено: Сб дек 15, 2012 02:03:13
vitalik_1984
Находятся они в месте под названием мастер кода, я вообще поражаюсь, есть мастер, трудно спросить у него?
Это такая серого цвета шестеренка где то в середине панели инструментов.
тупо выбираем контроллер, ставим галку на нужном прерывании, нажимаем на просмотр(кнопка в виде лупы левее такой же шестеренки как до этого нажали) и копируем нужную часть.
Этот символ не определен, потому что этому вектору нужно еще назначить подпрограмму, в которой будет происходить обработка, тело подпрограммы есть, а объявления то нет!
И тем более в CVAVR векторы по другому называются, отлично от даташита.
Re: А правильно ли я понял программу?!
Добавлено: Сб дек 15, 2012 17:00:49
olovo

Где же эта шестерёнка то?

Re: А правильно ли я понял программу?!
Добавлено: Сб дек 15, 2012 17:23:08
YS
Это стиль объявления прерываний для GCC, и то устаревший - сейчас используется макрос ISR(). Как объявить прерывание в CV - смотрите в туториалах.
Код: Выделить всё
PORTB ^= 0x01; //1 - т.е. в регистре у нас 00000001 и на ноге РСВ0 у нас напряжение
Это операция "исключающее или", проводимая над портом и значением 0x01. Каждый раз при выполнении этого кода состояние ножки будет меняться на противоположное. Это простой способ помигать диодом.
Re: А правильно ли я понял программу?!
Добавлено: Сб дек 15, 2012 23:42:25
olovo
УРА! скомпилилось
Код: Выделить всё
//модель мегии
#include <tiny2313.h>
//частота кристала
#define _hz 4000000
//
//----------
interrupt [TIM1_OVF] void timer1(void)// тут обрабатываем прерывание от таймера
{
//
TCNT1 = 0x10000 - (_hz/1024); // 65536(число переполнения таймера так как он 16бит) - частоту разделив на 1024 получаем 3906 - это насчитает таймер за секунду
PORTB ^= 0x01; //1 - т.е. в регистре у нас 00000001 и на ноге РСВ0 у нас напряжение
//
}
//----------
void main(void)
{
//
DDRB = 0x01; //направление передачи , в регистре 00000001, т.е. нога РСВ0 эявляется выходом
//для мазохизма пользуем сложный таймер Т/С1 в котором есть регистры сравнений
TCCR1A =0; // TCCR1A - заносим в регистр 0, отключаем ШИМ
TCCR1B = 5; // TCCR1B - ставим 5 или 101 (в регисьре значащие 3 разряда 0-2) тем самым устанавливая частоту тактирования таймера системная/1024 это 3906 тактов в секунду при частоте 4000000
TCNT1 = 0x10000 - (_hz/1024); // ложим в регистр 61630 что б сработало на следующую секунду после запуска
TIFR = 0; //сбрасываем флаги прерываний
TIMSK = 0x80; // пишем в регистр 10000000 , разрешаем прерывание Т/С1
GIMSK = 0; // запрещаем внешние прерывания
#asm
sei //прерывания разрешены
#endasm
while(1); //ждём прерывания таймера (сидим в бесконечном цыкле)
//
}
Re: А правильно ли я понял программу?!
Добавлено: Пн дек 17, 2012 00:50:04
vitalik_1984
olovo писал(а):Где же эта шестерёнка то?

У, как все запущено...
Качайте новую версию
Еще есть довольно понятный учебник по CVAVR.
Лебедев пособие для начинающих CVAVR
Re: А правильно ли я понял программу?!
Добавлено: Вт дек 18, 2012 04:39:26
zhv
olovo писал(а):...
TCN1 = 0x10000 - (_hz/1024); // ложим в регистр 61630 что б сработало на следующую секунду после запуска
.....
Где это видно из кода, что кладётся 61630?
Вообще мне, как начинающему, непонятно выражение у Лебедева на стр. 456
TCN1 = 0x10000 - (htal/1024/fmovie)
Как это понять? Делим частоту процессора htal на предделитель1024 и получаем частоту на входе в таймер (тактирования). Вроде понятно. Но затем это делится на fmovie- частоту, с которой должно происходить прерывание. И что получается? Когда одну частоту делишь на другую? А затем это выражение в скобках (htal/1024/fmovie) ещё и вычитаешь из числа 0x10000? И что получаем? Вообще-то догадываюсь что это число с которого счётчик начинает считать. Но арифметику не улавливаю. Проясните пожалуйста.
Re: А правильно ли я понял программу?!
Добавлено: Вт дек 18, 2012 08:24:27
Engineer_Keen
zhv писал(а):Где это видно из кода, что кладётся 61630?
0x10000=65536, _hz=4000000
TCN1 = 65536 - 4000000 / 1024 = 61629.75 ~ 61630
zhv писал(а):Делим частоту процессора htal на предделитель1024 и получаем частоту на входе в таймер (тактирования). Вроде понятно. Но затем это делится на fmovie- частоту, с которой должно происходить прерывание.
Да, чтобы получить такое значение счетчика, что считая с него, переполнение (следовательно и прерывание) произойдет с нужной нам частотой (fmovie). Арифметика такая: допустим нам нужно Fmovie=25Гц, тогда:
TCNT1=65536-4000000/1024/25=65380
получается что таймер начинает считать с 65380, и до переполнения, он просчитает: 65536-65380=156 тактов, один такт=1/(4000000/1024)=0.000256с, следовательно прерывание произойдет через 0.000256*156=0.0399с, что соответствует частоте 1/0.0399=25Гц.
Re: А правильно ли я понял программу?!
Добавлено: Ср дек 19, 2012 02:10:41
vitalik_1984
olovo писал(а):Где же эта шестерёнка то?

В вашей версии это шляпа волшебника
