با سلام در این قسمت از آموزش CH سراغ واحد آنالوگ دیگری به نام DAC میریم، در قسمت قبل در مورد واحد تبدیل سیگنال آنالوگ به دیجیتال یاد گرفتیم و در این قسمت واحد تبدیل دیجیتال به آنالوگ که وظیفه آن تولید ولتاژی آنالوگ بر روی پایه میکرو است.
اگر با این واحد از میکروکنترلرها آشنایی ندارید پیشنهاد میکنم قبل از شروع این آموزش، آموزش مربوط با این بخش که توسط دوستان تهیه شده رو مطالعه کنید.
با نگاهی ساده به دیاگرام بالا متوجه خواهید شد که واحد DAC در این میکرو شباهت زیادی به DAC در میکروهای STM32 دارد، واحد DAC در WCH قابلیت تولید دو موج مثلثی و نویز را دارد که در حالت نویز مقادیر رندوم در خروجی آن قرار میگیرد.
این واحد قابلیت DMA دارد و میتوان بدون استفاده از CPU مقادیر را به آن منتقل کرد، این واحد یکطرفه است و فقط اطلاعات به این بخش وارد میشوند، همچنین قابلیت آپدیت شدن مقادیر را با پریفرال های سختافزاری و حتی نرمافزاری دارد.
در این قسمت از آموزشها ما با آپدیت نرمافزاری مقداری رو روی خروجی قرار میدهیم، سپس برای کد نهایی چند شکل موج سینوسی، کسینوسی، مربعی، مثلثی و دندانارهای در خروجی قرار میدهیم.
در فرصتی دیگر شاید در آموزش DMA این واحد را بهصورت سختافزاری آپدیت و با DMA مقادیر رو انتقال دهیم، در اینجا فعلاً ساده عمل میکنیم.
این میکرو دو پایه DAC دارد که بر روی A4 و A5 قرار دارد. بریم سراغ کد راهاندازی این پریفرال.
در ابتدا مانند همه پریفرال هایی که قبلاً راهاندازی کردهایم، کلاک مربوط به این بخش را فعال میکنیم.
1 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE); |
پس از فعال سازی کلاک نوبت به کانفیگ کردن آن است که از ساختار DAC_InitTypeDef کمک میگیریم.
یک اسم به آن اختصاص میدهیم و مقادیر را تنظیم میکنیم.
1 2 3 | DAC_InitTypeDef dactd; dactd.DAC_OutputBuffer =DAC_OutputBuffer_Enable; |
با این خط بافر خروجی را فعال میکنیم،این بافر پیشنهاد شده که فعال باشد.
1 | dactd.DAC_Trigger = DAC_Trigger_Software; |
با این خط مشخص میکنیم که اپدیت مقادیر توسط نرم افزار صورت میگیرد.
1 | dactd.DAC_WaveGeneration = DAC_WaveGeneration_None; |
با این خط مشخص میکنیم که نمیخواهیم از موج مربعی یا نویز که توسط سخت افزار ساخته میشوند استفاده کنیم.
1 | dactd.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; |
چون ما از قابلیت های سخت افزاری نویز و موج مربعی استفاده نمیکنیم، این خط تاثیری در کار ما ندارد، این خط برای تعیین حداکثر دامنه موج نویز و مثلثی سخت افزاری هست که مقادیر تعریف شده آن به شکل زیر است.
پس از تنظیم مقادیر،مقادیر را بر روی سخت افزار اعمال میکنیم و واحد DAC را فعال میکنیم به شکل زیر:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | DAC_InitTypeDef dactd; dactd.DAC_OutputBuffer =DAC_OutputBuffer_Enable; dactd.DAC_Trigger = DAC_Trigger_Software; dactd.DAC_WaveGeneration = DAC_WaveGeneration_None; dactd.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; DAC_Init(DAC_Channel_1,&dactd); DAC_Init(DAC_Channel_2,&dactd); DAC_Cmd(DAC_Channel_1,ENABLE); DAC_Cmd(DAC_Channel_2,ENABLE); |
پس از فعال سازی هر دو کانال بااستفاده از توابع زیر میتوانیم به آن ها مقدار بدیم و اپدیت کنیم مقادیر را:
1 2 3 | DAC_SetChannel1Data(DAC_Align_12b_R,2048); DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE); |
چون ما خروجی رو 12 بیتی در نظر گرفتیم مقداری که میتونیم وارد بکنیم از 0 تا 4095 هست.
درصورتیکه هشت بیتی بود 0 تا 255 بود.
حالا شاید براتون سؤال بشه که معنی اون R بغل DAC_Align_12b_R چیه؟
واحد DAC میکرو میتواند بیتهای دیتا را از سمت راست یا چپ در رجیستر خروجی بچیند؛ مانند شکل زیر:
این هم دیفاین ها تعریف شده برای انتخاب بین حالت های چیدن دیتا در DAC
خب در ادامه بریم کدی که برای تولید انواع موج ها هست رو با هم ببینیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | #include "debug.h" #include "math.h" /* Global typedef */ /* Global define */ #define Each_data_sample 360 /* Global Variable */ uint16_t sindata[360],cosdata[360],triangledata[360],rampdata[360],Squrdata[360],cnt=0; /********************************************************************* * @fn main * * @brief Main program. * * @return none */ int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); printf("SystemClk:%d\r\n",SystemCoreClock); printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() ); printf("This is printf example\r\n"); for(int s=0; s< Each_data_sample ; s++) { sindata[s] =(int) (( 2047 * sin(( s * 3.14)/(Each_data_sample/2) )) + 2047); } for(int s=0; s< Each_data_sample ; s++) { cosdata[s] =(int) (( 2047 * cos(( s * 3.14)/(Each_data_sample/2) )) + 2047); } for(int s=0; s< Each_data_sample ; s++) { rampdata[s] =(int) (s*11.375); } for(int s=0; s< Each_data_sample ; s++) { if(s<(Each_data_sample/2))triangledata[s] =(int)(2*s*11.375); else triangledata[s] =(int)(2*(Each_data_sample-s)*11.375); } for(int s=0; s< Each_data_sample ; s++) { if(s<(Each_data_sample/2))Squrdata[s] =4095; else Squrdata[s] =0; } RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE); DAC_InitTypeDef dactd; dactd.DAC_OutputBuffer =DAC_OutputBuffer_Enable; dactd.DAC_Trigger = DAC_Trigger_Software; dactd.DAC_WaveGeneration = DAC_WaveGeneration_None; dactd.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; DAC_Init(DAC_Channel_1,&dactd); DAC_Init(DAC_Channel_2,&dactd); DAC_Cmd(DAC_Channel_1,ENABLE); DAC_Cmd(DAC_Channel_2,ENABLE); while(1) { for(int t=0;t<5000;t++) { DAC_SetChannel1Data(DAC_Align_12b_R,triangledata[cnt]); //DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE); -> software trigger for one channel DAC_SetChannel2Data(DAC_Align_12b_R,~triangledata[cnt]); DAC_DualSoftwareTriggerCmd(ENABLE); cnt++;if(cnt>=360)cnt=0; Delay_Ms(1); } for(int t=0;t<5000;t++) { DAC_SetChannel1Data(DAC_Align_12b_R,Squrdata[cnt]); //DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE); -> software trigger for one channel DAC_SetChannel2Data(DAC_Align_12b_R,~Squrdata[cnt]); DAC_DualSoftwareTriggerCmd(ENABLE); cnt++;if(cnt>=360)cnt=0; Delay_Ms(1); } for(int t=0;t<5000;t++) { DAC_SetChannel1Data(DAC_Align_12b_R,sindata[cnt]); //DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE); -> software trigger for one channel DAC_SetChannel2Data(DAC_Align_12b_R,cosdata[cnt]); DAC_DualSoftwareTriggerCmd(ENABLE); cnt++;if(cnt>=360)cnt=0; Delay_Ms(1); } for(int t=0;t<5000;t++) { DAC_SetChannel1Data(DAC_Align_12b_R,sindata[cnt]); //DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE); -> software trigger for one channel DAC_SetChannel2Data(DAC_Align_12b_R,~sindata[cnt]); DAC_DualSoftwareTriggerCmd(ENABLE); cnt++;if(cnt>=360)cnt=0; Delay_Ms(1); } for(int t=0;t<5000;t++) { DAC_SetChannel1Data(DAC_Align_12b_R,rampdata[cnt]); //DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE); -> software trigger for one channel DAC_SetChannel2Data(DAC_Align_12b_R,~rampdata[cnt]); DAC_DualSoftwareTriggerCmd(ENABLE); cnt++;if(cnt>=360)cnt=0; Delay_Ms(1); } } } |
این هم شکل های خروجی برنامه ی بالا:
نویسنده شو !
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.