در فصل قبل توجه خود را بر روی کنترلر ADC متمرکز کردیم و مرتبط ترین ویژگی های این ابزار جانبی مهم را که همه میکروکنترلرهای STM32 ارائه می کنند، نشان دادیم. معکوس این به مبدل دیجیتال به آنالوگ (DAC) نامیده می شود.
بر اساس خانواده و پکیج مورد استفاده، میکروکنترلرهای STM32 معمولاً فقط یک DAC با یک یا دو خروجی اختصاصی ارائه میدهند، به استثنای تعداد کمی از پارات نامبرهای سری STM32F3 که دارای دو DAC ، (اولی با دو خروجی و دیگری فقط با یک خروجی) می باشند.
کانال های DAC می توانند در حالت 8/12 بیتی پیکربندی شوند، و تبدیل دو کانال را می توان به طور مستقل یا همزمان انجام داد: حالت آخر در برنامه هایی مفید است که باید دو سیگنال مستقل اما همزمان را تولید کرد (به عنوان مثال، در برنامه های صوتی). همانند ابزار جانبی ADC، DAC نیز می تواند توسط یک تایمر اختصاصی فعال شود تا سیگنال های آنالوگ در یک فرکانس مشخص تولید شوند.
این فصل به معرفی سریع ویژگیهای این واحد جانبی میپردازد و مسئولیت بررسی عمیقتر ویژگیهای DAC در هر میکروکنترلر STM32 خاص به خواننده واگذار میشود. طبق معمول، قصد داریم توضیح مختصری در مورد نحوه عملکرد کنترلر DAC ارائه دهیم.
Introduction to the DAC Peripheral
DAC دستگاهی است که یک عدد را به سیگنال آنالوگ تبدیل می کند که متناسب با ولتاژ مرجع VREF است (شکل 1 را ببینید). سری DAC های بسیاری در مارکت وجود دارد. برخی از اینها عبارتند از مدولاتورهای عرض پالس (PWM)، درون یابی، DACهای سیگما-دلتا و DACهای سرعت بالا. ما در فصل 11 نحوه استفاده از تایمر STM32 را برای تولید سیگنال های PWM بررسی و از این قابلیت برای تولید موج سینوسی در خروجی با کمک فیلتر پایین گذر RC استفاده کردیم.
تجهیزات جانبی DAC موجود در میکروکنترلرهای STM32 بر اساس شبکه نردبانی مقاومتی R-2R مشترک ، هستند. نردبان مقاومتی resistor ladder یک مدار الکتریکی است که از واحدهای تکرار شده مقاومتی ساخته شده است ، روشی ارزان و ساده برای انجام تبدیل دیجیتال به آنالوگ با استفاده از شبکههای مقاومتی تکراری که با مقاومتهای بسیار دقیق ساخته شدهاند. شبکه به عنوان یک تقسیم کننده ولتاژ قابل برنامه ریزی بین ولتاژ مرجع و زمین عمل می کند.
یک شبکه نردبانی مقاومتی 8 بیتی R-2R در شکل 2 نشان داده شده است. هر بیت از DAC توسط گیت های منطقی دیجیتال هدایت می شود. در حالت ایده آل، این گیت ها بیت ورودی را بین V = 0 (logic 0) و V = VREF (logic 1) تغییر می دهند. شبکه R-2R باعث می شود که این بیت های دیجیتال به اندازه مشارکتشان در ولتاژ خروجی VOUT سهیم شوند. بسته به اینکه کدام بیت روی 1 و کدام روی 0 تنظیم شده باشد، ولتاژ خروجی یک مقدار پلکانی متناظر بین 0 و VREF منهای مقدار کمترین گام که مربوط به بیت 0 است ،خواهد داشت.
برای یک مقدار عددی معین D، از یک DAC R-2R با N بیت و سطوح منطقی V/VREF0، ولتاژ خروجی VOUT برابر است با:
به عنوان مثال، اگر N = 12 (از این رو ) و VREF = 3.3 ولت (ولتاژ تغذیه آنالوگ در MCU STM32)، VOUT بین 0 ولت (VAL = 0 = 000000002) و حداکثر (VAL = 4095 = 111111112) تغییر می کند.:
با گام های (متناظر با VAL = 1):
با این حال، همیشه به خاطر داشته باشید که دقت و پایداری خروجی DAC به شدت تحت تأثیر کیفیت دامنه ولتاژ VDDA و چیدمان PCB است.
HAL_DAC Module
پس از آشنایی مختصر با مهمترین ویژگی های ارائه شده توسط واحد جانبی DAC در میکروکنترلرهای STM32، زمان مناسبی است که به API های CubeHAL مربوطه بپردازیم.
برای تنظیم واحد جانبی DAC، HAL ساختار DAC_HandleTypeDef را به صورت زیر تعریف می شود:
DAC_TypeDef *Instance; /* Pointer to DAC descriptor */
__IO HAL_DAC_StateTypeDef State; /* DAC communication state */
HAL_LockTypeDef Lock; /* DAC locking object */
DMA_HandleTypeDef *DMA_Handle1; /* Pointer DMA handler for channel 1 */
DMA_HandleTypeDef *DMA_Handle2; /* Pointer DMA handler for channel 2 */
__IO uint32_t ErrorCode; /* DAC Error code */
} DAC_HandleTypeDef;
- Instance: اشاره گر به توصیفگر DAC ایست که قرار است از آن استفاده کنیم. به عنوان مثال، DAC1 توصیف کننده اولین واحد جانبی DAC است.
- DMA_Handle{1،2}: اشاره گر به کنترل کننده DMA ایست که برای انجام تبدیل های D/A در حالت DMA پیکربندی شده است. در DAC با دو کانال خروجی، دو کنترل کننده DMA مستقل برای انجام تبدیل در هر کانال وجود دارد.
همانطور که می بینید، ساختار DAC_HandleTypeDef با دیگر توصیفگرهای کنترل کننده تاکنون استفاده شده متفاوت است. در واقع، پارامتر Init اختصاصی را که توسط تابع HAL_DAC_Init() برای پیکربندی DAC استفاده میشود، ارائه نمیکند. به همین پیکربندی مؤثر DAC در سطح کانال انجام و از ساختار DAC_ChannelConfTypeDef که به شکل زیر تعریف میشود درخواست میشود:
typedef struct {
uint32_t DAC_Trigger; /* Specifies the external trigger for the selected
DAC channel */
uint32_t DAC_OutputBuffer;/* Specifies whether the DAC channel output buffer
is enabled or disabled */
} DAC_ChannelConfTypeDef;
- DAC_Trigger: منبع مورد استفاده برای شروع تبدیل DAC را مشخص می کند. هنگامی که DAC به صورت دستی با استفاده از تابع HAL_DAC_SetValue() درایو می شود، می تواند مقدار DAC_TRIGGER_NONE را در برگیرد. مقدار DAC_TRIGGER_SOFTWARE را هنگامی که DAC در حالت DMA بدون تایمر برای “کلاک” تبدیل ها درایو میشود، در برمیگیرد. مقدار DAC_TRIGGER_Tx_TRGO برای نشان دادن تبدیل توسط یک تایمر اختصاصی ، استفاده می شود.
- DAC_OutputBuffer: بافر خروجی اختصاصی را فعال می کند.
برای پیکربندی کانال DAC، از تابع زیر استفاده می کنیم:
HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef* hdac, DAC_ChannelConfTypeDef* sConfig, uint32_t Channel);
Driving the DAC Manually
پریفرال DAC را می توان به صورت دستی یا با استفاده از DMA و یک منبع trigger (به عنوان مثال یک تایمر اختصاصی) درایو کرد. اکنون قصد داریم روش اول را تحلیل کنیم که در مواقعی که نیازی به تبدیل در فرکانس های بالا نداریم استفاده می شود.
اولین مرحله شامل راه اندازی دستگاه جانبی با فراخوانی تابع زیر است :
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel);
12-4. Driving the DAC in DMA Mode Using a Timer
رایج ترین استفاده از واحد جانبی DAC، تولید یک شکل موج آنالوگ با فرکانس معین است (به عنوان مثال برنامه های صوتی). در این شرایط، بهترین راه برای درایو DAC استفاده از DMA و تایمر برای فعال کردن تبدیل است.
برای راه اندازی DAC و انتقال در حالت DMA ، باید جفت channel/stream کانال/جریان DMA مربوطه را پیکربندی و از تابع زیر استفاده کنیم:
HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment);
که اشاره گر به نمونهای از ساختار DAC_HandleTypeDef، کانال مورد نظر برای فعالسازی (DAC_CHANNEL_1 یا DAC_CHANNEL_2)، اشارهگر به آرایه مقادیر برای انتقال در حالت DMA، طول آن، و alignment مقادیر خروجی در حافظه ، که میتواند مقدار DAC_ALIGN_8B_R برای درایو DAC در حالت 8 بیتی، DAC_ALIGN_12B_L یا DAC_ALIGN_12B_R برای درایو DAC در حالت 12 بیتی که مقدار خروجی را به ترتیب left- or right-aligned عبور می دهد، میپذیرد.
به عنوان مثال، ما می توانیم به راحتی با استفاده از DAC یک موج سینوسی تولید کنیم. در فصل 11 نحوه استفاده از حالت PWM یک تایمر برای تولید امواج سینوسی را تحلیل کردیم. اگر MCU واحد DAC را ارائه دهد، همان عملیات را می توان راحت تر انجام داد. علاوه بر این، بسته به کاربردهای خاص، با فعال کردن بافر خروجی، میتوانیم از قطعات پسیو خارجی اجتناب کنیم.
برای تولید یک موج سینوسی که در یک فرکانس مشخص اجرا می شود، باید دوره کامل را در چند مرحله تقسیم کنیم. معمولاً بیش از 200 مرحله تقریب خوبی برای یک موج خروجی است. یعنی اگر بخواهیم یک موج سینوسی 50 هرتز تولید کنیم، باید تبدیل را در هر:
انجام دهیم.
از آنجایی که STM32 DAC دارای وضوح 12 بیتی است، باید مقدار 4095 را که مربوط به حداکثر ولتاژ خروجی است، با استفاده از فرمول زیر بر 200 مرحله تقسیم کنیم:
که ns تعداد نمونه ها و در مثال ما 200 است.
با استفاده از فرمول بالا می توانیم یک بردار اولیه برای تغذیه DAC در حالت DMA ایجاد کنیم. مانند واحد جانبی ADC، می توانیم از یک تایمر پیکربندی شده برای راه اندازی خط TRGO در فرکانس 10kHz استفاده کنیم. مثال زیر نحوه تولید یک موج سینوسی 50 هرتز را با استفاده از DAC در یک MCU STM32F072 نشان می دهد.