реклама на сайте
подробности

 
 
17 страниц V  « < 14 15 16 17 >  
Reply to this topicStart new topic
> Микроконтроллеры для начинающих, AVR, PIC, FUJITSU
lyric
сообщение Sep 22 2017, 06:03
Сообщение #226





Группа: Участник
Сообщений: 14
Регистрация: 29-01-16
Пользователь №: 90 250



Привет всем. Наверняка уже много раз этот вопрос поднимался, но не знаю как и где искать.

Программирую атмегу по интерфейсу JTAG. В программе я могу эти 4 ноги, занятые JTAGом, использовать как обычные входы/выходы?
Go to the top of the page
 
+Quote Post
Smoky
сообщение Sep 22 2017, 06:56
Сообщение #227


Местный
***

Группа: Свой
Сообщений: 401
Регистрация: 7-05-10
Из: Оренбург
Пользователь №: 57 135



Цитата(lyric @ Sep 22 2017, 12:03) *
Привет всем. Наверняка уже много раз этот вопрос поднимался, но не знаю как и где искать.

Программирую атмегу по интерфейсу JTAG. В программе я могу эти 4 ноги, занятые JTAGом, использовать как обычные входы/выходы?


При отладке программ нельзя, а в рабочем режиме имеется возможность. В регистрах MCUCSR или MCUCR имеется хитрый бит JTD, переключением которого можно эти порты использовать в рабочем режиме. Правда его переключение довольно своеобразное, как пишут в руководстве необходимо произвести запись бита дважды за четыре такта...


--------------------
Лень, оттвори дверь, сгоришь - а хоть и сгорю, но не оттворю.
Go to the top of the page
 
+Quote Post
lyric
сообщение Sep 22 2017, 07:22
Сообщение #228





Группа: Участник
Сообщений: 14
Регистрация: 29-01-16
Пользователь №: 90 250



Цитата(Smoky @ Sep 22 2017, 13:56) *
При отладке программ нельзя, а в рабочем режиме имеется возможность. В регистрах MCUCSR или MCUCR имеется хитрый бит JTD, переключением которого можно эти порты использовать в рабочем режиме. Правда его переключение довольно своеобразное, как пишут в руководстве необходимо произвести запись бита дважды за четыре такта...


Спасибо, попробую beer.gif
Go to the top of the page
 
+Quote Post
lyric
сообщение Oct 6 2017, 11:22
Сообщение #229





Группа: Участник
Сообщений: 14
Регистрация: 29-01-16
Пользователь №: 90 250



Здравствуйте, снова есть смешной (для сколь-нибудь опытных разработчиков) вопрос:

Снова про AVR, работаю в атмел студии 7.
Ниже привожу проект, который должен включать Порт B на 10 секунд, потом вЫключать на 10 секунд, снова включать и так далее.
Использую для этого таймер1 (16 бит).

Задача - понять как правильно использовать аппаратный таймер для создания, допустим, 30 своих независимых друг от друга программных таймеров с произвольными моментами включения и сброса для каждого из них в зависимости от состояния, допустим, какой-либо переменной в программе. Пока экспериментирую с одной переменной. МК работает на частоте 8МГц, от внутреннего источника, - как был, я его не калибровал и не знаю как это делать и надо ли вообще.. Делитель 256.

Код
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

unsigned int n_count=0;

void preset()
{
    DDRB = 0b11111111; // 0xFF
    PORTB = 0b11111111; // 0x00
    
        DDRD = 0b00001111; // 0xFF
        PORTD = 0b00000000; // 0x00
    
    DDRA = 0b00000000;
    PORTA = 0b11111111; // 0x00
}

void timer_ini(void)    //функция инициализации таймера
{
    TCCR1B |= (1<<WGM12); //установка режима работы CTC (сброс по совпадению)
    TIMSK1 |= (1<<OCIE1A); //устанавливаем бит разрешения прерывания первого счётчика по совпадению с OCIR1A (H и L)
    OCR1AH = 0b00001100; //записываем в регистр OCR1A число 3125 (при работе на частоте 8 МГц это будет давать прерывание каждые 0,1 сек)
    OCR1AL = 0b00110101; //
    TCCR1B |= (1<<CS12); //установка делителя 256
    
}

ISR(TIMER1_COMPA_vect) //Прерывание по достижению таймером значения регистра OCR1A (H и L)
{
n_count++;
if (n_count>=200)    {n_count=0;}
}

int main(void)
{
    preset();
    timer_ini();    
    sei(); //глобальное разрешение прерываний
    
    while(1)
    {
        if ((n_count>0)&&(n_count<100)) {PORTB = 0b11111111;}
else
    if ((n_count>100)&&(n_count<=200)) {PORTB = 0b00000000;};        
    }
}


И вот мой Порт В включается и выключается, - ДА, примерно каждые 10 секунд. Как измерил? - положил рядом с включаемым светодиодом свой телефон с запущенным секундомером. И Вот такой подсчёт времени в микроконтроллере даёт погрешность примерно 1 секунду в минуту. А за 4 минуты - МК уже врёт на 4 секунды - убегает вперёд относительно времени, которое на смартфоне...

Тогда я переставил код из бесконечного цикла в тело прерывания. Так МК убегает вперёд на 12 секунд за 10 минут... Это слишком большая погрешность.. Как быть? Это нормально и вызвана непостоянностью рабочей частоты? Погрешность эту можно как-то сократить? А если я 30 таких таймеров запилю - мне их все в этом же прерывании обрабатывать будет нормально или они, возможно, не будут успевать обрабатываться за прерывание?

Буду рад, примеру простого но более или менее точного программного таймера.

И ещё вопрос из фьюзов кроме CKDIV8 ещё какие-то влияют на рабочую частоту МК, если он работает от внутреннего генератора? То есть в моём случае есть всего 2 варианта частоты, - с включенным CKDIV8 это 1МГц, а с выключенным CKDIV8 это 8МГц и третьего не дано? Атмега644, если это важно.

Сообщение отредактировал lyric - Oct 6 2017, 12:54
Go to the top of the page
 
+Quote Post
Smoky
сообщение Oct 6 2017, 15:41
Сообщение #230


Местный
***

Группа: Свой
Сообщений: 401
Регистрация: 7-05-10
Из: Оренбург
Пользователь №: 57 135



Я бы не стал слишком сильно доверять телефонному секундомеру... Но если вы хотите опираться на него как на эталон, попробуйте поварьировать данные в регистре OCR1A. Одна единица этого регистра изменит ваши 10 сек на 3,2 мсек.


--------------------
Лень, оттвори дверь, сгоришь - а хоть и сгорю, но не оттворю.
Go to the top of the page
 
+Quote Post
x736C
сообщение Oct 6 2017, 17:33
Сообщение #231


Профессионал
*****

Группа: Участник
Сообщений: 1 273
Регистрация: 3-03-06
Пользователь №: 14 942



Возможно, у вас лишняя единица где-то еще.

Значение для таймера считается без единицы. В вашем случае:
timer_value = ([10] мс * 8000 [кГц] / 256) - 1 = 3124.
Эта ошибка уже добавляет лишние 320 мкс на одну секунду или 192 мс на 10 минут.

Вероятно, на следующем уровне иерархии, когда обрабатываете свои счетчики, допускаете ту же ошибку.

Цитата(lyric @ Oct 6 2017, 14:22) *
Как быть? Это нормально и вызвана непостоянностью рабочей частоты? Погрешность эту можно как-то сократить?

Такой погрешности быть не должно. То есть на глаз, если положить рядом секундомер, интервалы должны быть неотличимы.
Но это в том случае, если используете внешний кварцевый резонатор или генератор. Если внутренний RC-генератор, то все может быть иначе. Но проверить можно в AtmelStudio в режиме симуляции. Там есть возможность замерить интервалы работы участков кода. Только необходимо упростить пример, уменьшив значение, загружаемое в счетчик. Накопление погрешностей можно отследить. Все остальное будет из-за несовершенства RC-генератора. Его можно откалибровать, насколько помню. См. документацию.

Цитата(lyric @ Oct 6 2017, 14:22) *
А если я 30 таких таймеров запилю - мне их все в этом же прерывании обрабатывать будет нормально или они, возможно, не будут успевать обрабатываться за прерывание?

Это надо проверять, кто ж вам ответит. Но перегрузить прерывание, происходящее раз в 100 мс — это надо очень постараться.


Цитата(lyric @ Oct 6 2017, 14:22) *
И ещё вопрос из фьюзов кроме CKDIV8 ещё какие-то влияют на рабочую частоту МК, если он работает от внутреннего генератора? То есть в моём случае есть всего 2 варианта частоты, - с включенным CKDIV8 это 1МГц, а с выключенным CKDIV8 это 8МГц и третьего не дано? Атмега644, если это важно.

Далее идет делитель CLKPR, который может дальше поделить эту частоту.

Сообщение отредактировал x736C - Oct 6 2017, 17:37
Go to the top of the page
 
+Quote Post
lyric
сообщение Oct 10 2017, 07:51
Сообщение #232





Группа: Участник
Сообщений: 14
Регистрация: 29-01-16
Пользователь №: 90 250



Smoky, x736C

Большое спасибо, Ваши советы и замечания помогли. Ну и кроме того я сделал прерывание каждые 5 миллисекунд (вместо каждых 100), и инкрементируемую переменную указал volatile вместо unsigned. теперь секундомер смартфона один в один бьёт с тем, что отсчитывает МК, - на глаз никак не отличить. По моим расчётам погрешность за каждую секунду теперь составляет 2 микросекунды, а за 10 минут, соответственно, - 1,2 миллисекунды. Итого удалось уменьшить погрешность примерно в 10000 раз, неплохо rolleyes.gif
Go to the top of the page
 
+Quote Post
lyric
сообщение Aug 23 2018, 03:06
Сообщение #233





Группа: Участник
Сообщений: 14
Регистрация: 29-01-16
Пользователь №: 90 250



Здравствуйте.
Снова есть вопросы по AVR.

В программе сделал динамическую семисегментную индикацию через SPI, индикация вызывается в прерывании таймера каждые 2 миллисекунды.
И написал так же функцию, которая опрашивает все 8 каналов АЦП (без прерывания по окончанию преобразования). Эта функция вызывается в основном цикле, опрашивает 1 канал за такт. Для первых двух каналов АЦП в этой функции производятся довольно тяжёлые математические вычисления (оверсемплинг, фильтрация, аппроксимация по 2 точкам, коррекция) в переменных типа FLOAT. Ну и на время этих вычислений я запрещаю прерывания, соответственно индикаторы мерцают... А хотелось бы чтобы они горели с постоянной яркостью.

1а) Если НЕ запрещать прерывания, то прерывания могут испортить переменные в ОЗУ, которые в обработчике этого прерывания никак не участвуют?

1б) Если могут испортить - то, получается, мне в каждом куске основного цикла где есть работа с типами int16_t, int32_t, float - всегда запрещать прерывания?

2) В Atmel Studio 7, если использовать стандартные функции работы с EEPROM, то функция записи/обновления переменной в EEPROM сама отключает прерывания на время своей работы? Или это надо вручную перед вызовом этой функции запретить прерывания, а после выполнения функции - снова разрешать? В обработчике прерывания эти переменные так же не используются. Сейчас без запрета прерываний всё работает вроде, но боюсь что мне просто везёт, а хотелось бы знать наверняка. Можно ли где-то посмотреть сам текст этих стандартных функций работы с EEPROM? В хедер-файле EEPROM.h этого кода нет.

Сообщение отредактировал lyric - Aug 23 2018, 03:16
Go to the top of the page
 
+Quote Post
Plain
сообщение Aug 23 2018, 05:43
Сообщение #234


Гуру
******

Группа: Участник
Сообщений: 6 776
Регистрация: 5-03-09
Из: Москва
Пользователь №: 45 710



Во-первых, прерывания сами по себе ничего не портят, это просто условное ветвление программы, а во-вторых, в прерываниях надо делать только то, что в них действительно нуждается.

Узел EEPROM — это отдельная схема на кристалле микроконтроллера, она тактируется собственным тактовым генератором, поэтому всё делает сама и не зависит ни от чего. Также, после её озадачивания записью и до завершения всех процессов она включает помпу, повышающую напряжение питания, потому что для работы с ячейками памяти такого типа требуется относительно высокое напряжение, т.е. начинает потреблять указанный в паспорте существенный и дополнительный к общему ток на указанный в паспорте же интервал.
Go to the top of the page
 
+Quote Post
lyric
сообщение Aug 23 2018, 05:56
Сообщение #235





Группа: Участник
Сообщений: 14
Регистрация: 29-01-16
Пользователь №: 90 250



Plain

это значит что в моём случае запрещать прерывания не нужно ни при расчёте АЦП ни при записи EEPROM?

В обработчике прерывания таймера есть только то что касается индикации, и инкремент трёх переменных для создания программных таймеров в основном цикле.
Go to the top of the page
 
+Quote Post
Plain
сообщение Aug 23 2018, 06:58
Сообщение #236


Гуру
******

Группа: Участник
Сообщений: 6 776
Регистрация: 5-03-09
Из: Москва
Пользователь №: 45 710



Цитата(lyric @ Aug 23 2018, 08:56) *
запрещать прерывания не нужно

Естественно.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 23 2018, 07:55
Сообщение #237


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (lyric @ Aug 23 2018, 08:56) *
ни при записи EEPROM?
Прерывание может не только менять данные, но и нарушать временнЫе интервалы между командами. При записи в ЭСППЗУ нужно сделать две записи в регистр EECR, между которыми не должно быть больше четырех тактов процессора. Естественно, если после первой записи произойдет прерывание - ни о каких четырех тактах речь идти уже не будет. Поэтому вот именно перед первой записью в EECR прерывания должны быть запрещены, а после второй их уже можно разрешать.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
lyric
сообщение Aug 23 2018, 08:44
Сообщение #238





Группа: Участник
Сообщений: 14
Регистрация: 29-01-16
Пользователь №: 90 250



Цитата(Сергей Борщ @ Aug 23 2018, 14:55) *
Прерывание может не только менять данные, но и нарушать временнЫе интервалы между командами. При записи в ЭСППЗУ нужно сделать две записи в регистр EECR, между которыми не должно быть больше четырех тактов процессора. Естественно, если после первой записи произойдет прерывание - ни о каких четырех тактах речь идти уже не будет. Поэтому вот именно перед первой записью в EECR прерывания должны быть запрещены, а после второй их уже можно разрешать.


А если я использую стандартные функции работы с EEPROM, которые содержаться в компиляторе Атмел Студии, - всё равно вручную запрещать прерывания? Функция eeprom_update_word() сама этого не делает? Где-то можно посмотреть её код?

Сообщение отредактировал lyric - Aug 23 2018, 08:44
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 23 2018, 09:16
Сообщение #239


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (lyric @ Aug 23 2018, 11:44) *
А если я использую стандартные функции работы с EEPROM, которые содержаться в компиляторе Атмел Студии, - всё равно вручную запрещать прерывания?
Если она не запрещает прерывания - надо делать это вручную.
QUOTE (lyric @ Aug 23 2018, 11:44) *
Функция eeprom_update_word() сама этого не делает? Где-то можно посмотреть её код?
Самое простое - в листинге дизассемблера.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
lyric
сообщение Aug 23 2018, 10:55
Сообщение #240





Группа: Участник
Сообщений: 14
Регистрация: 29-01-16
Пользователь №: 90 250



Цитата(Сергей Борщ @ Aug 23 2018, 16:16) *
Если она не запрещает прерывания - надо делать это вручную.
Самое простое - в листинге дизассемблера.


Не запрещает. Придётся писать свою функцию записи/обновления EEPROM, видимо.
Спасибо за помощь, с EEPROM понятно a14.gif .

Подскажите пожалуйста ещё на эти вопросы:

Цитата(lyric @ Aug 23 2018, 10:06) *
1а) Если НЕ запрещать прерывания, то прерывания могут испортить переменные в ОЗУ, которые в обработчике этого прерывания никак не участвуют?

1б) Если могут испортить - то, получается, мне в каждом куске основного цикла где есть работа с типами int16_t, int32_t, float - всегда запрещать прерывания?


Какие ответы? rolleyes.gif

Сообщение отредактировал lyric - Aug 23 2018, 10:56
Go to the top of the page
 
+Quote Post

17 страниц V  « < 14 15 16 17 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 08:02
Рейтинг@Mail.ru


Страница сгенерированна за 0.01504 секунд с 7
ELECTRONIX ©2004-2016