Jump to content
Сергей Фомин

Расчёт таймера на attiny13

Recommended Posts

Изучаю прерывания на attiny13. Пока остановился на прерываниях по переполнению. Сделал тестовый код в Atmel Studio и сразу через программатор заливаю на тиньку со светодиодом. Проблема в том что гореть он должен 10 секунд и выключаться, а горит примерно 20-23 секунды. Прошу помощи в правильном расчёте. Код ниже (пока учусь сильно не ругайтесь) :

#define F_CPU 1000000
#define LED PB2
#include <avr/io.h>
//#include <util/delay.h>
#include <avr/interrupt.h>
unsigned char work_time =384;    //  1000000/1024/256=3.8  (0.026 сек)    10/0.026=384
volatile unsigned char temp =0;


ISR (TIM0_OVF_vect)
{ 
    TCNT0=0x00;
    temp ++;
    if (temp>=work_time)
    {
        PORTB &=~(1<<LED);  //Инвертируем состояние
        TCCR0B=0x00    // остановка таймера
        cli (); //общее запрещение прерываний
    }
}

int main (void)
{

    init();
    
    
    while (1)
    {
        
    }
}


void init ()
{
    
    DDRB |= (1<<LED); // выход
    PORTB =(1<<LED); //включен
    TCCR0B =0x05; // установка делителя на 1024
    TIMSK0 |= _BV(TOIE0);
    sei();   // Либо SREG |= (1<<SREG_I); //Разрешаем прерывания глобально
    TCNT0 = 0X00;        //Обнулить счётный регистр

}

 

Edited by admin
Тэг CODE для кого?

Share this post


Link to post
Share on other sites
16 hours ago, Сергей Фомин said:

в правильном расчёте

Во-первых

unsigned char work_time =384;

в переменную типа unsigned char нельзя положить значение более 255, величина 384 там просто не поместится и обрежется до 384 - 256 = 128. То есть  у Вас получается work_time =128;

Во-вторых, при расчёте времени переполнения  1000000/1024/256=3.8 допущена ошибка:

1/3.8 = 0.26 сек, а не 0.026 сек

Поэтому  work_time = 10 / 0.26 = 38;

Тут, кстати, значение 38 уже легко поместится в unsigned char.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Similar Content

    • Guest vit2700
      By Guest vit2700
      Доброго дня всем гуру  программирования в BASCOM AVR !  В программировании я также как и в космической отрасли ... Увлекаюсь рыбалкой, использую электронные сигнализаторы поклевки (китайские). У меня их с приказавшим долго жить микроконтроллером уже больше десятка. Появилась идея , в корпуса изготовить свою плату на МК attiny13, соответственно без полного набора функций как у оригинала. Здесь на сайте нашел  статью "Музыкальный звонок на МК Attiny13". В готовую схему в колхозил светодиод. По факту кнопку планирую заменить на геркон. 
       Не могу разобраться как сделать чтоб при нажатии  кнопки, контролер выполнил программу один раз и остановил цикл даже с нажатой кнопкой(это тот случай когда магнит на ролике остановился возле геркон и замкнул контакт ) ? Отпустил,нажал еще раз  все повторилось.
      Есть вторая проблема, во время цикла контролер  не реагирует на кнопку .Как сделать чтоб при повторном нажатии происходил сброс программы (уже действующего цикла) и запускалась новая программа (цикл)? 
      $regfile = "attiny13.dat"
      $crystal = 1200000
      $hwstack = 16
      $swstack = 16
      $framesize = 16
      $noramclear
      Config PINB.1 = Input
      Config PORTB.2 = Output
      Toch Alias PINB.1
      Led Alias PORTB.2
      Config INT0 = Low Level
      On INT0 Button:
      Enable Interrupts
      Enable INT0
      Declare Sub Melodi1()
      Dim Melcount As Byte
      Do
      Powerdown
      Loop
      End
      Sub Melodi1()
      Do
      Sound , PORTB.0 , 30 , 100
      Waitms 10
      Sound , PORTB.0 , 30 , 150
      Waitms 10
      Melcount = Melcount + 1
      Loop Until Melcount = 5
      Melcount = 0
      if Toch = 1 Then Led = 0
      if Toch = 0 Then Led = 1
      Led = 1
      Waitms 200
      Led = 0
      Waitms 200
      Led = 1
      Waitms 200
      Led = 0
      Waitms 200
      Led = 1
      Waitms 200
      Led = 0
      Waitms 200
      Led = 1
      Waitms 200
      Led = 0
      Waitms 200
      Led = 1
      Waitms 200
      Led = 0
      Waitms 200
      End Sub
      Button:
      Call Melodi1()
      GIFR = 64
      Return
      Спасибо всем кто откликнется! Буду рад любой помощи.
       

      ver 1.1.0.bas
    • By psinetron
      Здравствуйте. Решил попробовать в деле ATTiny13. Решил начать с самого простого - поморгать светодиодами. ОК, запустил platformIO, скопировал пример - вроде все работает. Светодиод моргает. Но. как только решил поменять значение _delay_ms, то понял, что что-то пошло не так.
      Дело в том, что светодиод моргает вообще игнорируя этот самый delay. Не важно сколько бы ms задержки я там не выставил - получается эпилептическое моргание. 
      Прошиваю через Arduino Uno. AtTiny опробовал пару разных - на второй микрухе тот же самый эффект. Причем если не прописывать включать светодиод - он не горит. Примеры пробовал разные, эффект везде один. Уже и не знаю на что думать
      Пример моего кода:
       
      #define F_CPU 120000UL // Указываем тактовую частоту МК #define LED PB2 // Используем светодиод, подключенный к PB2 (7 пин) #include <avr/io.h> // Подключаем определения ввода/вывода #include <util/delay.h> // Подключаем библиотеку функций задержки int main(void) { // Светодиод DDRB |= (1<<LED); // конфигурируем пин как выход while (1) { PORTB |= (1<<LED); _delay_us(1000L); PORTB &= ~(1<<LED); _delay_ms(10000L); } }  
      На всякий случай конфигурация platformIo:
      [env:attiny13a] platform = atmelavr board = attiny13 ; change microcontroller board_build.mcu = attiny13 ; change MCU frequency board_build.f_cpu = 1200000L upload_protocol = stk500v1 ; each flag in a new line upload_flags = -P$UPLOAD_PORT -b$UPLOAD_SPEED ; edit these lines upload_port = COM3 upload_speed = 19200  
    • By mal333
      Всем привет.
      Есть задачка на 2 пина контроллера посадить 4 кнопки и распознавать их состояние, а так же состояние "ни одна не нажата". Есть схемы подключения их в матрицу R2R и последующее аналоговое измерение, но я почему-то думаю, что можно считывать и чисто цифровым методом. Пораскинув мозгами, получилась эта схема.В ней опрос будет такой- сначала читаем состояние выводов, потом переключаем пины попеременно в 1 и смотрим состояние другого вывода. Может есть схемы проще, но вот что-то не нашел.

    • By katet
      Добрый день. Может быть,кто-нибудь уже сталкивался с таким. 
      Занимаюсь доработкой чужого проекта в среде STM32CubeMX, первый раз работаю с библиотекой HAL.
      В этом проекте осуществлялся прием байт по USART1 из ComMon. Проект был открыт в STM32CubeMX, где мной дополнительно были активированы новые модули - RTC, SD, USART2. Настройки USART1 не менялись. 
      Часы реального времени RTC: питание от батарейки, тактирование – от LSE. 
      При приеме байт по USART1 в новом проекте (активны  USART1, RTC, SD, USART2) было выявлено, что после приема 2 байт по USART1 перестает инкрементироваться значение переменной uwTick, отвечающей за прерывания Systick, в результате чего дальнейшая отладка невозможна. Не удается выяснить, в каком месте и почему перестает увеличиваться значение uwTick. При работе со старым проектом (где активен только USART1) uwTick инкрементируется после приема 2 байт.
      Смены приоритета прерываний не происходит, в  функцию HAL_Delay() отладчик не попадает. При вызове функции HAL_ResumeTick(), возобновляющей прерывания Systick, ничего не меняется, значение uwTick остается неизменным.
      Остановка прерываний была обнаружена при попадании в функцию:
      static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
      {
        /* Wait until flag is set */
        while((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status) 
        {
          /* Check for the Timeout */
          if(Timeout != HAL_MAX_DELAY)
          {            
            if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout))
            {
              /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
              CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE));
              CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
              
              huart->gState  = HAL_UART_STATE_READY;
              huart->RxState = HAL_UART_STATE_READY;
              
              /* Process Unlocked */
              __HAL_UNLOCK(huart);
              
              return HAL_TIMEOUT;
            }
          }
        }
        
        return HAL_OK;
      }
      В новом проекте текущее значение uwTick, возвращаемое функцией HAL_GetTick(), всегда равно значению Tickstart. В старом проекте сначала также, но затем uwTick начинает увеличиваться. Выяснить, в каком именно месте кода значение uwTick должно начать увеличиваться, не удается.
      Может быть, у кого-нибудь есть хоть какие-то идеи, с чем может быть связана остановка увеличения значений uwTick, помогите пожалуйста)
      Распиновка и конфигурация обоих проектов: верхняя часть рисунков - первоначальный, работающий вариант,  нижняя - сбой прерываний Systick.


    • By IgnatiusF
      Не могу настроить таймер 0 на работу, и даже не получается понять в чем проблема. Делаю в Proteus, так как это быстрее и нагляднее.
      Пробовал и просто по переполнению делать прерывание (WGM[1..0]  00) и по совпадению (WGM[1..0]  10; OCR0A = 0 - 255), однако прерываний нет. Перед циклом ставлю TCNT0 = 0;
      Тактирование выставляю TCCR0B (CS[2..0] 001, 100, 101).
      Прерывания TIMSK0 (OCIE0A, TOIE0) выставляю, не вызываются. Даже принудительным заносом значения в регистр TIFR0 (OCF0A, TOV0).
      Прерывание пытаюсь выполнить таким образом:
      #include <avr/interrupt.h> volatile unsigned int A = 0; ISR(TIMER0_OVF_vect) { A = 1; } ... while(1) { if (A == 1) PORTB |= (1<<0); } Proteus показывает, что вывод настроен как выход, но всегда 0;
      Конкретный код привести не могу, так как у меня не заработало совсем ничего.
      Внизу я сделал вырезку из даташита на ATMEGA328 по 0 таймеру 8-бит, и занес в один PDF файл.
      ATmega328-106-112.pdf
      Прошу помочь разобраться с таймером и прерываниями для него.
  • Сообщения

    • Да.  Но при 230В в сети. В основном 40-41В. Но как подключу  основной БП - напишу, какое фактическое. С нагрузкой 1к (42мА) - 42В в плечо при 230В в сети. Это чисто  плечи БП.
    • Ясно. Так штатное питание какое будет, 42 в плечо?
    • Я же по одному каналу запускаю. У меня нет двух ЛБП. Да, я знаю. Просто выставил для теста радиатора.  
    • Как пишешь, так и читаю. Выше написано было: ТП 75 мА на канал. Я не экстрассенс, что для тебя ТП, ток покоя ВК или потребление на ХХ.
    • Опять 25! Какой Ацетон, из магазина Вонючий? Который может разбавленный... А я чистым пробовал, который без запаха, и ведь спрашивал у @m-60 он каким пробовал, тоже говорит из бочки, слева на фото не смылась надпись, но краска потуснела, если бы я дальше поупорствовал, то моим Ацетоном с военного завода она бы смылась, вопрос времени, пришлите мне хоть Санкен, хоть чё, и я Вам за Пару минут любую надпись смою своим Ацетоном!!
    • Смысл есть всегда. Потому что отличия есть и звук действительно разный. Другое дело, что если на первом же соавнении интерес пропал, то дальше слушать уже и нечего. Между тем, один и тот же усилитель при двойном моно против стерео или псевдо звучит абсолютно по-другому.
    • Волномер на аналоге лямбда зонда до 150-и МГц      
×
×
  • Create New...