اطلاعیه

Collapse
No announcement yet.

مشکل شمارنده معکوس timer0 در کد ویژن

Collapse
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    مشکل شمارنده معکوس timer0 در کد ویژن

    با سلام
    من یه منو تو در تو دارم روی lcd 4*20
    من یک منودارم که یک تایم مثلا 30 دقیقه از کاربر میگیره و بعد از فشردن اینتر وارد یک منو دیگه میشه که همون فانکشن جدید مثل (() void timer) شروع میکنه از 30 دقیقه شمارش معکوس تا صفر بشه و اون عملیات تمام بشه.

    حالا من یک عدد از کاربر میگیرم.
    میخوام اون عدد که مثلا 16 باشه یا هرچیزی رو نمایش بده. یه شمارنده 60 ثانیه هم باشه که از 59 شروع به کم شدن بکنه و قتی به 0 رسید یک واحد از عدد کاربر مثلاً 16 کم بشه تا هم ثانیه و هم دقیقه صفر بشه. و وقتی صفر شد یه اتفاق بیوفته مثلاً لامپ خاموش بشه.

    مشکل اینجاست که ثانیه وقتی صفر میشه از 255 شروع میکنه. وقتی دقیقه 0 میشه میره روی 1- و ... .
    جدیدترین ویرایش توسط shoniz; ۱۷:۳۷ ۱۳۹۹/۰۳/۰۹.
    *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

    #2
    پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

    نوشته اصلی توسط shoniz نمایش پست ها
    با سلام
    من یه منو تو در تو دارم روی lcd 4*20
    من یک منودارم که یک تایم مثلا 30 دقیقه از کاربر میگیره و بعد از فشردن اینتر وارد یک منو دیگه میشه که همون فانکشن جدید مثل (() void timer) شروع میکنه از 30 دقیقه شمارش معکوس تا صفر بشه و اون عملیات تمام بشه.

    کد:
    interrupt [EXT_INT0] void timer0_ovf_isr(void)
     {
    کدهای مربوط به timer0
    }
    حالا کد های مربوط به تایمر صفر رو زدم

    حالا چطور تایمر صفر رو توی فانکشن های مختلف صدا بزنم؟

    چه دستوری داره؟
    من کد های توی فانکشنم درسته
    فقط تایمر شروع نمیکنه شمارش.
    کد #asm ("sei") رو هم تمام جاهای مختلف امتحان کردم.
    نشد که نشد.

    ممنون میشم راهنمایی کنید.
    سلام
    الآن مشکلتون کار نکردن تایمره، ایجاد تاخیر 30 دقیقه ای هستش یا چی؟
    اگر مشکلتون خود تایمره، تایمرهای سخت افزاری میکروکنترلری مثل ATmega32 از صفر شروع به شمارش میکنن تا برسن به نقطه سرریز یا مقایسه؛ بعد دوباره صفر میشن و شمارش از نو. بسته به این که تایمر توی کدوم مد کار میکنه، موقع تطبیق مقایسه یا سرریز، میتونه یک وقفه تولید کنه. هر وقفه هم یک سرویس وقفه داره که در صورت رخداد اون وقفه، برنامه اصلی موقتا متوقف میشه و cpu دستورات سرویس وقفه رو اجرا میکنه تا اینکه دستورات سرویس وقفه تموم بشن و cpu برگرده به برنامه اصلی و کارش رو ادامه بده.
    برای اینکه به درخواست وقفه پاسخ داده بشه، باید بیت فعال ساز وقفه عمومی هم فعال بشه که بهش میگن بیت I. در واقع شما با قرار دادن sei در برنامه اتون دارید این بیت رو فعال میکنید؛ کافیه یک بار این خط رو در تابع main قرار بدید تا در صورت وقوع وقفه بهش پاسخ داده بشه. همچنین لازمه وقفه خود تایمر هم از طریق رجیسترهاش فعال بشه.
    چیزی که مسلمه تایمر avr توانایی ایجاد زمان های 30 دقیقه ای نداره. پس شما برای این که زمان 30 دقیقه ای تولید کنید، باید با استفاده از روش های مثل استفاده از متغیر در سرویس وقفه تایمر، این زمان رو تولید کنید. یعنی اگر فرض بگیریم دوره تایمر 25 میلی ثانیه باشه، برای ایجاد 30 دقیقه که خودش برابر 1800 ثانیه هستش، لازمه 72000 بار وقفه رخ بده. کافیه یک متغیر در برنامه بذاریم که هر بار وقفه تایمر رخ داد یکی به مقدارش اضافه بشه و بعد از رسیدن به مقدار 72000، میتونیم بگیم 30 دقیقه سپری شده. شما با مقدار این متغیر در برنامه اصلی میتونید بفهمید در این بازه 30 دقیقه قرار گرفتید یا نه و چه عملکردی لازمه انجام بشه.
    اگر مشکلتون اینا نبودن، بفرمایید، بلد باشم جواب میدم.

    دیدگاه


      #3
      پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

      نوشته اصلی توسط hossein.m98 نمایش پست ها
      سلام
      الآن مشکلتون کار نکردن تایمره، ایجاد تاخیر 30 دقیقه ای هستش یا چی؟
      اگر مشکلتون خود تایمره، تایمرهای سخت افزاری میکروکنترلری مثل ATmega32 از صفر شروع به شمارش میکنن تا برسن به نقطه سرریز یا مقایسه؛ بعد دوباره صفر میشن و شمارش از نو. بسته به این که تایمر توی کدوم مد کار میکنه، موقع تطبیق مقایسه یا سرریز، میتونه یک وقفه تولید کنه. هر وقفه هم یک سرویس وقفه داره که در صورت رخداد اون وقفه، برنامه اصلی موقتا متوقف میشه و cpu دستورات سرویس وقفه رو اجرا میکنه تا اینکه دستورات سرویس وقفه تموم بشن و cpu برگرده به برنامه اصلی و کارش رو ادامه بده.
      برای اینکه به درخواست وقفه پاسخ داده بشه، باید بیت فعال ساز وقفه عمومی هم فعال بشه که بهش میگن بیت I. در واقع شما با قرار دادن sei در برنامه اتون دارید این بیت رو فعال میکنید؛ کافیه یک بار این خط رو در تابع main قرار بدید تا در صورت وقوع وقفه بهش پاسخ داده بشه. همچنین لازمه وقفه خود تایمر هم از طریق رجیسترهاش فعال بشه.
      چیزی که مسلمه تایمر avr توانایی ایجاد زمان های 30 دقیقه ای نداره. پس شما برای این که زمان 30 دقیقه ای تولید کنید، باید با استفاده از روش های مثل استفاده از متغیر در سرویس وقفه تایمر، این زمان رو تولید کنید. یعنی اگر فرض بگیریم دوره تایمر 25 میلی ثانیه باشه، برای ایجاد 30 دقیقه که خودش برابر 1800 ثانیه هستش، لازمه 72000 بار وقفه رخ بده. کافیه یک متغیر در برنامه بذاریم که هر بار وقفه تایمر رخ داد یکی به مقدارش اضافه بشه و بعد از رسیدن به مقدار 72000، میتونیم بگیم 30 دقیقه سپری شده. شما با مقدار این متغیر در برنامه اصلی میتونید بفهمید در این بازه 30 دقیقه قرار گرفتید یا نه و چه عملکردی لازمه انجام بشه.
      اگر مشکلتون اینا نبودن، بفرمایید، بلد باشم جواب میدم.
      الان کار میکنه.
      مشکل شمارش هست.
      مثلا کاربر 16 دقیقه داده.

      حالا من این 16 دقیقه رو از eeprom میخونم. تا اینجا هم مشکلی نیست.
      حالا این 16 دقیقه و شروع کنه معکوس شماردن تا صفر بشه.
      START PROCESS
      15:59 معکوس بشماهر.(هر 60 ثانیه که صفر بشه یه واحد از دقیقه کم بشه).

      کد:
      interrupt [TIM0_OVF] void timer0_ovf_isr(void)
       {
        TCCR0=0x00;
        i++;
        TCNT0=4;
        TCCR0=0x04;
        if(i==128)      // 128 = 1 sanie
           {
              if(m > 0)
              {
               s --;
              }
              if(s == 0)
              {
               m--;
               s = 0;
              }
           i=0;
      
           lcd_clear();
           lcd_gotoxy(3,0);
           sprintf(Buffer_LCD0,"%02d:%02d",m,s);
           lcd_puts(Buffer_LCD0);
           }
      
            TCCR0=0x04;                     // clock 31.250 kHz va : 256
            TCNT0=4;
            TIMSK=0x01;
       }
      این تابع تایمر صفر

      کد:
      void timer()
          {  
            m = MinuteVal[1];
            s = 60;
            if(m>0)
            {
            s--;
            }
            #asm("sei")
            TCCR0=0x04;                     // clock 31.250 kHz va : 256
            TCNT0=4;
            TIMSK=0x01;
           while(1)
           {   
            if(esckey == 0)
            {
             TCCR0=0x00;
            }
            if(enterkey == 0)
            {
             TCCR0=0x04;
            } 
            if(upkey == 0)
            {
             TCCR0=0x00;
             MainMenus();
            } 
           } 
          }
      اینم فانکشن تایمر

      -----------

      ایرادش اینه که از 255 شروع میکنه و دقیقه هم بعد صفر منفی میشه
      *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

      دیدگاه


        #4
        پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

        نوشته اصلی توسط shoniz نمایش پست ها
        الان کار میکنه.
        مشکل شمارش هست.
        مثلا کاربر 16 دقیقه داده.

        حالا من این 16 دقیقه رو از eeprom میخونم. تا اینجا هم مشکلی نیست.
        حالا این 16 دقیقه و شروع کنه معکوس شماردن تا صفر بشه.
        START PROCESS
        15:59 معکوس بشماهر.(هر 60 ثانیه که صفر بشه یه واحد از دقیقه کم بشه).

        کد:
        interrupt [TIM0_OVF] void timer0_ovf_isr(void)
         {
          TCCR0=0x00;
          i++;
          TCNT0=4;
          TCCR0=0x04;
          if(i==128)      // 128 = 1 sanie
             {
                if(m > 0)
                {
                 s --;
                }
                if(s == 0)
                {
                 m--;
                 s = 0;
                }
             i=0;
        
             lcd_clear();
             lcd_gotoxy(3,0);
             sprintf(Buffer_LCD0,"%02d:%02d",m,s);
             lcd_puts(Buffer_LCD0);
             }
        
              TCCR0=0x04;                     // clock 31.250 kHz va : 256
              TCNT0=4;
              TIMSK=0x01;
         }
        این تابع تایمر صفر

        کد:
        void timer()
            {  
              m = MinuteVal[1];
              s = 60;
              if(m>0)
              {
              s--;
              }
              #asm("sei")
              TCCR0=0x04;                     // clock 31.250 kHz va : 256
              TCNT0=4;
              TIMSK=0x01;
             while(1)
             {   
              if(esckey == 0)
              {
               TCCR0=0x00;
              }
              if(enterkey == 0)
              {
               TCCR0=0x04;
              } 
              if(upkey == 0)
              {
               TCCR0=0x00;
               MainMenus();
              } 
             } 
            }
        اینم فانکشن تایمر

        -----------

        ایرادش اینه که از 255 شروع میکنه و دقیقه هم بعد صفر منفی میشه
        مگه تنظیمات تایمر جایی تغییر میکنه که داخل سرویس وقفه اش تنظیمات جدید بهش میدید؟
        سعی کنید داخل سرویس وقفه، چیزی غیر از تغییر مقدار متغیرها و ست کردن پرچم ها نباشه. کار با LCD رو منتقل کنید به برنامه اصلی.
        پیشنهاد بعدیم اینه شمارش هاتون در یک متغیر 16 یا 32 بیتی (بسته به نیاز) و بر اساس ثانیه باشه. هر جا نیاز به تبدیل به دقیقه و ثانیه باشه، با چندتا عملیات ساده میشه تفکیکشون کرد.

        اما موردی که در مورد برنامه اتون دیدم اینه وقتی ثانیه به صفر میرسه، دقیقه رو یک واحد کم میکنید و دوباره به ثانیه مقدار 0 اختصاص میدید. از اونجایی که احتمالا متغیر s از نوع 8 بیتی و بدون علامت هستش، وقتی صفر باشه و یک واحد ازش کم بشه میشه 255. شما باید وقتی صفر شد بهش مقدار 59 بدید که از 255 شروع نکنه. همونطوری که گفتم اگر محاسباتتون بر حسب ثانیه باشه، خیلی از مشکلات حل میشن. وقتی هم بخوایید زمان رو به شکل دقیقه و ثانیه به کاربر نمایش بدید، میتونید به این شکل دقیقه و ثانیه اش رو تفکیک کنید:

        unsigned int min = time / 60;
        unsigned int sec = time % 60;

        وقتی هم از کاربر زمان رو بر حسب دقیقه و ثانیه گرفتید، با یک ضرب و جمع ساده میشه به ثانیه تبدیلش کرد:

        time = (min * 60) + sec;

        دیدگاه


          #5
          پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

          نوشته اصلی توسط hossein.m98 نمایش پست ها
          مگه تنظیمات تایمر جایی تغییر میکنه که داخل سرویس وقفه اش تنظیمات جدید بهش میدید؟
          سعی کنید داخل سرویس وقفه، چیزی غیر از تغییر مقدار متغیرها و ست کردن پرچم ها نباشه. کار با LCD رو منتقل کنید به برنامه اصلی.
          پیشنهاد بعدیم اینه شمارش هاتون در یک متغیر 16 یا 32 بیتی (بسته به نیاز) و بر اساس ثانیه باشه. هر جا نیاز به تبدیل به دقیقه و ثانیه باشه، با چندتا عملیات ساده میشه تفکیکشون کرد.

          اما موردی که در مورد برنامه اتون دیدم اینه وقتی ثانیه به صفر میرسه، دقیقه رو یک واحد کم میکنید و دوباره به ثانیه مقدار 0 اختصاص میدید. از اونجایی که احتمالا متغیر s از نوع 8 بیتی و بدون علامت هستش، وقتی صفر باشه و یک واحد ازش کم بشه میشه 255. شما باید وقتی صفر شد بهش مقدار 59 بدید که از 255 شروع نکنه. همونطوری که گفتم اگر محاسباتتون بر حسب ثانیه باشه، خیلی از مشکلات حل میشن. وقتی هم بخوایید زمان رو به شکل دقیقه و ثانیه به کاربر نمایش بدید، میتونید به این شکل دقیقه و ثانیه اش رو تفکیک کنید:

          unsigned int min = time / 60;
          unsigned int sec = time % 60;

          وقتی هم از کاربر زمان رو بر حسب دقیقه و ثانیه گرفتید، با یک ضرب و جمع ساده میشه به ثانیه تبدیلش کرد:

          time = (min * 60) + sec;
          بله من این مدل رو در کدهام استفاده کردم در قسمتی که کل زمان های ذخیره شده رو (12 زمان دریافتی از کاربر) جمع کنه و بصورت ساعت و دقیقه نشون بده.

          اما برای این قسمت کارایی نداره.

          من فقط دقیقه و ثانیه باشه.
          یه دقیقه خاص حالا ممکنه 350 دقیقه باشه.
          همون 350 رو نشون بده، جلوشم یه عدد که از 59 معکوس بشماره تا 0 و وقتی 0 شد یک واحد از 350 کم کنه.
          و وقتی هم دقیقه و ثانیه 0 شد، فقط تایمر صفر غیر فعال بشه.
          *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

          دیدگاه


            #6
            پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

            نوشته اصلی توسط shoniz نمایش پست ها
            بله من این مدل رو در کدهام استفاده کردم در قسمتی که کل زمان های ذخیره شده رو (12 زمان دریافتی از کاربر) جمع کنه و بصورت ساعت و دقیقه نشون بده.

            اما برای این قسمت کارایی نداره.

            من فقط دقیقه و ثانیه باشه.
            یه دقیقه خاص حالا ممکنه 350 دقیقه باشه.
            همون 350 رو نشون بده، جلوشم یه عدد که از 59 معکوس بشماره تا 0 و وقتی 0 شد یک واحد از 350 کم کنه.
            و وقتی هم دقیقه و ثانیه 0 شد، فقط تایمر صفر غیر فعال بشه.
            خوب هر جور راحتید. مشکل کدتون هم فکر کنم همونی باشه که گفتم. کافیه اگر s صفر بود، به جای یک واحد کم کردن بیاد و مقدار 59 رو جایگزین کنه، 1 واحد هم از دقیقه کم کنه.

            دیدگاه


              #7
              پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

              نشد
              اولش از 59 شروع میکنه به کم شدن.
              بعد که 1 واحد از m کم میکنه میاد رو 255.
              دقیقه هم که 0 میشه یا میره رو 1- یا وقتیم 0 میشه ثانیه رو 59 گیر میکنه.
              *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

              دیدگاه


                #8
                پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

                نوشته اصلی توسط shoniz نمایش پست ها
                نشد
                اولش از 59 شروع میکنه به کم شدن.
                بعد که 1 واحد از m کم میکنه میاد رو 255.
                دقیقه هم که 0 میشه یا میره رو 1- یا وقتیم 0 میشه ثانیه رو 59 گیر میکنه.
                این قسمت رو جایگزین کنید:

                interrupt [TIM0_OVF] void timer0_ovf_isr(void)
                {
                TCCR0=0x00;
                i++;
                TCNT0=4;
                TCCR0=0x04;
                if(i==128) // 128 = 1 sanie
                {
                if(s > 0)
                {
                s--;
                }
                else
                {
                s = 59;
                if(m > 0)
                m--;
                }

                i = 0;

                lcd_clear();
                lcd_gotoxy(3,0);
                sprintf(Buffer_LCD0,"%02d:%02d",m,s);
                lcd_puts(Buffer_LCD0);
                }

                TCCR0=0x04; // clock 31.250 kHz va : 256
                TCNT0=4;
                TIMSK=0x01;
                }

                دیدگاه


                  #9
                  پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

                  مرسی استاد حسین عزیز
                  این کد جواب داد و خیلی خوب کار میکنه.
                  فقط یه بحثی. وقتی 0 میشه دوباره میاد از 59 میشماره.
                  بازم با کد درستش کردم وقتی 0 بشن دوتاشون، ;TCCR0=0x00 بشه و بایسته. نمیشه خودش 00 که شد کلا صفر بمونه؟ چون یه منو میرم عقب دوباره برمیگردم از 59 باز شمارش معکوس انجام میده.

                  دلیل: ادغام دو پست برای جلوگیری از اسپم

                  استاد حسین عزیز خدا خیرت بده.
                  درستش کردم.
                  4500 خط برنامه نوشتم. این یدونه داغونم کرده بود.
                  حالا برم کد هامو مرتب کنم تو فانکشن های دیگه هم قرار بدم.
                  بعدش pwm رو دارم که با همین تایمر در ارتباطه.
                  *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

                  دیدگاه


                    #10
                    پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

                    نوشته اصلی توسط shoniz نمایش پست ها
                    مرسی استاد حسین عزیز
                    این کد جواب داد و خیلی خوب کار میکنه.
                    فقط یه بحثی. وقتی 0 میشه دوباره میاد از 59 میشماره.
                    بازم با کد درستش کردم وقتی 0 بشن دوتاشون، ;TCCR0=0x00 بشه و بایسته. نمیشه خودش 00 که شد کلا صفر بمونه؟ چون یه منو میرم عقب دوباره برمیگردم از 59 باز شمارش معکوس انجام میده.

                    دلیل: ادغام دو پست برای جلوگیری از اسپم

                    استاد حسین عزیز خدا خیرت بده.
                    درستش کردم.
                    4500 خط برنامه نوشتم. این یدونه داغونم کرده بود.
                    حالا برم کد هامو مرتب کنم تو فانکشن های دیگه هم قرار بدم.
                    بعدش pwm رو دارم که با همین تایمر در ارتباطه.
                    اینو تست کنید:

                    interrupt [TIM0_OVF] void timer0_ovf_isr(void)
                    {
                    TCCR0=0x00;
                    i++;
                    TCNT0=4;
                    TCCR0=0x04;

                    if(i==128) // 128 = 1 sanie
                    {
                    if(s > 0)
                    {
                    s--;
                    }
                    else if(m > 0)
                    {
                    s = 59;
                    m--;
                    }

                    i = 0;

                    lcd_clear();
                    lcd_gotoxy(3,0);
                    sprintf(Buffer_LCD0,"%02d:%02d",m,s);
                    lcd_puts(Buffer_LCD0);
                    }

                    TCCR0=0x04; // clock 31.250 kHz va : 256
                    TCNT0=4;
                    TIMSK=0x01;
                    }

                    دیدگاه


                      #11
                      پاسخ : استفاده از Timer0 در فانکشن و پروسیجرهای مختلف در کدویژن (راهنمایی کنید)

                      نوشته اصلی توسط hossein.m98 نمایش پست ها
                      اینو تست کنید:

                      interrupt [TIM0_OVF] void timer0_ovf_isr(void)
                      {
                      TCCR0=0x00;
                      i++;
                      TCNT0=4;
                      TCCR0=0x04;

                      if(i==128) // 128 = 1 sanie
                      {
                      if(s > 0)
                      {
                      s--;
                      }
                      else if(m > 0)
                      {
                      s = 59;
                      m--;
                      }

                      i = 0;

                      lcd_clear();
                      lcd_gotoxy(3,0);
                      sprintf(Buffer_LCD0,"%02d:%02d",m,s);
                      lcd_puts(Buffer_LCD0);
                      }

                      TCCR0=0x04; // clock 31.250 kHz va : 256
                      TCNT0=4;
                      TIMSK=0x01;
                      }
                      خیلی لطف کردی استاد
                      خیلی هم خوب جواب داد
                      *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

                      دیدگاه

                      لطفا صبر کنید...
                      X