Proteus: вопросы и ответы
- Сообщения: 232
- Зарегистрирован: Чт янв 01, 2015 13:44:12
Доброго времени суток! Поддерживаю вопрос Valeriy L по поводу можно ли сделать видными скрытые выводы микроконтроллеров (в моем случае AVR )... Видел графу где можно в письменном виде задать контакт к которому присоединить скрытый вывод, но что то это не то... Пробовал писать к примеру резистор, после этого под микроконтроллером появилась надпись VCC-R10 -следовательно появилась связь между выводом VCC и резистором R10... Но в данном случае не понятно с каким из выводов резистора VCC соединилось?
Все гениальное - просто
- Реклама
- Сообщения: 281
- Зарегистрирован: Пт ноя 15, 2013 20:58:23
Valeriy L писал(а):как сделать активными выводы питания Vdd и GND для PIC12F629. Что-бы я их мог использовать в проекте.
Тэкс, кто третьим будет??? В стопитьсотый раз повторюсь, в том числе и здесь на Коте - не парьте себе и другим мосК. Видимость выводов МК никаких преимуществ Вам не даст, поскольку использовать их как активные, т.е. управлять через них питанием МК Вы не сможете. Так задуманы и реализованы модели. Если про Пики в хелпе Лабцентр об этом скромно умолчал, то для AVR чётко прорисано (см. раздел AVR MODEL HELP -> General Model Limitations):CB1 писал(а):Поддерживаю вопрос Valeriy L по поводу можно ли сделать видными скрытые выводы микроконтроллеров (в моем случае AVR )...
Там есть и другие ограничения, касающиеся питания, в частности BOR. Я уже неоднократно и объяснял, как такое обойти - есть вывод RESET (у PIC - MCLR) - вот на него "тумблер" на землю - им и гасите, эффект практически тот же.Power supply voltage changing is not supported.
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
Начал изучать микроконтроллеры и решил освоить прерывания, хочу сделать задержку без delay_ms().
У меня появился вопрос насколько точно работает осциллограф в протеусе? Можно ли доверять ему?
Хочу сделать таймер на прерывании как можно точнее.
Приведу два примера: один с использованием delay_ms() второй с использованием прерывания.
С использование delay_ms()

С использованием прерывания

У меня появился вопрос насколько точно работает осциллограф в протеусе? Можно ли доверять ему?
Хочу сделать таймер на прерывании как можно точнее.
Приведу два примера: один с использованием delay_ms() второй с использованием прерывания.
С использование delay_ms()
Код: Выделить всё
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRC |= (1<<5);
PORTC |= (1<<5);
while(1)
{
_delay_ms(20);
PORTC ^= (1<<5);
}
}
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
unsigned long long millis = 0; //От 0 до 18 446 744 073 709 551 615
unsigned long long prevMillis = 0;
ISR (TIMER2_COMP_vect)
{
millis++; //миллисекунды
}
void timer2_init (void)
{
//*** Настройки для 8MHz ***//
TCCR2 |= (1<<1) | (1<<0); //установка предделителя = 64
TIMSK |= (1<<7); //разрешает прерывания по событию совпадение
TCCR2 |= (1<<3); //сброс при совпадении TCNT2 с OCR2
OCR2 = 249; //подгонялось вручную для 8MHz
TCNT2 = 0b00000000; //т.к. счетчик уже считает, то сброс счетчика после настройки.
}
void port_init (void)
{
DDRC |= (1<<5);
PORTC |= (1<<5);
}
int main(void)
{
timer2_init(); //настройка таймера2 для подсчета миллисекунд
port_init(); //настройка портов
sei(); //разрешение прерываний
while(1)
{
if (millis - prevMillis > 20)
{
prevMillis = millis;
PORTC ^= (1<<5); //инверсия одного бита
}
}
}
Плохой подход.Код: Выделить всё
millis++; //миллисекунды .............. .............. if (millis - prevMillis > 20)
1. Никогда не забывайте об атомарном доступе к многобайтным переменным.
2. Представьте, что произойдёт, когда переменная millis переполнится.
Можно. По крайней мере, до десятых (а может и сотых) микросекунд точно будет мерить.Можно ли доверять ему?
ЗЫ: В протеусе, для таких случаев, есть инструмент - COUNTER TIMER. Им можно мерить длину импульса с разрешением в 1 us.
ЗЫЗЫ: А вообще, по протеусу, так то, уже существует тема. Давайте туда "переедем" ?
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
Понял, буду задавать вопросы в той теме.ЗЫЗЫ: А вообще, по протеусу, так то, уже существует тема. Давайте туда "переедем" ?
Может быть я не правильно рассчитал переполнение переменной? Но вроде бы она очень не скоро должна переполниться, разве нет? unsigned long long millis переполнится через 5849,42 лет верно?Плохой подход.
1. Никогда не забывайте об атомарном доступе к многобайтным переменным.
2. Представьте, что произойдёт, когда переменная millis переполнится.
Каким образом тогда можно выполнить задержку без _delay_ms() и ей подобных ф-й?
- Реклама
Если она 8 байт, то действительно что-то очень долго получается. Контроллер успеет сгнить 1000 разНо вроде бы она очень не скоро должна переполниться, разве нет?
Тогда всё нормально. Только об атомарном доступе позаботьтесь и всё.
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
Можно запретить прерывания. Я правильно понимаю?Тогда всё нормально. Только об атомарном доступе позаботьтесь и всё.
Код: Выделить всё
while(1)
{
cli()
if ((millis - prevMillis) > 20)
{
prevMillis = millis;
PORTC ^= (1<<5); //инверсия одного бита
}
sei()
}
Код: Выделить всё
__monitor unsigned long get_system_timer(void)
{
return system_timer;
}
Правильно.Можно запретить прерывания. Я правильно понимаю?
Только прерывания достаточно запрещать на время работы с переменной, используемой в прерывании. На весь кусок запрещать нет смысла.
Просто создайте функцию, запрещающую прерывание на время чтения переменной и возвращающую это значение.Хотелось бы сделать такую же функцию в Atmel Studio. Как это можно сделать?
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
Так можно сделать?Аlex писал(а):Просто создайте функцию, запрещающую прерывание на время чтения переменной и возвращающую это значение.
Код: Выделить всё
unsigned long long get_millis(void)
{
cli();
return millis;
sei();
}
Неужели попробовать будет дольше, чем ждать ответа на форуме ? 
ЗЫ: После return, дальше, программа не выполняется. Вот и думайте, можно так или нет
ЗЫ: После return, дальше, программа не выполняется. Вот и думайте, можно так или нет
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
Попробовать конечно не сложно, только у меня из-за return и появился вопрос. Тогда может быть так?Аlex писал(а):Неужели попробовать будет дольше, чем ждать ответа на форуме ?
ЗЫ: После return, дальше, программа не выполняется. Вот и думайте, можно так или нет
Код: Выделить всё
unsigned long long get_millis(void)
{
cli();
unsigned long long tmp = millis;
sei();
return tmp
}
Но при отладке видно же докуда (не)доходит программа.
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
Действительно)Аlex писал(а):Но при отладке видно же докуда (не)доходит программа.
Мой последний кусок кода будет правильным?
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
Я наверное задаю вопросы быстрее чем думаю
Нашел в Atmel studio окошко Processor там есть Status register и 7-й бит Global interrupt enable
Нашел в Atmel studio окошко Processor там есть Status register и 7-й бит Global interrupt enable
изучить документацию на WinAVR и использовать макрос ATOMIC_BLOCK:Ellissar писал(а):Хотелось бы сделать такую же функцию в Atmel Studio. Как это можно сделать?
Код: Выделить всё
#include <ulil/atomic.h>
ATOMIC_BLOCK(ATOMIC_RESTORE_STATE){
// тут пишется код, который будет выполнен атомарно
}если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
ATOMIC_BLOCK интересная штука, но в неё тоже нельзя включить return millis;. Поэтому решил использовать cli() и sei().
в нее можно включать return что угодно!!!
а вот ваш вариант с cli-sti может дать побочный эффект, потому как уже вам нужно будет контролировать, были ли разрешены прерывания перед обращением к вашей функции или нет, потому как ваша функция всегда БУДЕТ разрешать прерывания, или наоборот, БУДЕТ их запрещать.
ATOMIC_BLOCK в показанном мной варианте использования всегда восстановит то состояние прерываний, которое было до обращения к нему. вдумайтесь
а вот ваш вариант с cli-sti может дать побочный эффект, потому как уже вам нужно будет контролировать, были ли разрешены прерывания перед обращением к вашей функции или нет, потому как ваша функция всегда БУДЕТ разрешать прерывания, или наоборот, БУДЕТ их запрещать.
ATOMIC_BLOCK в показанном мной варианте использования всегда восстановит то состояние прерываний, которое было до обращения к нему. вдумайтесь
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 135
- Зарегистрирован: Чт май 09, 2013 10:50:04
пробую так:ARV писал(а):в нее можно включать return что угодно!!!
Код: Выделить всё
unsigned long long get_millis(void)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
return millis;
};
}
Работает нормально только в таком виде
Код: Выделить всё
unsigned long long get_millis(void)
{
unsigned long long tmp;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
tmp = millis;
};
return tmp;
}
Не, ну всегда же можно прочитать состояние, а потом восстановить.ATOMIC_BLOCK в показанном мной варианте использования всегда восстановит то состояние прерываний, которое было до обращения к нему. вдумайтесь
"Горшки тоже не боги обжигают" (с)
Я что-то делаю не так?
А макрос тоже "человек", ему тоже хочется закончиться до концаАlex писал(а): После return, дальше, программа не выполняется !
Если у вас в программе всегда будут разрешены прерывания, то не парьтесь, сделайте просто запрет-разрешение. Если хотите по-нормальному, то до запрета читайте бит разрешения прерываний, сохраняйте его, а потом вместо разрешения - восстанавливайте.


