PDA

توجه ! این یک نسخه آرشیو شده میباشد و در این حالت شما عکسی را مشاهده نمیکنید برای مشاهده کامل متن و عکسها بر روی لینک مقابل کلیک کنید : ساخت زمان با تایمر



spring110.sh
09-09-2013, 11:44
سلام بر اساتید محترم .
من می خوام با تایمر میکرو زمان یک ثانیه رو بسازم . اینم کد منه :

M_TimeBaseStructure.TIM_Period = 1000 - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 5000 - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM IT enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);


void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
a++;
for(a=0;a<=100;a++);
if (a<=100)
GPIOC->ODR ^= GPIO_Pin_2;

}}

اما کد بالا کار نیم کنه و پورت 2.d من toggle نمیشه.:unh:

لطف می کنید راهنمایی کنید ؟:hi:

sadmonew
09-09-2013, 12:15
سلام
بايد اين قسمت رو هم فعال كني:


NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
NVIC_Init(&NVIC_InitStructure);

ضمنا" اين قسمت هارو هم تغيير بده:


TIM_TimeBaseStructure.TIM_Period = 20000;
TIM_TimeBaseStructure.TIM_Prescaler = 3600 - 1;

spring110.sh
09-09-2013, 16:29
سلام
بايد اين قسمت رو هم فعال كني:


NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
NVIC_Init(&NVIC_InitStructure);

ضمنا" اين قسمت هارو هم تغيير بده:


TIM_TimeBaseStructure.TIM_Period = 20000;
TIM_TimeBaseStructure.TIM_Prescaler = 3600 - 1;



خیلی ممنون آقا صادق . البته من اون قسمت رو فعال کرده بودم . prescaler رو هم برای کریستال 8 مگاهرتز حساب کرده بودم . البته تو کار با وقفه مشکل دارم ، چون کتابخونه delay خوب کار نمی کنه و فکر می کنم سرعت وقفه هم خیلی زیاده ! چون تا میکرو استارت می شه ، متغیری که داخل تابع وقفه گذاشتم سریع = 100 می شه...
حالا بازم اگه مشکلی تو برنامه من به نظرتون می رسه ، ممنون می شم استفاده کنم

sadmonew
09-09-2013, 19:31
خیلی ممنون آقا صادق . البته من اون قسمت رو فعال کرده بودم . Prescaler رو هم برای کریستال 8 مگاهرتز حساب کرده بودم . البته تو کار با وقفه مشکل دارم ، چون کتابخونه delay خوب کار نمی کنه و فکر می کنم سرعت وقفه هم خیلی زیاده ! چون تا میکرو استارت می شه ، متغیری که داخل تابع وقفه گذاشتم سریع = 100 می شه...
حالا بازم اگه مشکلی تو برنامه من به نظرتون می رسه ، ممنون می شم استفاده کنم
سلام مهندس
براي اينكه بدونم مشكل دقيقا" چيه، بايد كل پروژه اي كه ساختيو ببينم!

spring110.sh
09-09-2013, 20:45
سلام مهندس
براي اينكه بدونم مشكل دقيقا" چيه، بايد كل پروژه اي كه ساختيو ببينم!

اینم کدی که برای تست تایمر استفاده کردم :

#include "stm32f10x.h"
#include <stdio.h>
#include "stm32f10x_tim.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
#include <delay.h>
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStructure;
int a=0,b=0,j=0;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;

void main(void){



/********************** GPIO configuration*********************************/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // we want the pins to be an output
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // this sets the GPIO modules clock speed
//GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // this sets the pin type to push / pull (as opposed to open drain)
//GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // this sets the pullup / pulldown resistors to be inactive
GPIO_Init(GPIOD, &GPIO_InitStruct); // this finally passes all the values to the GPIO_Init function which takes care of setting the corresponding bits.

/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* TIM2 clock enable */
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 100000 - 1; // 1 MHz down to 1 KHz (1 ms)
TIM_TimeBaseStructure.TIM_Prescaler = 30000 - 1; // 24 MHz Clock down to 1 MHz (adjust per your clock)
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM IT enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
}

/***************** Timing********************* */

void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
a++;
for(a=0;a<=100;a++);
if (a<=100)
a=0;
GPIOD->ODR ^= GPIO_Pin_1;
delay_ms(1000);

}}


نظرت چیه ؟


اینم فایلش
You can see links before reply

spring110.sh
10-09-2013, 16:34
تا جایی که من فهمیدم باید prescaler و period رو ضرب در هم کرده و تقسیم بر 36 مگاهرتز کنیم . البته اگه کلاک دایو = 1 باشه !
طبق گفته عده ای در این حالت اگه پریود 1000 ، prescaler = 36000 باشه ، ما می تونیم هر یک ثانیه یک وقفه داشته باشیم . اما من عملا همچین چیزی جواب نگرفتم !

sadmonew
11-09-2013, 19:53
سلام مهندس
چيزي كه من تو برنامه ديدم اينه كه شما اصلا" فركانس هسته ميكرو، روي 72MHz تنظيم نكردين!!
پس نبايد انتظار داشته باشين كه وقفه تو زماني كه تنظيم كردين عمل كنه!!

spring110.sh
11-09-2013, 21:45
سلام مهندس
چيزي كه من تو برنامه ديدم اينه كه شما اصلا" فركانس هسته ميكرو، روي 72mhz تنظيم نكردين!!
پس نبايد انتظار داشته باشين كه وقفه تو زماني كه تنظيم كردين عمل كنه!!

خب من برنامه رو با شبیه ساز خود کیل هم تست کردم که فرکانسش روی 8 مگه ! برای اونم پارامترا رو مشخص کردم و نشد .
چه طور تو برنامه فرکانس رو تنظیم کنم و آیا اشکال دیگه ای هم داره ؟

spring110.sh
12-09-2013, 11:54
سلام مهندس
چيزي كه من تو برنامه ديدم اينه كه شما اصلا" فركانس هسته ميكرو، روي 72MHz تنظيم نكردين!!
پس نبايد انتظار داشته باشين كه وقفه تو زماني كه تنظيم كردين عمل كنه!!

آقا مشکلشو با کمک یکی از همکارام پیدا کردم . فکر می کنی چی بود مشکلش ؟
برنامه حلقه تکرار (loop) نداشت !
اینم برنامه اصلاح شده :

#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
#include <delay.h>
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitTypeDef GPIO_InitStruct;
int a=0;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;

int main(void){

/********************** GPIO configuration*********************************/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStruct);

//**************config NVIC************************

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

//**************timer config*****************

TIM_TimeBaseStructure.TIM_Period = 1000; //
TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1; //
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/* TIM IT enable: for overflow */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

/* TIM2 enable */
TIM_Cmd(TIM2, ENABLE);
while(1);//loop : when we dont have any intrrupt , thise code runing !

}

/***************** Timing ovf function********************* */

void TIM2_IRQHandler(void)
{
a++;// with each interrupt , a=a +1
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//reset timer flag

}
if (a>=5)// each 5 second , pinD1 toggled !

GPIOD->ODR ^= GPIO_Pin_1;// toggle code
if (a>5)
a=0;


}


تو این برنامه هر 5 ثانیه پایه d1 تغییر وضعیت می ده !

spring110.sh
15-09-2013, 15:17
نتیجه گیری :
برای استفاده از تایمر ، ابتدا باید اون رو پیکره بندی (config) کنید !

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

دستور بالا ، کلاک تایمر 2 را فعال می کند !
از اینجا (You can see links before reply)می تونید توضیح راجع به باس ها رو مطالعه کنید . برای تنظیم سرعت تایمر به دردتون می خوره !
ادامه :

TIM_TimeBaseStructure.TIM_Period = 1000; //
TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1; //
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/* TIM IT enable: for overflow */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

/* TIM2 enable */
TIM_Cmd(TIM2, ENABLE);

فرمول محاسبه ovf تایمر :
period*prescaler
نتیجه ضرب بالا تقسیم بر فرکانس میشه زمان ovf( اور فلو )

spring110.sh
15-09-2013, 15:19
اگه اون مطلب باس ها رو بخونید متوجه می شید که الان تایمر 2 با فرکانس 36 مگاهرتز داره کار می کنه ! من طوری تنظیم کردم که هر 1 ثانیه وارد تابع وقفه بشه ! خب گفتم تابع وقفه ، میریم سراغ پیکره بندی وقفه !

spring110.sh
15-09-2013, 15:27
پیکره بندی وقفه :


NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


با دستورات بالا وقفه تایمر 2 فعال می شه !

spring110.sh
15-09-2013, 15:28
گزینه های priority اولویت اجرای وقفه رو مشخص می کنن ! این اولویت های برای زمانی که چند وقفه داریم کاربرد داره !

گزینه

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

هم وقفه تایمر 2 رو فعال و شروع به کار می کنه !

spring110.sh
15-09-2013, 15:29
در نهایت ما نیاز به تابع وقفه داریم . تابعی که با هر بار سرریز شدن و ایجاد وقفه ، برنامه های درون اون اجرا بشه !
ک به شرح زیره :

void TIM2_IRQHandler(void)
{
a++;// with each interrupt , a=a +1
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//reset timer flag

}
if (a>=5)// each 5 second , pinD1 toggled !
{
GPIOD->ODR ^= GPIO_Pin_1;}// toggle code
if (a>5){
a=0;}


}

spring110.sh
15-09-2013, 15:34
این دستور هربار که پرچم وقفه set بشه ، اجرا میشه ! در این میکرو کنترلر بر خلاف avr خودتون باید پرچم وقفه رو بعد از هربار ست شدن ، ریست کنید !

if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)

دستور ریست کردن:

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//reset timer flag

هر 1 ثانیه که این تابع اجرا بشه ، متغیر a یکی بهش اضافه می شه . وقتی 5 ثانیه گذشت ، یعنی مقدار این متغیر 5 شد ، دستور زیر که toggle کننده پین هست ، اجرا می شه !

GPIOD->ODR ^= GPIO_Pin_1;}// toggle code

.
امیدوارم به دردتون بخوره !
سوالی بود در خدمتم !!

spring110.sh
15-09-2013, 15:35
ضمنا یادتون باشه که حتما یه حلقه تو برنامتون داشته باشید تا زمانی که تایمر در حال شمارشه و هنوز وقفه ای شکل نگرفته ، اون حلقه اجرا بشه ! وگرنه به خطا می خورید !

spring110.sh
15-09-2013, 15:35
کل برنامه من قبلا داخل همین تاپیک قرار گرفته که می تونید مطالعه کنید !

spring110.sh
15-09-2013, 16:28
فایل کل پروژه ...
می تونید به جای دستور toggle از دستورات set و reset استفاده کنید .

MMBMMB20
20-10-2013, 20:22
کل برنامه من قبلا داخل همین تاپیک قرار گرفته که می تونید مطالعه کنید !

آفا مازیار یعنی با این پروژه امکانش هست یک ساعت دقیق روی lcd پیاده کرد؟؟؟؟

dostajn
21-10-2013, 19:59
گزینه های priority اولویت اجرای وقفه رو مشخص می کنن ! این اولویت های برای زمانی که چند وقفه داریم کاربرد داره !

گزینه

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

هم وقفه تایمر 2 رو فعال و شروع به کار می کنه !
سلام
در مورد اولویت بندی صحبت فرموده بودید.
ظاهرا اینجور که شما گفتین برخلاف Avr با وقوع یک وقفه کل وقفه ها غیر فعال نمیشوند

یعنی مثلا من نیاز به ده تا کانتر دارم که می خوام اونا رو به جای استفاده از تایمر با اینتراپت برنامه ریزی کنم اگه زمانی که یه وقفه اتفاق می افته بقیه وقفه ها غیر فعال نشن، کانتر ها بدون مشکل کار می کنند و به ترتیب مقادیر هر کانال ذخیره میشه میره برای وقفه بعدی؟؟؟

ببخشید دارم روی آرم تحقیق می کنم شاید بعدا خودمم به این موضوع خندیدم :mrgreen:

Greatal
20-01-2014, 08:39
با تشکر از جناب مازیار شاهسون پور
چندتا نکته کچولو در هر زمان می توندی مقدار کانتر رو با تغییر رجیستر cnt اون تایمر عوض کنید
مثلا اگر استپ آپ هستش می تونید وسط شمارش یه دفه 0 کنید(مثلان برای چک کردن تایم اوت)
و اینکه اگر زیر برنامه تو تایمرتون از زمان اینتراپتون بزرگتره یعنی اگر قبل از اتمام کد های داخل وقفه ایتراپت یه ایپت دیگه میاد ولی شما اینو نمی خوایند می تونید تایمر رو با کامند دیس ایبل کنید و دوباره راه بندازید فقط نکته کوچیکش اینکه ظاهرا باید دوباره cnt رو ست کنید چون مقدارش معلوم نیست!
مثلا به این ترتیب
اول کلیر کردن وقفه
دیس ایبل کردن تایمر
کد
.
.
.
اگر تایمر استپ آپ هستش سفر کردن cnt
راه اندازی مجدد تایمر
البته فقط برای مواردی که زیر روال وقفه خیلی بزرگه یا فاصله اجرای وقفه بعدی از اتمام وقفه فعلی براتون خیلی مهمه این کار لازمه