Нескольно простых вопросов о программировании AVR на Си.

Обсуждаем контроллеры компании Atmel.
Ответить
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

Ну почему же! Спорт у каждого свой. Как и смысл.)
Реклама
Родился
Сообщения: 17
Зарегистрирован: Чт сен 12, 2024 21:34:21
Откуда: Москва

Сообщение elektronic3452 »

Добрый вечер! Форумчане!!!
Я начинающий! Можете подсказать что значит строка PORTC = 0x3F & led_buff[0]; в этом коде?



#include <mega8.h>
#include <delay.h>

#define ON 1
#define OFF 0
#define timer_ TCNT0
#define timer_tact TCCR0
#define OUT PORTB.0

#define enable PINB.3
#define up PINB.4
#define down PINB.5
#define pwm__ OCR1AL

#define klapan PORTB.2
#define motor_stop {PORTB.1=0;}
#define motor_tormoz {PORTD.4=1;}
#define motor_tormoz_off {PORTD.4=0;}

bit flags_button=0;
volatile unsigned char sek_;
volatile unsigned char timer_button, timer_butt;
volatile unsigned char timer_shou;
volatile unsigned char timer_stop;
volatile unsigned char eep_timer;
volatile unsigned char sek;
volatile unsigned char timer;
volatile unsigned char y,jamp2=0;
volatile unsigned int pwm, start_;



volatile unsigned char pwm_, data0, data1, data2, led_buff[3];
//--------------- 0-9 10 ........... 18 символов
//Символы для LED (0-9, ,-,t,L,A,r,d,b,DP)
flash unsigned char led_table[26]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0x87,0xC7,0x88,0xAF,0xA1,0x83,0x7F,0x8C,0xC6,0xC1,0x86,0x89,0x8E,0x9C};
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// [] - t L A r d b Dp P C U E H F град.

//volatile unsigned char y, jamp2=0;
volatile unsigned char start=180;

eeprom unsigned char eep_power, eep_jamp, eep_pwm, eep_sek;

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void) // прерывание для захвата перехода через ноль.
{
// Place your code here Процедура обслуживания внешнего прерывания 0

OUT=OFF;
timer_=start;

}

// Timer 0 overflow interrupt service routine Процедура обслуживания прерывания переполнения таймера 0
interrupt [TIM0_OVF] void timer0_ovf_isr(void) // прерывание для выхода управления тиристорами
{
// Place your code here Разместите свой код здесь
timer_=start;
OUT=ON;
}

// Timer2 overflow interrupt service routine Процедура обслуживания прерывания переполнения Таймера 2
interrupt [TIM2_OVF] void timer2_ovf_isr(void) // прерывание для дисплея
{
// Reinitialize Timer2 value Повторно инициализировать значение Таймера2
TCNT2=0xCB;

if (jamp2==0)
{
PORTD.5=PORTD.6=PORTD.7=0; // выключаем все разряды

switch (y) // общий анод
{

case 0:

PORTC = 0x3F & led_buff[0];
PORTD.0 = 0x40 & led_buff[0];
PORTD.1 = 0x80 & led_buff[0];
Реклама
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

Вы бы, прежде чем постить, посмотрели бы как люди код вставляют в сообщение.
Вымогатель припоя
Сообщения: 596
Зарегистрирован: Ср янв 06, 2010 10:01:46

Сообщение metan »

elektronic3452 писал(а):что значит строка PORTC = 0x3F & led_buff[0]; в этом коде
вывод в PORTC значения из нулевого элемента массива led_buff c обнулением двух старших битов
Последний раз редактировалось metan Пт сен 13, 2024 09:13:18, всего редактировалось 1 раз.
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Не путайте. В массиве ничего не обнулиться.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Вымогатель припоя
Сообщения: 596
Зарегистрирован: Ср янв 06, 2010 10:01:46

Сообщение metan »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=4624861#p4624861"]Не путайте.[/uquote]извиняюсь, неверно выразил свою мысль, поправил
Реклама
Родился
Сообщения: 17
Зарегистрирован: Чт сен 12, 2024 21:34:21
Откуда: Москва

Сообщение elektronic3452 »

Спасибо!!! "metan" и "Z_h_e"!
Поставщик валерьянки для Кота
Сообщения: 2199
Зарегистрирован: Вс ноя 15, 2009 23:13:59
Откуда: Харьков

Сообщение watchmaker »

Немного нубский вопрос, но всё же. ATtiny85. Чип просыпается по внешнему прерыванию на пине PB2, затем сразу же в обработчике прерывания это самое прерывание отключается (PCMSK = 0), а включается обратно (PCMSK = 0b100) существенно позже, перед уходом в спящий режим. Делаю это для того, чтобы постоянно меняющийся уровень на пине (а там летит извне меандр 4 кГц) не вызывал сотни прерываний в секунду при работе основной программы, от них программа тормозит (чип работает на 128 кГц). Контроллер зависает намертво в спящем режиме второй раз за неделю, реагирует только на ресет. Безопасно ли отключать прерывание в обработчике этого же прерывания? И может ли быть такое, что при установке бита в PCMSK прерывание не включается или включается не сразу?
Иногда мой питомец уходит в такую спячку, что разбудить его можно только щелчком по первой ноге...
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

Внутри прерывания ничего отключать не надо - т.к. пока ты в прерывании сбрасывается регистр "I" (глобальное разрешение прерываний)
а вот флаг прерывания в конце прерывания очистить наверно не повредит (зависит от решаемой задачи), это исключит повторный вызов прерывания сразу после его завершения если события, вызывающие прерывание, происходили во время прерывания. (флаг прерывания очищается записью в него "1")
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
VNS
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1633
Зарегистрирован: Пт дек 10, 2021 12:48:46
Откуда: Тюмень

Сообщение VNS »

[uquote="watchmaker",url="/forum/viewtopic.php?p=4706302#p4706302"]ATtiny85. Чип просыпается по внешнему прерыванию на пине PB2,[/uquote]
Уточните, от какого прерывания просыпается МК, от INT0 или от PCIE0?
Делаю это для того, чтобы постоянно меняющийся уровень на пине (а там летит извне меандр 4 кГц) не вызывал сотни прерываний в секунду
То есть, этот меандр будит ваш МК?
Контроллер зависает намертво в спящем режиме второй раз за неделю,
Контроллер в спящем режиме (Power-down) и так всегда «весит», то есть "спит и ничего не делает", экономит энергию… :) вы наверное хотите сказать, что не могли его разбудить два раза за неделю? Дело в том, что для пробуждения МК необходимо удерживать низкий уровень на пине достаточное время, чтобы МК включил питание и запустил тактовый генератор (завершил полностью пробуждение). Если продолжительности уровня на пине не достаточно, то МК может и проснуться, но прерывание не будет сгенерировано. Обратите внимание в даташите какое время необходимо МК для полного пробуждения.
akl
Друг Кота
Сообщения: 4462
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

watchmaker писал(а):Безопасно ли отключать прерывание в обработчике этого же прерывания?
Отключайте безопасно.
Последний раз редактировалось akl Сб апр 19, 2025 04:34:16, всего редактировалось 1 раз.
Поставщик валерьянки для Кота
Сообщения: 2199
Зарегистрирован: Вс ноя 15, 2009 23:13:59
Откуда: Харьков

Сообщение watchmaker »

Уточните, от какого прерывания просыпается МК, от INT0 или от PCIE0?
ISR(PCINT0_vect)
То есть, этот меандр будит ваш МК?
Да, МК подключён к выходу пищалки в электронных часах и просыпается от такого сигнала.
Контроллер в спящем режиме (Power-down) и так всегда «весит», то есть "спит и ничего не делает", экономит энергию… :) вы наверное хотите сказать, что не могли его разбудить два раза за неделю?
Виснет так, что не разбудишь даже подачей постоянного уровня на пин, как будто прерывание не включилось при уходе в слип. Если конечно это вообще не аппаратные проблемы типа помех по питанию.
Иногда мой питомец уходит в такую спячку, что разбудить его можно только щелчком по первой ноге...
Контактная информация:
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

[uquote="watchmaker",url="/forum/viewtopic.php?p=4706384#p4706384"]Виснет так, что не разбудишь даже подачей постоянного уровня на пин, как будто прерывание не включилось при уходе в слип. Если конечно это вообще не аппаратные проблемы типа помех по питанию.[/uquote]
На пьезо какое напряжение? Бывает их раскачивают...
Поставщик валерьянки для Кота
Сообщения: 2199
Зарегистрирован: Вс ноя 15, 2009 23:13:59
Откуда: Харьков

Сообщение watchmaker »

Пьезо там уже нет, сигнал запуска с часового чипа идёт прямо на МК, а с МК совсем другой сигнал идёт через мосфет на 32 Ом динамик.
Иногда мой питомец уходит в такую спячку, что разбудить его можно только щелчком по первой ноге...
Контактная информация:
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

Я имею ввиду входное напряжение. И пофигу ваши динамики.
VNS
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1633
Зарегистрирован: Пт дек 10, 2021 12:48:46
Откуда: Тюмень

Сообщение VNS »

[uquote="watchmaker",url="/forum/viewtopic.php?p=4706384#p4706384"]ISR(PCINT0_vect)[/uquote]
Тогда (ИМХО) правильней использовать не регистр PCMSK в вашем случае, а регистр GIMSK (бит PCIE) для разрешения или запрета прерывания по маске пинов, а выбор пина (PCMSK) не трогать. Ну и не забывать при установке (PCIE), сбрасывать бит прерывания (PCIF).

Ну и сформировать достаточный временной потенциал для полного пробуждения МК.
Поставщик валерьянки для Кота
Сообщения: 2199
Зарегистрирован: Вс ноя 15, 2009 23:13:59
Откуда: Харьков

Сообщение watchmaker »

Я имею ввиду входное напряжение. И пофигу ваши динамики.
3 В, как и на МК.
Тогда (ИМХО) правильней использовать не регистр PCMSK в вашем случае, а регистр GIMSK (бит PCIE) для разрешения или запрета прерывания по маске пинов, а выбор пина (PCMSK) не трогать. Ну и не забывать при установке (PCIE), сбрасывать бит прерывания (PCIF).
Попробую.
Кстати, в даташите написано, что этот флаг сбрасывается записью в него единицы. Это не опечатка, надо писать именно единицу?
Иногда мой питомец уходит в такую спячку, что разбудить его можно только щелчком по первой ноге...
Контактная информация:
VNS
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1633
Зарегистрирован: Пт дек 10, 2021 12:48:46
Откуда: Тюмень

Сообщение VNS »

[uquote="watchmaker",url="/forum/viewtopic.php?p=4706623#p4706623"]Это не опечатка, надо писать именно единицу?[/uquote]
Не опечатка, да "1".
Открыл глаза
Сообщения: 46
Зарегистрирован: Пт дек 02, 2022 00:37:17

Сообщение fomkin1912 »

Памагите! Вопрос тупой, но все извилины заплел.
Запрограммировал секундомер на Атмеге8 по учебному примеру, и все заработало. Но как?? как он работает???
В счетчике времени (переменная "display") установлена задержка 10мс - это 1/100 секунды (это точно, верьте - я уже на калькуляторе проверял). То есть счетчик увеличивается на единицу каждую сотую секунды, а на индикатор выводятся десятые! Почему???
Вот программа:
// Подключение семисегментных индикаторов к AVR. Динамическая индикация
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

//---------------------------0-----1-----2-----3-----4-----5-----6-----7-----8------9
unsigned char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

unsigned char segcounter = 0;
unsigned int display = 0;

// Обработчик прерывания по переполнению таймера 2
ISR(TIMER2_OVF_vect)
{
PORTD = 0xFF; // Гасим все разряды
PORTB = (1 << segcounter); // Выбираем следующий разряд

switch(segcounter)
{
case 0:
PORTD = ~(SEGMENTE[display % 10000 / 1000]); // Раскладываем число на разряды
break;
case 1:
PORTD = ~(SEGMENTE[display % 1000 / 100]);
break;
case 2:
PORTD = ~(SEGMENTE[display % 100 / 10]);
break;
case 3:
PORTD = ~(SEGMENTE[display % 10]);
break;
}
if(segcounter++ > 2) segcounter = 0;
}
// Главная функция
int main(void)
{
DDRB = 0xFF; // Порт B - выход
PORTB = 0x00;
DDRD = 0xFF; // Порт D - выход
PORTD = 0x00;

TCCR2 |= (1 << CS21); // Предделитель на 8
TIMSK |= (1 << TOIE2); // Разрешение прерывания по таймеру 2

sei(); // Глобально разрешаем прерывания

while(1)
{
display++; // Увеличиваем счет от 0 до 9999
if(display > 9999) display = 0;
_delay_ms(10); // Задержка
}
}
Последний раз редактировалось Аlex Чт ноя 06, 2025 16:23:49, всего редактировалось 1 раз.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Выведите, для начала, константу. И посмотрите, что выводится. Если не то, что нужно, - пошаговая отладка спасёт.
И, блин, ну что за форматирование ? Глаз дёргается.
Минута в интернете и всё красиво :
Спойлер

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

// Подключение семисегментных индикаторов к AVR. Динамическая индикация
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

// Массив кодов для семисегментного индикатора (цифры 0-9)
unsigned char SEGMENTE[] = {
    0x3F, // 0
    0x06, // 1
    0x5B, // 2
    0x4F, // 3
    0x66, // 4
    0x6D, // 5
    0x7D, // 6
    0x07, // 7
    0x7F, // 8
    0x6F  // 9
};

unsigned char segcounter = 0;
unsigned int display = 0;

// Обработчик прерывания по переполнению таймера 2
ISR(TIMER2_OVF_vect)
{
    PORTD = 0xFF; // Гасим все разряды
    PORTB = (1 << segcounter); // Выбираем следующий разряд
    
    switch(segcounter)
    {
        case 0:
            PORTD = ~(SEGMENTE[display % 10000 / 1000]); // Тысячи
            break;
        case 1:
            PORTD = ~(SEGMENTE[display % 1000 / 100]); // Сотни
            break;
        case 2:
            PORTD = ~(SEGMENTE[display % 100 / 10]); // Десятки
            break;
        case 3:
            PORTD = ~(SEGMENTE[display % 10]); // Единицы
            break;
    }
    
    if(segcounter++ > 2)
        segcounter = 0;
}

// Главная функция
int main(void)
{
    // Настройка портов
    DDRB = 0xFF;  // Порт B - выход (выбор разряда)
    PORTB = 0x00;
    DDRD = 0xFF;  // Порт D - выход (сегменты)
    PORTD = 0x00;
    
    // Настройка таймера 2
    TCCR2 |= (1 << CS21);  // Предделитель на 8
    TIMSK |= (1 << TOIE2); // Разрешение прерывания по таймеру 2
    
    sei(); // Глобально разрешаем прерывания
    
    // Основной цикл
    while(1)
    {
        display++; // Увеличиваем счет от 0 до 9999
        
        if(display > 9999)
            display = 0;
            
        _delay_ms(10); // Задержка
    }
}
Ответить

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