GebraBit

حالات همگام سازی Master/Slave

متن سربرگ خود را وارد کنید

15

حالات همگام سازی Master/Slave

  1. خانه
  2. »
  3. میکروکنترلر
  4. »
  5. حالات همگام سازی Master/Slave

حالات همگام سازی Master/Slave

هنگامی که یک تایمر در حالت master  کار می کند، می تواند تایمر دیگری را که در حالت Slave پیکربندی شده است از طریق یک خط خروجی اختصاصی، به نام خروجی Trigger  (TRGO)، متصل به خطوط اختصاصی داخلی به نام ITR0، ITR1، ITR2 و ITR3 تغذیه (کلاک) کند. تایمر master  هم می تواند به عنوان منبع کلاک عمل کند (به عنوان یک prescaler  مرتبه اول) یا تایمر slave  را تحریک  trigger  کند.

این خطوط Trigger داخلی (ITR) (ITR0، ITR1، ITR2 و ITR3) دقیقاً داخل تراشه هستند و هر خط بین دو تایمر مشخص ، متصل می شود. به عنوان مثال، در میکروکنترلر STM32F030، خط TIM1 TRGO به خط ITR0 تایمر TIM2 متصل است، همانطور که در شکل زیر نشان داده شده است.

یک تایمر slave  می‌تواند به‌طور همزمان به‌عنوان master  برای تایمر دیگر نیز عمل کند و شبکه‌ پیچیده ای از تایمر ها را به وجود آورد. به عنوان مثال، شکل زیر نشان می دهد که چگونه تایمرها را می توان به صورت آبشاری متصل کرد:

اما شکل زیر نشان می دهد که چگونه تایمرها می توانند ساختارهای سلسله مراتبی را با استفاده از ترکیب حالت های master/slave تشکیل دهند. توجه داشته باشید که TIM1، TIM2 و TIM3 به صورت داخلی از طریق همان خط ITR0 به هم متصل هستند. این امر باعث می شود تا چندین تایمر در یک رویداد مشابه (reset, enable, update و غیره) همگام سازی شوند.

typedef struct {

 uint32_t MasterOutputTrigger; /* Trigger output (TRGO) selection */

 uint32_t MasterSlaveMode; /* Master/slave mode selection */

} TIM_MasterConfigTypeDef;

  • MasterOutputTrigger: رفتار خروجی TRGO را مشخص می کند و می تواند مقادیری از جدول زیر را در بر گیرد.
  • MasterSlaveMode: برای فعال/غیرفعال کردن حالت master/slave یک تایمر استفاده می شود. می تواند مقادیر TIM_MASTERSLAVEMODE_ENABLE یا TIM_MASTERSLAVEMODE_DISABLE را در بر گیرد.

در ادامه نحوه پیکربندی TIM1 و TIM3 را در حالت آبشاری با تنظیم TIM1 به عنوان master برای تایمر TIM3 نشان می‌دهیم. TIM1 به عنوان منبع کلاک برای TIM3 از طریق خط ITR0 استفاده می شود. علاوه بر این، TIM1 به گونه ای پیکربندی شده است که روی یک رویداد خارجی در خط TI1FP1 شروع به شمارش می کند، که در Nucleo-F030 مربوط به پین PA8 است: زمانی که پایه PA8 بالا می رود، TIM1 شروع به شمارش می کند و سپس تایمر TIM3 را از طریق خط ITR0. تغذیه (کلاک) می کند.

				
					12 int main(void) {
13 HAL_Init();
14 15 Nucleo_BSP_Init();
16 MX_TIM1_Init();
17 MX_TIM3_Init();
18 19 HAL_TIM_Base_Start_IT(&htim3);
20 21 while (1);
22 }
23 
24 void MX_TIM1_Init(void) {
25 TIM_ClockConfigTypeDef sClockSourceConfig;
26 TIM_MasterConfigTypeDef sMasterConfig;
27 TIM_SlaveConfigTypeDef sSlaveConfig;
28 
29 htim1.Instance = TIM1;
30 htim1.Init.Prescaler = 47999;
31 htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
32 htim1.Init.Period = 249;
33 htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
34 htim1.Init.RepetitionCounter = 0;
35 HAL_TIM_Base_Init(&htim1);
36 
37 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
38 HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);
39 
40 sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
41 sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
42 sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
43 sSlaveConfig.TriggerFilter = 15;
44 HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig);
45 
46 sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
47 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
48 HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);
49 }
50 
51 void MX_TIM3_Init(void) {
52 TIM_SlaveConfigTypeDef sSlaveConfig;
53 
54 htim3.Instance = TIM3;
55 htim3.Init.Prescaler = 0;
56 htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
57 htim3.Init.Period = 1;
58 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
59 HAL_TIM_Base_Init(&htim3);
60 
61 sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
62 sSlaveConfig.InputTrigger = TIM_TS_ITR0;
63 HAL_TIM_SlaveConfigSynchronization(&htim3, &sSlaveConfig);
64 
65 HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
66 HAL_NVIC_EnableIRQ(TIM3_IRQn);
67 }
68 
69 void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) {
70 GPIO_InitTypeDef GPIO_InitStruct;
71 if(htim_base->Instance==TIM3) {
72 __HAL_RCC_TIM3_CLK_ENABLE();
73 }
74 
75 if(htim_base->Instance==TIM1) {
76 __HAL_RCC_TIM1_CLK_ENABLE();
77 
78 GPIO_InitStruct.Pin = GPIO_PIN_8;
79 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
80 GPIO_InitStruct.Pull = GPIO_PULLDOWN;
81 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
82 GPIO_InitStruct.Alternate = GPIO_AF2_TIM1;
83 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
84   }
85 }


				
			

خطوط [29:38] TIM1 را به گونه ای پیکربندی می کنند که از گذرگاه APB1 داخلی کلاک شود. و خطوط [40:44] TIM1 را در حالت slave  پیکربندی می کنند، به طوری که وقتی خط TI1FP1 بالا رفت (یعنی فعال می شود) شروع به شمارش می کند. PA8 GPIO بر این اساس در خطوط [74:79] پیکربندی شده است (به عنوان GPIO_AF2_TIM1 پیکربندی شده است). توجه داشته باشید که مقاومت PULL UP داخلی در خط 76 فعال می شود: این امر مانع از این می شود که ورودی به طور تصادفی تایمر را فعال کند. به همین دلیل، TriggerFilter در خط 43 روی حداکثر سطح تنظیم شده است (اگر سعی کنید آن را روی صفر تنظیم کنید، متوجه خواهید شد که راه اندازی تصادفی تایمر حتی با لمس سیم متصل به پین PA8  بسیار آسان است،).

خطوط [46:48] TIM1 را نیز در حالت master  پیکربندی می‌کنند. تایمر خط داخلی خود را (که به خط ITR0 TIM3 متصل است) هر بار که رویداد به‌روزرسانی update event  ایجاد می‌شود، راه‌اندازی می‌کند. در نهایت، خطوط [61:63] TIM3 را در حالت  update event تنظیم می‌کنند و خط ITR0 را به عنوان منبع کلاک انتخاب می‌کنند.

توجه داشته باشید برای اینکه LED LD2 هر 500 میلی‌ثانیه (2 هرتز) چشمک بزند، دوره TIM1 روی 249 تنظیم شده است که باعث می‌شود فرکانس به‌روزرسانی TIM1 عدد 4 هرتز باشد با استفاده از معادله زیر داریم که:

 

UpdateEvent = 4Hz/(0 + 1)(1 + 1)(0 + 1) = 2Hz = 0.5s

 

توجه داشته باشید که قسمت Period را نمی توان صفر قرار داد.

برای فعال کردن TIM1 باید پین PA8 را به منبع +3V3 وصل کنید. شکل زیر نحوه اتصال آن را در Nucleo-F030 نشان می دهد.

فعال سازی وقفه های مرتبط با Trigger

هنگامی که یک تایمر در حالت slave  کار می کند، IRQ  تایمر , در صورت فعال بودن، هر بار که رویداد trigger  مشخص شده فعال میشود ، رخ می دهد. به عنوان مثال، هنگامی که کلاک master  به دلیل یک رویداد به‌روزرسانی فعال می‌شود، IRQ تایمر slave روشن می‌شود و می‌توان با تعریف callback از این موضوع مطلع شد:

				
					void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
 { 
       ... 
   }

				
			

 به طور پیش فرض، HAL_TIM_Base_Start_IT() این نوع وقفه را فعال نمی کند. ما باید از تابع HAL_TIM_SlaveConfigSynchronization_IT()، به جای تابع HAL_TIM_SlaveConfigSynchronization() استفاده کنیم. بدیهی است که ISR مربوطه باید تعریف شده  و تابع HAL_TIM_IRQHandler() فراخوانی شود.

استفاده از CubeMX برای تنظیم همگام سازی Master/Slave

برای پیکربندی یک تایمر در حالت slave  با استفاده از CubeMX، کافی است حالت trigger  مورد نظر (Reset Mode, Gated Mode, Trigger Mode) را از IP Pane tree (Slave mode combo-box انتخاب کنید و سپس منبع trigger  را انتخاب کنید.به خاطر داشته باشید تایمر پیکربندی شده در حالت slave  ، که در حالت External Clock Mode 1 کار نمی کند، باید از کلاک داخلی یا منبع ETR2 کلاک شود.

ایجاد رویدادهای مرتبط با تایمر توسط نرم افزار

تایمرها معمولاً در صورت برآورده شدن یک شرط معین رویدادها را تولید می کنند. برای مثال، زمانی که رجیستر شمارنده (CNT) با مقدار Period مطابقت داشته باشد، رویداد Update Event (UEV) را تولید می کنند.همچنین می‌توانیم تایمر را مجبور کنیم تا یک رویداد خاص را توسط نرم‌افزار تولید کند. هر تایمر یک رجیستر اختصاصی به نام Event Generator (EGR) ارائه می دهد. برخی از بیت‌های این رجیستر برای اجرای یک رویداد مربوط به تایمر استفاده می‌شوند. به عنوان مثال، اولین بیت، به نام Update Generator (UG)، اجازه می دهد تا یک رویداد UEV در هنگام 1 شدن ایجاد شود. این بیت پس از ایجاد رویداد به طور خودکار پاک می شود.

برای تولید رویدادها توسط نرم افزار، HAL تابع زیر را ارائه می دهد:

HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource);

TIM_EVENTSOURCE_UPDATE دو نقش مهم دارد. اولین مورد مربوط به نحوه به روز رسانی رجیستر Period  (یعنی رجیستر TIMx->ARR)  هنگامی که تایمر در حال اجراست. به‌طور پیش‌فرض، محتوای رجیستر ARR هنگام ایجاد رویداد TIM_EVENTSOURCE_UPDATE به رجیستر سایه داخلی منتقل می‌شود، مگر اینکه تایمر به‌طور متفاوتی پیکربندی شده باشد.

رویداد TIM_EVENTSOURCE_UPDATE همچنین زمانی مفید است که خروجی TRGO یک تایمر پیکربندی شده به عنوان master  در حالت TIM_TRGO_RESET تنظیم شود: در این حالت، تایمر slave  تنها در صورتی فعال trigger می شود که از رجیستر TIMx->EGR برای تولید رویداد TIM_EVENTSOURCE_UPDATE استفاده شود (یعنی ، بیت UG یک شده است).

کد زیر نحوه تولید رویداد نرم افزاری را نشان می دهد (مثال بر اساس میکروکنترلر STM32F401RE است). TIM3 و TIM4 دو تایمر هستند که به ترتیب در حالت master و slave پیکربندی شده اند. TIM4 برای کار در حالت ETR1  تنظیم شده است (یعنی توسط تایمر master کلاک می شود). TIM3 به گونه ای پیکربندی شده است که وقتی بیت UG رجیستر TIM3->EGR یک می شود، خروجی TRGO (که به صورت داخلی به خط ITR2 متصل است) trigg  شود. در نهایت، رویداد UEV را به صورت دستی هر 200 میلی‌ثانیه از روتین main() تولید می‌کنیم.

				
					int main(void) {
... while (1) { 
HAL_TIM_GenerateEvent(&htim3, TIM_EVENTSOURCE_UPDATE);
 HAL_Delay(200);
    }
   ...
 }
void MX_TIM3_Init(void){ 
TIM_ClockConfigTypeDef sClockSourceConfig; 
TIM_MasterConfigTypeDef sMasterConfig;
htim3.Instance = TIM3; 
htim3.Init.Prescaler = 65535; 
htim3.Init.CounterMode = TIM_COUNTERMODE_UP; 
htim3.Init.Period = 120; 
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 
HAL_TIM_Base_Init(&htim3); 
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; 
HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig); 
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; 
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig); 
} 
void MX_TIM4_Init(void) { 
TIM_SlaveConfigTypeDef sSlaveConfig; 
htim4.Instance = TIM4; 
htim4.Init.Prescaler = 0; 
htim4.Init.CounterMode = TIM_COUNTERMODE_UP; 
htim4.Init.Period = 1; 
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 
HAL_TIM_Base_Init(&htim4); 
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1; 
sSlaveConfig.InputTrigger = TIM_TS_ITR2; 
HAL_TIM_SlaveConfigSynchronization_IT(&htim4, &sSlaveConfig); 
}

				
			

مدهای کاری کانتر

در ابتدای این فصل دیدیم که یک تایمر پایه basic  از صفر تا یک مقدار Period  دوره معین را می شمارد. تایمرهای عمومی General purpose  و پیشرفته advanced  به روش های مختلف دیگری نیز می توانند شمارش کنند. شکل زیر سه حالت اصلی شمارش را نشان می دهد.

وقتی یک تایمر در حالت TIM_COUNTERMODE_DOWN شمارش می‌کند، از مقدار Period شروع می‌شود و تا صفر به صورت معکوس شمارش می‌کند: وقتی شمارنده به پایان رسید، IRQ تایمر رخ داده و فلگ UIF یک می‌شود (یعنی رویداد به‌روزرسانی ایجاد می‌شود و HAL_TIM_PeriodElapsedCallback () توسط HAL فراخوانی می شود.)

در عوض، وقتی یک تایمر در حالت TIM_COUNTERMODE_CENTERALIGNED شمارش می‌کند، از صفر تا مقدار Period شروع به شمارش می‌کند: این امر باعث می‌شود که IRQ رخ داده و فلگ UIF یک شود ، (یعنی رویداد به‌روزرسانی ایجاد شده و HAL_TIM_PeriodElapsedCallback توسط HAL فراخوانی می‌شود). سپس تایمر شروع به شمارش معکوس تا صفر می کند و یک رویداد به روز رسانی دیگر (و همچنین IRQ مربوطه) ایجاد می شود.

شکل 16 ساختار کانال های ورودی را در یک تایمر با هدف کلی25 نشان می دهد. همانطور که می بینید، هر ورودی به یک آشکارساز لبه متصل است، که همچنین مجهز به فیلتری است که برای “debounce” سیگنال ورودی استفاده می شود. خروجی آشکارساز لبه به یک مالتی پلکسر منبع (IC1، IC2 و غیره) می رود. در صورتی که ورودی/خروجی معینی به دستگاه جانبی دیگری اختصاص داده شود، این امکان را می دهد که کانال های ورودی را مجدداً ترسیم کنید. در نهایت، یک پیش مقیاس‌کننده اختصاصی اجازه می‌دهد تا فرکانس سیگنال ورودی را کاهش دهد تا در صورتی که فرکانس کارکرد تایمر قابل کاهش نباشد، همانطور که در مدتی دیگر خواهیم دید.

حالت Input Capture

تایمرهای عمومی General purpose برای تولید پایه زمانی طراحی نشده اند. حتی اگر استفاده از آنها برای انجام این کار کاملاً امکان پذیر باشد، می توان از تایمرهای دیگر مانند تایمرهای اولیه basic و تایمر SysTick برای انجام این کار استفاده کرد. تایمرهای عمومی General purpose قابلیت های بسیار پیشرفته تری دارند که می توان از آنها برای سایر فعالیت های مهم مرتبط با زمان استفاده کرد.

شکل زیر ساختار کانال های ورودی را در یک تایمر General purpose نشان می دهد. همانطور که می بینید، هر ورودی به یک آشکارساز لبه متصل است و مجهز به فیلتری است که برای “debounce” سیگنال ورودی استفاده می شود. خروجی آشکارساز لبه به یک مالتی پلکسر (IC1، IC2 و غیره) وصل می شود که این امکان را فراهم می سازد تا در صورتی که I/O  معینی به واحد جانبی دیگری اختصاص داده شود، ورودی کانال های تایمر ، مجدداً ترسیم شود. در نهایت، یک prescaler  اختصاصی باعث کاهش فرکانس سیگنال ورودی میشود  تا در صورتی که فرکانس کاری تایمر قابل کاهش نباشد، تناسب فرکانسی فراهم شود.

حالت Input capture  توسط تایمرهای پیشرفته advanced و همه منظوره general purpose ارائه می شود .این حالت امکان محاسبه فرکانس سیگنال های خارجی اعمال شده به هر یک از 4 کانالی که این تایمرها ارائه می دهند را فراهم می سازد و عمل capture  به طور مستقل برای هر کانال انجام می شود.

شکل زیر نحوه عملکرد فرآیند capture  را نشان می دهد. TIMx  تایمری است که برای کار در فرکانس کلاک TIMx_CLK معین پیکربندی شده است. به این معنی که رجیستر TIMx_CNT را تا مقدار Period هر 1/ TIMx_CLK ثانیه افزایش می دهد. فرض کنید سیگنال موج مربعی را به یکی از کانال‌های تایمر اعمال می‌کنیم و تایمر را به گونه‌ای تنظیم می‌کنیم که در هر لبه بالا رونده سیگنال ورودی، تحریک trigg شود. میبینیم که رجیستر TIMx_CCRx با محتوای رجیستر TIMx_CNT در هر انتقال شناسایی شده (شمارش) به‌روزرسانی می شود. هنگامی که این اتفاق می افتد، تایمر متناظرا یک وقفه یا یک درخواست DMA ایجاد می کند که اجازه می دهد تا مقدار شمارنده را دنبال کند.

برای محاسبه period  سیگنال خارجی، دو capture متوالی مورد نیاز است. دوره period   با کم کردن دو مقدار CNT0 (مقدار 4 در شکل زیر) و CNT1 (مقدار 20 در شکل زیر) و با استفاده از فرمول زیر محاسبه می شود:

Capture = CNT1 CNT0 if CNT0 < CNT1

Capture = (T IMx_P eriod CNT0) + CNT1 if CNT0 > CNT1

CHP rescaler  یک prescaler  دیگری است که به کانال ورودی اعمال می شود و PolarityIndex اگر کانال حساس به لبه بالارونده یا پایین رونده سیگنال ورودی باشد، برابر با 1 است و اگر حساس به هر دو لبه باشد برابر با 2 است.

شرایط دیگر این است که فرکانس UEV باید کمتر از فرکانس نمونه برداری از سیگنال باشد. دلیل اهمیت این موضوع واضح است: اگر تایمر سریعتر از سیگنال نمونه برداری شده کار کند، قبل از اینکه بتواند از لبه های سیگنال نمونه برداری کند، سرریز می شود (یعنی Period شمارنده تمام می شود ، شکل زیر را ببینید). به همین دلیل، معمولاً بهتر است مقدار Period روی حداکثر قرار گرفته و ضریب Prescaler برای کاهش فرکانس شمارش افزایش پیدا کند.

این مقاله را با دوستانتان به اشتراک بگذارید!

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

این مقاله را با دوستانتان به اشتراک بگذارید!

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

Shopping cart
Start typing to see posts you are looking for.

Sign in

No account yet?