مهندس الکترونیک

#C
Канал
Логотип телеграм канала مهندس الکترونیک
@elec_sourceПродвигать
2,63 тыс.
подписчиков
269
фото
129
видео
274
ссылки
کانال تلگرام مهندس الکترونیک لینک حمایت در سایت رسمی حامی باش : 🌠https://hamibash.com/elec_source🌠 - لینک گروه : @elec_src_grp کانال یوتیوب https://youtube.com/@elec_source?si=oupCXK8o1DYDeAi9
#C

نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 15 :
#Backslash

در زبان C، کاراکتر «\» Backslash کاربردهای مختلفی دارد که عمدتاً در دو زمینه استفاده می‌شود:

Escape Sequences
کاراکتر «\» در ترکیب با سایر کاراکترها، به عنوان یک escape character عمل می‌کند. این ترکیبات معمولاً برای نشان دادن کاراکترهایی استفاده می‌شوند که وارد کردن آن‌ها به‌طور مستقیم دشوار یا غیرممکن است. برخی از این ترکیبات عبارتند از:

\n: نمایانگر کاراکتر خط جدید (newline)
\t: نمایانگر یک تب (tab)
,....
۲. Line Continuation
در زبان C، اگر بخواهید یک خط کد طولانی را در چند خط بنویسید، می‌توانید از بَک‌اسلش در انتهای خط استفاده کنید تا نشان دهید که خط کد در خط بعدی ادامه دارد. به‌طور مثال:
printf("This is a very long line that we want to \
split into multiple lines for better readability.\n");

لینک حمایت مالی حامی‌باش جهت حمایت از کانال
#مهندس_الکترونیک
#الکترونیک
🆔 @elec_source
#C
#clean_code

نکات برنامه نویسی تمیز برای میکرو کنترلر ها
#قسمت_3
#Comment
استفاده از توضیحات مناسب در کد نویسی برای میکرو کنترلر ها بسیار مهم است زیرا کمک می‌کند تا برنامه نویسان و سایر افرادی که با کد شما در ارتباط هستند، بهتر از منظر عملکرد و نحوه استفاده از قسمت‌های مختلف کد شما آگاه شوند. در زیر تعدادی از مزایای استفاده از توضیحات مناسب در کد را می‌توان ذکر کرد:

توضیح عملکرد توابع: با اضافه کردن توضیحات به توابع، می‌توانید عملکرد و وظیفه آنها را برای سایر برنامه نویسان توضیح دهید. این می‌تواند بهبود قابلیت خوانایی کد و افزایش توانایی تعامل با توابع در طول توسعه و تغییرات مفید باشد.

توضیح پارامترها: با توضیح دادن معنی و استفاده از پارامترهای توابع، می‌توانید به برنامه نویسان دیگر کمک کنید تا بفهمند که چه نوع داده‌هایی باید به توابع ارسال کنند و چگونه از آنها استفاده کنند. این می‌تواند خطاهای احتمالی را کاهش داده و کد را ایمن‌تر کند.

توضیح متغیرها: با توضیح دادن نام و معنی متغیرها، می‌توانید برنامه‌نویسان را در درک مفهوم و کاربرد متغیرها در کد خود یاری کنید. این کمک می‌کند تا کد شما قابل فهم‌تر و ساده‌تر باشد و اشتباهاتی که به دلیل عدم درک صحیح متغیرها ایجاد می‌شوند را کاهش دهد.

توضیح بخش‌های مختلف کد: با اضافه کردن توضیحات به بخش‌های مختلف کد، می‌توانید به سایر برنامه‌نویسان کمک کنید تا ساختار کلی برنامه را درک کنند و راحتتر با کد شما کار کنند. علاوه بر این، این توضیحات می‌توانند درک و نگهداری کد را برای شما و سایر اعضای تیم تسهیل کنند.

مثال :


#include <avr/io.h>

// Function to turn on the LED
void turnOnLED() {
PORTB |= (1 << PB0);
}

// Function to turn off the LED
void turnOffLED() {
PORTB &= ~(1 << PB0);
}

int main(void) {
DDRB |= (1 << PB0); // Set pin as output

while (1) {
turnOnLED(); // Call the turnOnLED function
// Perform other operations
turnOffLED(); // Call the turnOffLED function
// Perform other operations
}

return 0;
}


#include <avr/io.h>

int main(void) {
int counter = 0; // Counter variable

while (1) {
if (counter < 10) {
counter++; // Increment the counter
} else {
counter = 0; // Reset the counter to zero
}

// Use the value of the counter
if (counter % 2 == 0) {
// Perform other operations
}
}

return 0;
}



حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
#clean_code

نکات برنامه نویسی تمیز برای میکرو کنترلر ها
#قسمت_2
#توابع_کوچک_و_مستقل

توابع کوچک و مستقل به عنوان یکی از اصول مهم clean code، به معنای نوشتن توابعی است که کوچک بوده و تنها یک وظیفه را انجام می‌دهند. این اصل به عنوان SRP (Single Responsibility Principle) نیز شناخته می‌شود. در ادامه، برخی از جزئیات کلیدی درباره توابع کوچک و مستقل را مرور می‌کنیم:

اندازه کوچک: توابع باید به گونه‌ای نوشته شوند که بتوان آنها را به سرعت و به طور کامل درک کرد. بهتر است توابع حداکثر تا چندین خط کد باشند. این به خوانایی کد کمک می‌کند و اجازه می‌دهد که توابع به طور مستقل تست شوند.

یک وظیفه: هر تابع باید تنها یک وظیفه را انجام دهد و به یک هدف خاص متمرکز شود. این بهینه‌سازی میزان قابلیت خواندن و تست کد را افزایش می‌دهد.

عدم تداخل: توابع باید به گونه‌ای نوشته شوند که تداخل با توابع دیگر را به حداقل برسانند. باید از استفاده از متغیرهای مشترک و تغییر وضعیت‌های خارجی در توابع خود پرهیز کنید.

نامگذاری مناسب: نامگذاری توابع باید معنادار و شفاف باشد و هدف و وظیفه آنها را با دقت نشان دهد. نام تابع باید به تنهایی قادر باشد توضیح دهد که تابع چه کاری انجام می‌دهد.

عدم تکرار: در صورتی که قسمتی از کد در چندین تابع تکرار شود، بهتر است آن قسمت را در یک تابع مستقل قرار داده و از آن در توابع مختلف استفاده کنید. این کاهش تکرار کد و افزایش قابلیت تغییر و تست را فراهم می‌کند.

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

int add(int a, int b) {
return a + b;
}
این تابع به صورت کوچک و مستقل عمل می‌کند و تنها یک وظیفه را انجام می‌دهد، یعنی جمع دو عدد را محاسبه می‌کند. با استفاده از نامگذاری مناسب، کارکرد تابع به طور واضح مشخص است.


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک
🆔 @elec_source
#C
#clean_code

نکات برنامه نویسی تمیز برای میکرو کنترلر ها
#قسمت_1
#نامگذاری_متغیرها

نام‌گذاری مناسب متغیرها در برنامه‌نویسی به شدت تاثیرگذار است و می‌تواند به خوانایی و قابل فهم بودن کد شما کمک کند. در ادامه به برخی اصول نام‌گذاری مناسب متغیرها در برنامه‌نویسی به زبان C می‌پردازیم:

1. از نام‌های معنادار استفاده کنید: نام‌گذاری متغیرها باید معنایی داشته باشد و از نام‌هایی استفاده شود که معنای آنها به راحتی قابل درک باشد. همچنین از نام‌های کوتاه و مخفف استفاده نشود.

2. از نام‌های کوتاه و یا اختصاری استفاده نکنید: استفاده از نام‌های کوتاه و یا اختصاری باعث کاهش خوانایی کد می‌شود و ممکن است باعث ایجاد ابهام در مورد نام متغیرها شود.

3. از نام‌های یکسان برای متغیرهای مختلف استفاده نکنید: اطمینان حاصل شود که نام‌های متغیرها برای هر متغیر به صورت منحصر به فرد و یکتا باشد و از نام‌های یکسان برای متغیرهای مختلف استفاده نشود.

4. استفاده از پیشوند برای نام‌گذاری متغیرها: استفاده از پیشوند برای نام‌گذاری متغیرها این امکان را می‌دهد که متغیرهای با عملکرد مشابه با یکدیگر گروه‌بندی شوند و در صورت نیاز به خواندن کد، به راحتی قابل درک باشند.

5. استفاده از camelCase یا snake_case: دو روش شناخته شده برای نام‌گذاری متغیرها در برنامه‌نویسی به زبان C، camelCase و snake_case هستند. در روش camelCase، کلمات به صورت بزرگی شروع می‌شوند به جز کلمه اول و در snake_case، کلمات با استفاده از underscore (_) از یکدیگر جدا می‌شوند. هر کدام از این روش‌ها برای نام‌گذاری متغیرها می‌توانند مفید باشند.

به طور کلی، نام‌گذاری مناسب متغیرها به شما کمک می‌کند که کد خود را قابل فهم و خوانایی برای خود و دیگران کنید. بهتر است در هنگام نام‌گذاری متغیرها، فکر کافی به معنای آنها و نیز به راحتی قابل درک بودن نام‌ها برای دیگران داشته باشید.

در ادامه یک مثال از نام‌گذاری مناسب متغیرها در برنامه‌نویسی به زبان C آورده شده است:

int temperatureSensorPin = A0; // متغیری برای نگهداری شماره پین حسگر دما
float temperatureValue = 0.0; // متغیری برای نگهداری دمایی که از حسگر خوانده شده است

void setup() {
pinMode(temperatureSensorPin, INPUT); // تنظیم حالت پین حسگر به حالت ورودی
Serial.begin(9600); // شروع ارتباط سریال با سریال مانیتور
}

void loop() {
// خواندن دمایی که از حسگر خوانده شده و ارسال آن به سریال مانیتور
temperatureValue = readTemperature(temperatureSensorPin);
Serial.println(temperatureValue);
delay(1000);
}

float readTemperature(int pin) {
// خواندن مقدار آنالوگ از پین حسگر و تبدیل آن به دما
int sensorValue = analogRead(pin);
float voltage = sensorValue * (5.0 / 1023.0); // تبدیل مقدار آنالوگ به ولتاژ
float temperature = (voltage - 0.5) * 100.0; // تبدیل ولتاژ به دما با فرمول خاص
return temperature;
}


در این مثال، متغیرهای temperatureSensorPin و temperatureValue به صورت camelCase نام‌گذاری شده‌اند و نام‌های آنها به معنای آنها مرتبط هستند. همچنین، پیشوند temperature در نام‌گذاری این دو متغیر به کار رفته است که به دلیل مرتبط بودن این دو متغیر با دما، مفید است.

حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک
🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 14 :

#bitfiled

در زبان برنامه‌نویسی C، بیت فیلد (Bit Field) به عنوان یک نوع داده‌ای (Data Type) تعریف می‌شود که به کاربر اجازه می‌دهد تا بیت‌های داخل یک آدرس حافظه را به صورت مجزا کنترل کند. این داده‌ی نوع، در واقع به برچسب‌های مخصوصی که در داخل یکی از متغیرهای دیگر در C می‌توان اعمال کرد، ارجاع داده می‌شود.

مثال:

برای تعریف یک بیت فیلد در C، ابتدا باید یک ساختار (Struct) تعریف کرد. در این ساختار، می‌توان بیت‌های مختلف را با استفاده از مقادیر صحیح (Integer) تعریف کرد. به عنوان مثال، برای تعریف یک بیت فیلد به نام flags با دو بیت، می‌توان به شکل زیر عمل کرد:

struct {
unsigned int flag1: 1;
unsigned int flag2: 1;
} flags;


در این مثال، یک ساختار با دو عضو flag1 و flag2 تعریف شده است که هر کدام از آنها یک بیت از آدرس حافظه را تشکیل می‌دهد. با استفاده از این ساختار، می‌توان هر کدام از بیت‌های flag1 و flag2 را به صورت مجزا تنظیم کرد. به عنوان مثال:

flags.flag1 = 1; 
// تنظیم بیت flag1 به 1
flags.flag2 = 0;
// تنظیم بیت flag2 به 0


در این مثال، با استفاده از نام ساختار flags و عضو flag1 و flag2، هر کدام از بیت‌های مربوطه را به صورت مجزا تنظیم کردیم.

فرض کنید می خواهید از واحد ADC میکروکنترلر AVR برای خواندن ولتاژ ورودی استفاده کنید. می توانید از یک ساختار داده ای با فیلدهای بیت برای ذخیره نتایج ADC استفاده کنید:

typedef struct {
unsigned int channel : 3; // 3-bit field for channel selection
unsigned int value : 10; // 10-bit field for ADC value
} AdcResult;


حال می توانید این ساختار داده ای را در برنامه AVR خود استفاده کنید:

int main() {
AdcResult result;

// set channel to 0
result.channel = 0;

// start ADC conversion
ADCSRA |= (1 << ADSC);

// wait for conversion to complete
while (ADCSRA & (1 << ADSC));

// read ADC value and store in result
result.value = ADC;

// do something with the result

return 0;
}


در اینجا، ابتدا یک متغیر از نوع AdcResult تعریف شده است و سپس فیلد channel به مقدار 0 تنظیم شده است. سپس ADC شروع به تبدیل می کند و بعد از پایان تبدیل، مقدار ADC در فیلد value ذخیره می شود. سپس می توانید از این متغیر در برنامه AVR خود استفاده کنید.

استفاده از Bit field ها به عنوان یک روش بهینه سازی حافظه در برنامه نویسی C مورد استفاده قرار می گیرد. با استفاده از این روش، می توانید حجم حافظه را به صورت قابل توجهی کاهش دهید و در عین حال عملکرد برنامه را بهبود بخشید.

مطالعه بیشتر LINK


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 13 :

#constants

متغیرها می‌توانند با استفاده از کلمه کلیدی const و پیش پردازنده #define به عنوان ثابت تعریف شوند. جزئیات درباره این دو روش به شرح زیر آمده است.

کلمه کلیدی const:
متغیرها می‌توانند با استفاده از کلمه کلیدی "const" قبل از نوع داده‌ای متغیر به عنوان ثابت تعریف شوند. متغیرهای ثابت فقط یک بار می‌توانند مقداردهی اولیه شوند و مقدار پیش‌فرض آنها صفر است.

برنامه‌ای که نمونه‌ای از تعریف متغیرهای ثابت در زبان برنامه‌نویسی C با استفاده از کلمه کلیدی const را نشان می‌دهد به شرح زیر است:

#include <stdio.h>
int main() {
const int a;
const int b = 12;
printf("مقدار پیش‌فرض متغیر a: %d", a);
printf("مقدار متغیر b: %d", b);
return 0;
}


خروجی این برنامه به شرح زیر است:

مقدار پیش‌فرض متغیر a: 0
مقدار متغیر b: 12


دستور قبل پردازنده #define:
متغیرها می‌توانند با استفاده از دستور پیش پردازنده #define به عنوان ثابت تعریف شوند، زیرا این دستور یک نام مستعار برای هر مقدار تعریف می‌کند.

برنامه‌ای که نمونه‌ای از تعریف متغیرهای ثابت در زبان برنامه‌نویسی C با استفاده از دستور قبل پردازنده #define را نشان می‌دهد به شرح زیر است:

#include <stdio.h>
#define num 25
int main() {
printf("مقدار num برابر است با: %d", num);
return 0;
}


خروجی این برنامه به شرح زیر است:

مقدار num برابر است با: 25


در ادامه، تفاوت‌های مهم بین const و ماکروها را بررسی می‌کنیم:

1. زمانی که تعریف می‌شوند:
- const: متغیرهای ثابت با استفاده از کلمه کلیدی const در زمان کامپایل تعریف می‌شوند. آنها به عنوان متغیرهای با نوع داده در کد شناخته می‌شوند و مقدار آنها را نمی‌توان در طول اجرای برنامه تغییر داد.
- ماکروها: ماکروها با استفاده از دستور پیش پردازنده #define تعریف می‌شوند. آنها بیشتر به عنوان جایگزینی متنی برای مقادیر استفاده می‌شوند. ماکروها در زمان قبل از فرآیند کامپایل، برای تغییر کدهای متنی بکار می‌روند و بعد از آن در برنامه نهایی وجود ندارند.

2. بررسی و نوع داده:
- const: متغیرهای ثابت معمولاً دارای نوع داده‌ای هستند و به صورت استاندارد در زبان‌های برنامه‌نویسی دارای بررسی نوع داده هستند. این به این معناست که کامپایلر قادر است از قوانین نوع داده استفاده کند و خطاها را چک کند.
- ماکروها: ماکروها در واقع متنی هستند که در هر جایی که ماکرو فراخوانی می‌شود، جایگزینی می‌شوند. زیرا ماکروها قبل از فرآیند کامپایل تبدیل می‌شوند، بنابراین نوع داده‌ای ندارند و تنها به متن جایگزین شده می‌شوند.

3. محدوده قابل دسترسی:
- const: متغیرهای ثابت معمولاً دارای محدوده قابل دسترسی است. به این معنا که آنها فقط در دامنه‌ای که تعریف شده‌اند، قابل دسترسی هستند.
- ماکروها: ماکروها به صورت جایگزینی متنی عمل می‌کنند و به هر جایی که ماکرو فراخوانی می‌شود، جایگزین می‌شوند. بنابراین، ماکروها دارای محدوده قابل دسترسی مستقلی نیستند و در تمام برنامه قابل دسترسی هستند.

4. عملکرد:
- const: متغیرهای ثابت در زمان اجرای برنامه به صورت مستقیم استفاده می‌شوند. آنها در حافظه ذخیره می‌شوند و به عنوان یک مکانیزم قابل اعتماد برای تعریف مقادیر ثابت عمل می‌کنند.
- ماکروها: ماکروها قبل از فرآیند کامپایل جایگزینی می‌شوند و هیچ محلی در حافظه اشغال نمی‌کنند. به عنوان یک جایگزینی متنی کار می‌کنند و مقدار ماکرو در کل برنامه جایگزین می‌شود.


در زمینه برنامه‌نویسی با متغیرهای ثابت (constants)، می‌توان به نکات زیر اشاره کرد:

1. تعریف مقدار اولیه: متغیرهای ثابت باید در هنگام تعریف مقدار اولیه داشته باشند و بعد از آن نمی‌توانند تغییر کنند. بنابراین، حتماً باید در زمان تعریف مقدار اولیه متغیر ثابت را ارائه دهید.

2. نامگذاری مناسب: برای متغیرهای ثابت، نامگذاری مناسبی انتخاب کنید تا مفهوم و مقصود مقدار ثابت را به خوبی بیان کند. استفاده از نامهای توصیفی و معنی‌دار می‌تواند بهبود خوانایی کد شما را فراهم کند.

3. استفاده در جای مناسب: از متغیرهای ثابت در جاهایی استفاده کنید که مقادیر آنها ثابت باقی می‌مانند و نیازی به تغییر ندارند. این شامل مقادیر ثابت در فرمول‌ها، ثوابت ریاضی، کدهای ثابت و مقادیر پیش‌فرض می‌شود.


استفاده صحیح از متغیرهای ثابت در برنامه‌نویسی می‌تواند کد شما را قابل فهم‌تر، قابل نگهداری‌تر و کارآمدتر کند. با توجه به ویژگی‌های ثابت، می‌توانید در برنامه‌نویسی خود از آنها بهره‌برداری کنید.


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 12 :

تفاوت += ,=+

در زبان برنامه‌نویسی C، عملگرهای += و =+ دو عملگر جداگانه هستند و تفاوت‌های مهمی در عملکرد آنها وجود دارد.

1. +=:
عملگر =+ یک عملگر ترکیبی است که به متغیر ارزشی را اضافه می‌دهد و سپس نتیجه را به همان متغیر اختصاص می‌دهد. به طور خلاصه، x += y برابر است با x = x + y. بدین ترتیب، مقدار متغیر x با ارزش y افزایش می‌یابد.

مثال:
int x = 5;
int y = 3;
x += y; // مقدار x به 8 تغییر می‌کند (x = x + y)


2. =+:
عملگر += در زبان C به صورت تفکیکی از دو عملگر تشکیل شده است. عملگر = برای اختصاص مقدار به یک متغیر استفاده می‌شود، و عملگر + برای انجام عملیات جمع بین دو عدد استفاده می‌شود. بنابراین، وقتی از x =+ y استفاده می‌کنیم، به واقع معادل x = +y خواهیم داشت. به طور خلاصه، مقدار متغیر x برابر با عدد مثبت y قرار می‌گیرد.

مثال:
int x = 5;
int y = 3;
x =+ y;
// مقدار x به 3 تغییر می‌کند (x = +y)


بنابراین، تفاوت اصلی بین += و =+ در C در این است که += مقدار را به متغیر اضافه می‌کند، در حالی که += مقدار را به صورت مثبت به متغیر اختصاص می‌دهد.

بنابراین، پس از اجرای کد زیر:
x = -10;
y = -20;
z =+ y;

مقادیر متغیرها به ترتیب به شکل زیر تغییر می‌کنند:
- x برابر -10 می‌شود.
- y برابر -20 می‌شود.
- z برابر +20 می‌شود.

توجه کنید که z برابر +20 است، زیرا y مقدار -20 داشت و با +=، +y به عنوان عدد مثبت به z اختصاص داده شده است.


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 11 :

#struct
در زبان برنامه‌نویسی C، "struct" یک کلمه کلیدی است که برای تعریف یک نوع دادهٔ ساختاری (structure) استفاده می‌شود. یک ساختار مجموعه‌ای از متغیرها است که به صورت یک واحد مجزا مدلسازی می‌شوند و به عنوان یک نوع داده جدید تعریف می‌شوند. این متغیرها می‌توانند انواع داده‌های مختلفی مانند اعداد صحیح، اعداد اعشاری، رشته‌ها و غیره باشند.

ساختارها (structs) به برنامه‌نویسان اجازه می‌دهند تا اطلاعات مرتبط را در یک متغیر ترکیبی جمع‌آوری کنند. این کار باعث می‌شود کد خوانا‌تر، قابل توسعه‌تر و قابل نگهداری‌تر شود. به عبارت دیگر، می‌توانید یک ساختار را به عنوان یک "کانتینر" از متغیرها در نظر بگیرید که این متغیرها می‌توانند به طور مستقل یا در کنار یکدیگر استفاده شوند.

برای تعریف یک ساختار، ابتدا باید الگوی ساختار را تعریف کنید. این الگو شامل نام ساختار و نوع و تعداد فیلدهایی است که در آن قرار دارند. به عنوان مثال، فرض کنید می‌خواهید یک ساختار برای نمایش یک کتاب تعریف کنید که شامل عنوان، نویسنده و سال انتشار است. شما می‌توانید ساختار زیر را برای این منظور تعریف کنید:

struct Book {
char title[100];
char author[100];
int year;
};


در این مثال، "Book" نام ساختار است و سه فیلد با نوع‌های داده‌ای مختلف در آن تعریف شده است: "title" یک رشته با حداکثرطول 100 کاراکتر، "author" یک رشته با حداکثر طول 100 کاراکتر و "year" یک عدد صحیح است.

با تعریف این ساختار، شما می‌توانید متغیرهایی از نوع "Book" بسازید و از فیلدهای داخلی آن‌ها استفاده کنید. به عنوان مثال:

struct Book myBook;

strcpy(myBook.title, "The Catcher in the Rye");
strcpy(myBook.author, "J.D. Salinger");
myBook.year = 1951;


در اینجا یک متغیر به نام "myBook" از نوع "Book" تعریف شده است. با استفاده از عملگر "."، می‌توانیم به فیلدهای داخلی متغیر "myBook" دسترسی پیدا کنیم و مقادیر آن‌ها را تنظیم کنیم. در این حالت، مقادیر عنوان، نویسنده و سال انتشار کتاب را مشخص کرده‌ایم.

بنابراین، تفاوت اصلی بین "struct" و "enum" در این است که "struct" یک نوع داده ساختاری است که مجموعه‌ای از فیلدها را در خود جمع‌آوری می‌کند، در حالی که "enum" برای تعریف مجموعه‌ای از ثابت‌ها با مقادیر صحیح استفاده می‌شود.

در برنامه‌نویسی میکروکنترلرها، می‌توانید از ساختارها برای نگهداری و مدیریت اطلاعات مربوط به ماژول‌ها و واحدهای مختلف استفاده کنید. در مثال زیر، یک نمونه از استفاده از ساختار (struct) در واحد RTC (Real-Time Clock) برای میکروکنترلر LPC1768 آورده شده است:

#include <lpc17xx_rtc.h>

// تعریف ساختار برای نگهداری اطلاعات زمان و تاریخ
struct DateTime {
uint32_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
};

// تابع برای دریافت زمان و تاریخ از RTC و ذخیره در ساختار DateTime
void getDateTime(struct DateTime* dt) {
RTC_GetFullTime(LPC_RTC, &(dt->hour), &(dt->minute), &(dt->second));
RTC_GetFullDate(LPC_RTC, &(dt->day), &(dt->month), &(dt->year));
}

int main() {
struct DateTime currentDateTime;

// دریافت زمان و تاریخ فعلی و ذخیره در ساختار DateTime
getDateTime(&currentDateTime);

// استفاده از اطلاعات زمان و تاریخ
printf("Current date and time: %02d/%02d/%04d %02d:%02d:%02d\n",
currentDateTime.day, currentDateTime.month, currentDateTime.year,
currentDateTime.hour, currentDateTime.minute, currentDateTime.second);

return 0;
}



در این مثال، یک ساختار به نام "DateTime" تعریف شده است که شامل فیلدهای مربوط به زمان و تاریخ می‌باشد. سپس، تابع "getDateTime" تعریف شده است که از RTC (Real-Time Clock) مقادیر زمان و تاریخ فعلی را دریافت کرده و در ساختار DateTime ذخیره می‌کند.

در نهایت، خروجی شبیه زیر در خروجی نمایش داده می‌شود:
Current date and time: 12/05/2023 15:30:45


در این مثال، ساختار struct برای نگهداری اطلاعات زمان و تاریخ در برنامه‌نویسی میکروکنترلر LPC1768 استفاده شده است. این نمونه نشان می‌دهد که با استفاده از ساختارها، می‌توانید اطلاعات را سازماندهی کرده و به آسانی آنها را دریافت و استفاده کنید.


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 10 :

#enum
در زبان برنامه‌نویسی enum یک نوع داده‌ای است که برای تعریف یک مجموعه مقادیر ثابت استفاده می‌شود. کلمه enum به معنای enumeration (شمارش) است و از آن برای تعریف مجموعه‌ای از مقادیر ثابت استفاده می‌شود که قابل شمارش هستند.

با استفاده از enum، می‌توانید یک مجموعه از عناصر ثابت(که به عنوان عضوهای enum شناخته می‌شوند) را تعریف کنید.


ثابت های از نوع enum نیز قابل تعریف هستند. این ثابت ها را می‌توان به دو روش تعریف کرد :

enum week{Mon, Tue, Wed};
enum week day;
یا
enum week{Mon, Tue, Wed}day;
مقدار default value در enum :
مقدار default value ثابت های enum از اولین ثابت با شماره صفر مقدار دهی شده و همین ترتیب متغیر بعدی 1 وبعدی 2 و.... مقدار دهی میشود .
مثال های زیر را مشاهده کنید

این برنامه یک مثال ساده است که نحوه کار با enum در زبان C را نشان می‌دهد. کد زیر را بررسی کنید:

#include<stdio.h>

enum week {Mon, Tue, Wed, Thur, Fri, Sat, Sun};

int main()
{
enum week day;
day = Wed;
printf("%d", day);
return 0;
}


خروجی (Output) این برنامه عدد 2 است. این به این دلیل است که در enum week، مقدار Wed به عنوان سومین ثابت تعریف شده است و بازنمایی عددی آن برابر با 2 است. بنابراین، در خط printf، عدد 2 چاپ می‌شود.

مثال بعدی :

enum SystemState {
IDLE,
BUSY,
ERROR
};

// تعریف تابعی که ورودی آن حالت سیستم است
void updateSystem(enum SystemState state) {
// عملیات‌های مربوط به هر حالت سیستم
switch(state) {
case IDLE:
// انجام عملیات‌های مربوط به حالت آرام
break;
case BUSY:
// انجام عملیات‌های مربوط به حالت مشغولیت
break;
case ERROR:
// انجام عملیات‌های مربوط به حالت خطا
break;
default:
// وضعیت مورد نظر نامشخص است
break;
}
}

int main() {
// استفاده از تابع updateSystem برای تنظیم سیستم در حالت BUSY
updateSystem(BUSY);
return 0;
}

در این مثال، یک enum به نام SystemState تعریف شده است که شامل ثابت‌های IDLE، BUSY و ERROR است. این enum برای نشان دادن حالت‌های مختلف سیستم استفاده می‌شود.

تابع updateSystem نیز تعریف شده است که ورودی آن یک متغیر از نوع SystemState است. در این تابع، با استفاده از switch، عملیات‌های مربوط به هر حالت سیستم انجام می‌شود. برای هر حالت، یک بلوک کد مشخص وجود دارد که عملیات مربوط به آن حالت را انجام می‌دهد.

در تابع main نیز از تابع updateSystem برای تنظیم سیستم در حالت BUSY استفاده شده است. در نهایت، مقدار 0 به عنوان خروجی برگشتی main بازگشت داده می‌شود.

به این ترتیب، این برنامه با استفاده از enum و تابع updateSystem، قادر است تا عملیات مربوط به هر حالت سیستم را انجام دهد و در این مثال، سیستم در حالت BUSY تنظیم شده است.

حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 9 :

#sprintf
استفاده از روش زیر برای گذاشتن صفر در پشت عدد غلط است :
if (num<10 &&num>=0)
{
sprintf(str, "%000.2f", num);
}
else if (num<100 &&num>=10)
{
sprintf(str, "%00.2f", num);
}
else if (num<1000 &&num>=100)
{
sprintf(str, "%0.2f", num);
}

اگر بخواهیم با استفاده از تابع sprintf در پشت عدد صفر بگذاریم مثلا (002 ) را نمایش دهیم از روش زیر استفاده میکنیم :
if (num < 10 && num >= 0) {
sprintf(str, "00%0.2f", num);
}
else if (num < 100 && num >= 10) {
sprintf(str, "0%0.2f", num);
}
else if (num < 1000 && num >= 100) {
sprintf(str, "%0.2f", num);
}


در این کد، ابتدا محدوده‌هایی که ورودی در آن قرار دارد بررسی می‌شوند. اگر عدد کوچکتر از 10 باشد، یعنی تنها یک رقم دارد، دو صفر به پشت آن اضافه می‌شود و به عنوان خروجی یک رشته با سه رقم اعشاری تولید می‌شود. اگر عدد بین 10 تا 100 باشد، یعنی دو رقم دارد، یک صفر به پشت آن اضافه می‌شود و به عنوان خروجی یک رشته با دو رقم اعشاری تولید می‌شود. و اگر عدد بین 100 تا 1000 باشد، یعنی سه رقم دارد، هیچ صفری به پشت آن اضافه نمی‌شود و به عنوان خروجی یک رشته با یک رقم اعشاری تولید می‌شود.

حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 8 :

#double_pointer
در زبان برنامه‌نویسی C، pointer to pointer برای زمانی استفاده می‌شود که می‌خواهیم آدرس یک pointer دیگر را ذخیره کنیم. pointer اول برای ذخیره آدرس متغیر استفاده می‌شود و pointer دوم برای ذخیره آدرس pointer اول استفاده می‌شود. به همین دلیل آن‌ها را double-pointer می‌نامند. می‌توان از یک pointer to pointer برای تغییر مقادیر پوینترهای معمولی یا ایجاد آرایه 2 بعدی به اندازه متغیر استفاده کرد. یک double-pointer در حافظه نیز همان فضایی که یک pointer معمولی به خود اختصاص می‌دهد را اشغال می‌کند.
• تعریف pointer to pointer در زبان برنامه‌نویسی C
تعریف pointer to pointer در زبان برنامه‌نویسی C شبیه تعریف یک pointer است، با این تفاوت که باید یک '*' اضافی قبل از نام پوینتر قرار داده شود.
data_type_of_pointer **name_of_variable = & normal_pointer_variable;
int val = 5;
int *ptr = &val; // storing address of val to pointer ptr.
int **d_ptr = &ptr; // pointer to a pointer declared
// which is pointing to an integer

این کد یک نمونه از تعریف یک پوینتر به پوینتر در زبان برنامه‌نویسی C است. در این مثال، ما یک متغیر از نوع int به نام "val" داریم که یک مقدار عددی به آن اختصاص داده شده است. سپس با استفاده از یک پوینتر معمولی به نام "ptr"، آدرس متغیر "val" را ذخیره می‌کنیم. در ادامه، با استفاده از یک پوینتر به پوینتر به نام "d_ptr"، آدرس پوینتر "ptr" را نیز ذخیره می‌کنیم. در واقع، "d_ptr" به یک پوینتر معمولی اشاره می‌کند که خود به پوینتر "val" اشاره دارد.

در کلیت، تعریف پوینتر به پوینتر به ما این امکان را می‌دهد که به پوینترها به عنوان یک متغیر دسترسی داشته باشیم و آدرس آنها را در یک پوینتر دیگر ذخیره کنیم. این کار برای مواردی مانند ایجاد آرایه‌های چند بعدی با اندازه متغیر قابل تغییر مفید است.
این کد یک نمونه از استفاده از پوینتر به پوینتر (double pointer) در زبان برنامه‌نویسی C است:
// C program to demonstrate pointer to pointer
#include <stdio.h>

int main()
{
int var = 789;

// pointer for var
int* ptr2;

// double pointer for ptr2
int** ptr1;

// storing address of var in ptr2
ptr2 = &var;

// Storing address of ptr2 in ptr1
ptr1 = &ptr2;

// Displaying value of var using
// both single and double pointers
printf("Value of var = %d\n", var);
printf("Value of var using single pointer = %d\n", *ptr2);
printf("Value of var using double pointer = %d\n", **ptr1);

return 0;
{
این برنامه، مثالی از استفاده از Double Pointer در زبان C است. در ابتدا یک متغیر به نام var از نوع integer با مقدار 789 تعریف شده است. سپس یک pointer به نام ptr2 برای متغیر var تعریف شده و آدرس آن در این pointer ذخیره شده است. در ادامه یک double pointer به نام ptr1 تعریف شده و آدرس pointer ptr2 در آن ذخیره شده است.

در خطوط بعدی، مقدار متغیر var با استفاده از هر دو single pointer و double pointer چاپ شده است. ابتدا مقدار متغیر var، سپس با استفاده از pointer ptr2 و در نهایت با استفاده از double pointer ptr1 و ptr2 چاپ شده است.

در نتیجه، این برنامه خروجی زیر را تولید می‌کند:

Value of var = 789
Value of var using single pointer = 789
Value of var using double pointer = 789

ادامه در پست بعدی : 👇👇👇



حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره7 :

#Heap
چدر میکروکنترلرها، Heap یک بخش از حافظه است که برای ذخیره داده ها در حین اجرای برنامه استفاده می شود. Heap شامل یک فضای ذخیره‌سازی دینامیکی است که برای ایجاد و حذف داده ها به کار می رود و برای ذخیره‌سازی داده هایی که اندازه آن ها در زمان کامپایل مشخص نمی شود، استفاده می شود. این حافظه برای استفاده از داده هایی که در زمان اجرای برنامه ایجاد می شوند، به کار می رود.

به عبارت دیگر، Heap یک منبع حافظه است که به صورت پویا توسط برنامه در زمان اجرا مدیریت می شود. برای تخصیص حافظه در Heap، باید از توابعی مانند malloc و calloc در زبان برنامه‌نویسی C استفاده کرد. این توابع به کاربر اجازه می دهند تا در زمان اجرا به صورت پویا حافظه اختصاص دهند.

در صورت استفاده نادرست از Heap ممکن است با مشکلاتی مانند Fragmentation و Memory Leaks مواجه شوید که می توانند باعث کاهش عملکرد برنامه شوند و حتی باعث خرابی سیستم شوند. بنابراین، استفاده صحیح از Heap و دقت در مدیریت حافظه می تواند بهبود قابل توجهی در عملکرد برنامه و کاهش احتمال خطاهای رخ داده در سیستم داشته باشد.

مثال ۱:
فرض کنید که در برنامه‌ی شما، باید یک آرایه‌ی دو بعدی با ابعاد مشخصی ایجاد کنید. در این صورت، شما می‌توانید از Heap برای ایجاد آن استفاده کنید. در ابتدا با توابع مانند malloc یا calloc، فضای حافظه‌ای را به اندازه‌ی مورد نیاز تخصیص می‌دهید، سپس آرایه‌ی دو بعدی را در آنجا ایجاد می‌کنید.


int rows = 5;
int cols = 10;
int **arr = (int **) malloc(rows * sizeof(int *));
for(int i = 0; i < rows; i++) {
arr[i] = (int*) calloc(cols, sizeof(int));
}





(توضیح int** باشه طلبتون )

در این مثال، یک آرایه‌ی دو بعدی به ابعاد ۵ در ۱۰ ایجاد شده است. ابتدا یک آرایه‌ی از اشاره‌گرها با اندازه rows ایجاد شده است، سپس به ازای هر ردیف، یک آرایه‌ی جدید با اندازه cols و به ازای هر ستون، با اندازه یک integer ایجاد می‌شود. هر اشاره‌گر به آرایه‌ی سطری در arr اشاره می‌کند.

مثال ۲:
یکی دیگر از مثال‌های استفاده از Heap، ایجاد یک رشته (string) با طول نامعلوم است. به جای تعریف یک آرایه‌ی ثابت برای رشته، می‌توانید از Heap استفاده کنید تا حافظه‌ای به اندازه‌ی لازم تخصیص دهید. برای این کار می‌توانید از تابع malloc استفاده کنید.

char* str = (char*) malloc(100 * sizeof(char));
strcpy(str, "This is a string that could be any length");
printf("%s", str);
free(str);

در این مثال، یک رشته به طول ۱۰۰ با استفاده از malloc ایجاد شده است. سپس با تابع strcpy، متن مورد نظر به رشته انتقال داده شده و در نهایت با تابع printf، رشته چاپ می‌شود. در پایان نیز با استفاده از تابع free، حافظه‌ی تخصیص داده شده به رشته با استفاده از malloc آزاد می‌شود تا از ایجاد حافظه‌ی غیر ضروری جلوگیری شود.

توجه کنید که استفاده از heap باید با دقت و با توجه به نیاز برنامه‌ی شما باشد. همچنین، پس از اتمام کار با حافظه‌ی تخصیص داده شده در Heap، باید آن را با تابع free آزاد کنید تا از حافظه‌ی غیر ضروری جلوگیری شود.

حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 6 :

#Stack
The Concept of Stack and Its Usage in Microprocessors

Overview :
بطور کلی می‌توانیم استک را به عنوان یک حافظه موقت برای داده‌ها توصیف کنیم. دسترسی به داده‌ها در استک بطور Last In First Out (LIFO) یا به عبارتی آخرین داده‌ای که در استک ذخیره شده است اولین داده است که می‌تواند بازیابی شود و اولین داده‌ای که در استک ذخیره شده است آخرین داده است که می‌تواند بازیابی شود. عمل افزودن داده به استک PUSH نامیده می‌شود و عمل بازیابی داده به POP یا PULL معروف است.
Stack Usage in Programming Languages
اکثریت قریب به اتفاق زبان های برنامه نویسی که توابع را پیاده سازی می کنند از یک Stack(پشته) استفاده می کنند. به هر تابع بخش مخصوص به خود از حافظه داده می شود تا در آن کار کند. این بخش بخشی از Stack است و به عنوان Stack frame نامیده می شود. معمولاً شامل اجزای زیر است
آدرس برگشتی (وقتی تابع کامل شد به فراخوانی تابع برمی گردد)
آرگومان ها به تابع منتقل می شوند
متغیرهای محلی تابع
کپی های ذخیره شده از هر register که توسط تابع تغییر یافته و باید بازیابی شود.

وقتی یک برنامه وارد یک تابع می‌شود، فضایی در بالای stack تخصیص داده می‌شود. وقتی برنامه از تابع خارج می‌شود، فضا آزاد می‌شود. عمر متغیرها در stack ، محدود به مدت زمان اجرای تابع است. داده‌هایی که باید بین فراخوانی‌های تابع ذخیره شوند، در heap ذخیره می‌شوند.
Usage in Microprocessors

استفاده از Stack برای سیستم های embedded بسیار حیاتی است و تنظیم آن به درستی برای پایداری و اعتماد سیستم بسیار حائز اهمیت است. دست کم گرفتن استفاده از Stack، مشکلات جدی مانند متغیرهای Overwrite شده ،اشاره گرهای Uninitialized و corrupted return addresses ایجاد می کند.

متغیرهای Overwrite :
به متغیرهایی اطلاق می‌شود که مقدار آن‌ها به طور ناخواسته توسط برنامه دیگری تغییر داده شده است.. این اتفاق می‌تواند باعث خرابی برنامه و در نتیجه بروز مشکلات جدی مانند عدم پاسخگویی و حتی از دست دادن داده‌های مهم شود.

اشاره‌گرهای Uninitialized :
اشاره‌گرهایی هستند که به یک مکان مشخص در حافظه اشاره می‌کنند، اما به آن مقداری داده نشده است. به عبارت دیگر، مقدار داخل حافظه که به آن اشاره می‌شود تعیین نشده است. استفاده از اشاره‌گرهای Uninitialized می‌تواند باعث بروز مشکلات جدی در برنامه شود مانند کرش کردن برنامه، تغییر غیرمنتظره مقادیر در حافظه و یا بروز خطاهای دیگر در زمان اجرای برنامه. بنابراین این مهم است که در هنگام تعریف و استفاده از اشاره‌گرها، ابتدا مقدار آن‌ها تعیین شود.

corrupted return addresses:

در برنامه نویسی، زمانی که یک تابع فراخوانی می شود، برنامه به داخل تابع می رود و پس از اجرای تابع، برنامه باید به ادامه خطی که قبل از فراخوانی تابع وجود داشت، بازگردد. این خط با استفاده از یک متغیر به نام return address ذخیره می شود. اگر در حین اجرای تابع، این متغیر به هر دلیلی دچار خرابی شود، برنامه بعد از پایان تابع به جای بازگشت به ادامه خط، به جای آن به یک محل تصادفی در حافظه می رود که ممکن است عواقب خطرناکی داشته باشد. به این مشکل "corrupted return address" یا "آدرس بازگشتی خراب شده" گفته می شود.

حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 5 :
#Pointer
در زبان برنامه‌نویسی C، اشاره گر(Pointer) یک متغیر است که آدرس حافظه را نشان می‌دهد. به عبارت دیگر، اشاره گربه مکان دقیق در حافظه اشاره می‌کند.. با استفاده از پوینترها، می‌توان داده‌ها را از حافظه بخوانید، به حافظه بنویسید و یا به عنوان آرگومان در تابع‌ها استفاده کنید.
برای ایجاد یک اشاره گردر زبان C، از علامت * استفاده می‌شود. به عنوان مثال:
uint8_t* my_pointer;
این کد یک اشاره گربه یک متغیر از نوع uint8_t تعریف می‌کند. برای دسترسی به محتوای آدرس مربوط به اشاره گر، از عملگر * استفاده می‌شود. به عنوان مثال
#include <avr/io.h>

int main(void)
{
DDRB = 0xFF; // تنظیم پین‌های پورت B به عنوان خروجی

uint8_t* portc_ptr = &PINC; // ایجاد اشاره گربه پورت C

while (1)
{
if (*portc_ptr & 0x01) // اگر پین 0 پورت C ورودی شده باشد
{
PORTB = 0xFF; // روشن کردن همه پین‌های پورت B
}
else
{
PORTB = 0x00; // خاموش کردن همه پین‌های پورت B
}
}
return 0;
}

این برنامه از اشاره گرportc_ptr برای دسترسی به وضعیت پین‌های ورودی پورت C استفاده می‌کند. هر بار که وضعیت پین 0 پورت C تغییر کند، وضعیت همه پین‌های پورت B تغییر می‌کند.
تفاوت اصلی بین یک متغیر pointer و یک متغیر معمولی در C، در نحوه‌ی ذخیره‌سازی و نحوه‌ی دسترسی به مقدار آن‌ها است. در حالی که یک متغیر معمولی دارای مقدار خود است و می‌توان به آن به صورت مستقیم اشاره کرد، یک متغیر pointer فقط آدرس متغیر دیگری را نگه‌داری می‌کند و برای دسترسی به مقدار آن متغیر، باید از عملگر (*) استفاده کرد.

برای مثال، فرض کنید یک متغیر عددی به نام x و یک متغیر pointer به نام p در برنامه AVR خود داریم. اگر مقدار x برابر با 10 باشد، برای نمایش مقدار x در مانیتور سریال، می‌توان به دو روش زیر عمل کرد:

1- استفاده از متغیر x:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <util/delay.h>

int main(void)
{
int x = 10;
char buffer[10];

uart_init();
while (1)
{
sprintf(buffer, "%d", x);
uart_puts(buffer);
_delay_ms(1000);
}

return 0;
}

در این روش، مقدار متغیر x را به رشته تبدیل کرده و با استفاده از تابع uart_puts، رشته را در مانیتور سریال نمایش می‌دهیم.

2- استفاده از متغیر pointer:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <util/delay.h>

int main(void)
{
int x = 10;
int *p = &x;
char buffer[10];

uart_init();
while (1)
{
sprintf(buffer, "%d", *p);
uart_puts(buffer);
_delay_ms(1000);
}

return 0;
{
در این روش، یک متغیر pointer به نام p به آدرس متغیر x اشاره می‌کند. سپس با استفاده از تابع sprintf، مقدار متغیر x را به رشته تبدیل کرده و با استفاده از تابع uart_puts، رشته را در مانیتور سریال نمایش می‌دهیم

سایز یک اشاره‌گر در میکروکنترلرهای مختلف می‌تواند متفاوت باشد و این بسته به ساختار میکروکنترلر و نوع آن بستگی دارد. برای مثال، در برخی از میکروکنترلرها مانند AVR، سایز یک اشاره‌گر 2 بایت است که به این معناست که اشاره‌گر برای نگهداری آدرس حافظه، دو بایت از حافظه را اشغال می‌کند. در مقابل، در برخی دیگر از میکروکنترلرها مانند ARM، سایز یک اشاره‌گر 4 بایت است.

در زبان C برای بدست آوردن سایز یک اشاره‌گر می‌توان از اندازه‌گیری سایز یک متغیر pointer به کمک دستور sizeof استفاده کرد. برای مثال، برای بدست آوردن سایز یک اشاره‌گر ، می‌توان به صورت زیر عمل کرد:
#include <stdio.h>

int main() {
int *ptr;
printf("The size of a pointer is: %u\n", sizeof(ptr));
return 0;
}


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک
🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 4 :
#volatile

کلمه کلیدی volatile در زبان برنامه نویسی C برای اعلام این استفاده می‌شود که یک متغیر توسط برنامه‌ی کاربری و یا توسط سخت‌افزار تغییر مقدار داده می‌شود. با داشتن این علامت، کامپایلر باید هر بار مقدار این متغیر را از مکان‌های مختلف حافظه بخواند و به روز رسانی کند. بدون این علامت، کامپایلر ممکن است بهینه‌سازی‌هایی انجام دهد که باعث نادرستی در کد برنامه شود.

برای درک بهتر مفهوم volatile، برای مثال فرض کنید که یک متغیر با نام counter تعریف کرده‌ایم و مقدار آن را در هر سیکل زمانی به یک واحد افزایش می‌دهیم. اگر ما این متغیر را به عنوان volatile تعریف نکنیم، کامپایلر ممکن است این متغیر را در حافظه‌ی موقت یا کش ذخیره کند و تا زمانی که این متغیر توسط سخت‌افزار یا کاربر تغییر نکند، از محتوای حافظه‌ی موقت استفاده کند. اما اگر ما این متغیر را به عنوان volatile تعریف کنیم، کامپایلر هر بار باید مقدار آن را از مکان حافظه‌ی اصلی بخواند و به روز رسانی کند. این بسیار مهم است در مواقعی که از متغیر‌های اشتراکی در برنامه استفاده می‌کنیم.

یکی از کاربردهای volatile در برنامه‌نویسی میکروکنترلرها است. برای مثال در میکروکنترلر AVR، ممکن است بخواهیم مقداری را در پورت ورودی‌ها خوانده و آن را به یک متغیر تخصیص دهیم. با تعریف این متغیر به عنوان volatile، کامپایلر مجبور است هر بار که مقدار پورت ورودی‌ها تغییر کرده است، مقدار آن را از مکان حافظه‌ی اصلی خوانده و به روز رسانی کند. بدون تعریف volatile، کامپایلر ممکن است بهینه‌سازی‌هایی انجام دهد که باعث نادرستی در کد برنامه شود.
برای مثال، فرض کنید که می‌خواهیم وضعیت یک پین ورودی را در میکروکنترلر AVR خوانده و در یک متغیر ذخیره کنیم. کد زیر را در نظر بگیرید:
volatile uint8_t *PINB = (volatile uint8_t *) 0x23;
uint8_t input;

int main() {
while (1) {
input = *PINB;
// do something with input
}
return 0;
}

در این کد، PINB به عنوان یک متغیر volatile تعریف شده است. در هر بار اجرای حلقه‌ی while، مقدار پورت ورودی‌ها را از آدرس 0x23 خوانده و در متغیر input ذخیره می‌کنیم. با تعریف PINB به عنوان volatile، کامپایلر مجبور است هر بار مقدار پورت ورودی‌ها را از حافظه‌ی اصلی خوانده و به روز رسانی کند. اگر این متغیر به عنوان volatile تعریف نشود، کامپایلر ممکن است مقدار پورت ورودی‌ها را در حافظه‌ی موقت ذخیره کرده و از آن استفاده کند، در حالی که واقعیتاً مقدار پورت ورودی‌ها تغییر کرده است.
مثال دوم :
در واحد ADC، مقدار ولتاژ ورودی به دستگاه تبدیل آنالوگ به دیجیتال اندازه‌گیری می‌شود و در یک متغیر ذخیره می‌شود. این متغیر باید به عنوان volatile تعریف شود تا هر بار که مقدار ولتاژ ورودی تغییر کند، به روز رسانی شود.
برای مثال، فرض کنید که می‌خواهیم مقدار ولتاژ ورودی به پین ADC0 را در یک متغیر ذخیره کنیم. کد زیر این کار را انجام می‌دهد:
#include <avr/io.h>

volatile uint16_t adc_value; // تعریف متغیر ADC به صورت volatile

void init_adc()
{
ADMUX |= (1 << REFS0); // تنظیم ولتاژ مرجع برای ADC
ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // فعالسازی ADC و تنظیم prescaler
}

void read_adc()
{
ADCSRA |= (1 << ADSC); // شروع تبدیل ADC
while (ADCSRA & (1 << ADSC)); // منتظر بودن برای پایان تبدیل ADC
adc_value = ADC; // ذخیره‌ی مقدار ADC در متغیر تعریف شده به عنوان volatile
}

int main()
{
init_adc(); // تنظیمات ADC
while ()
{
read_adc(); // خواندن مقدار ADC
// انجام کاری با مقدار ADC
}
return 0;
}
در کل، استفاده از volatile بسیار مهم است در مواقعی که با متغیر‌هایی سروکار داریم که توسط سخت‌افزار و یا دیگر قسمت‌های برنامه تغییر مقدار داده می‌شوند.


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 4 :
#volatile


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 3:
#inline_function
برای افزایش عملکرد برنامه، می توان از inline function استفاده کرد.
توابع inline برای بهینه‌سازی کد مورد استفاده قرار می‌گیرند. با استفاده از این توابع، کامپایلر می‌تواند بدنه‌ی تابع را در نقطه‌ی فراخوانی تابع در برنامه قرار داده و از این طریق از هزینه‌ی زمانی و حافظه‌ی مصرفی برای صدا کردن تابع در زمان اجرا کاست.

وقتی یک تابع به عنوان inline تعریف می‌شود، کامپایلر به جای ایجاد یک تابع جداگانه و فراخوانی آن در محل استفاده، بدنه تابع را به صورت مستقیم در محل فراخوانی قرار می‌دهد. به عبارت دیگر، هنگامی که تابعی را به صورت inline فراخوانی می‌کنیم، به جای اینکه کامپایلر به یک نقطه جداگانه در برنامه بروند و برای فراخوانی تابع به آنجا برگردند، بدنه تابع را مستقیماً در نقطه فراخوانی تعبیه می‌کنند.

بنابراین، با استفاده از inline، بجای ایجاد یک تابع و فراخوانی آن در برنامه، کد بدنه تابع به صورت مستقیم در محل فراخوانی قرار می‌گیرد. این باعث می‌شود که زمانی که برنامه اجرا می‌شود، زمان ایجاد تابع جداگانه برای فراخوانی، برای inline کاهش پیدا کند.
در زبان برنامه‌نویسی C، برای تعریف یک تابع به صورت inline، کلمه‌ی کلیدی inline در ابتدای تعریف تابع قرار می‌گیرد. برای مثال، تابع add را به صورت inline در زبان C می‌توان به شکل زیر تعریف کرد:
inline int add(int a, int b)
}
return a + b;
}

استفاده از inline در برنامه‌های C، به دلیل جایگزینی تابع با بدنه آن در محل فراخوانی، می‌تواند باعث افزایش سرعت اجرای برنامه شود، اگر از این قابلیت به درستی استفاده شود. این به این معنی است که در برنامه‌ای که از inline استفاده می‌کند، زمان اجرای برنامه ممکن است کوتاه‌تر باشد و سرعت آن بیشتر باشد.

اما این تفاوت در عمل ممکن است به دلیل محدودیت‌هایی در inline، غیر قابل توجه باشد. به عنوان مثال، تابع‌های بلند و پیچیده، به دلیل حجم زیاد کد، به‌صورت inline قابل قبول نیستند. همچنین، inline در برنامه‌هایی که از زمان اجرای برنامه مهمتر است، مانند سیستم‌های عامل، ممکن است به دلیل تلاش برای بهبود عملکرد، محدودیت داشته باشد.

بنابراین، بسته به شرایط و نیازهای برنامه، استفاده از inline می‌تواند تفاوتی در سرعت اجرای برنامه ایجاد کند. با این حال، توجه به نکاتی مانند طول و پیچیدگی تابع، تعداد فراخوانی‌های آن، و اولویت بهینه‌سازی برنامه، می‌تواند مؤثر باشد و می‌تواند به دقت انتخاب inline کمک کند.

برای مثال، می‌توانیم یک تابع inline برای تنظیم تایمر در میکروکنترلر AVR ایجاد کنیم. فرض کنید می‌خواهیم یک تایمر 8 بیتی در میکروکنترلر AVR تنظیم کنیم و زمان تنظیم آن بسیار حساس است. در این حالت، می‌توانیم از تابع inline برای بهینه‌سازی زمان اجرای تابع استفاده کنیم.

#include <avr/io.h>

static inline void set_timer_8bit(volatile uint8_t* reg, uint8_t val) {
*reg = val;
}

int main() {
// تنظیم تایمر 8 بیتی با فرکانس کلاک 8 مگاهرتز
TCCR0B |= (1 << CS01) | (1 << CS00);

// تنظیم مقدار تایمر به 100 میلی ثانیه
set_timer_8bit(&TCNT0, 78);

while (1) {
// کد برنامه
}

return 0;


}

در این مثال، ابتدا تایمر 8 بیتی را با فرکانس کلاک 8 مگاهرتز تنظیم کرده و سپس با فراخوانی تابع set_timer_8bit، مقدار تایمر را به معادل 100 میلی ثانیه تنظیم می‌کنیم. با استفاده از inline در تعریف تابع set_timer_8bit، می‌توانیم زمان اجرای برنامه را بهبود بخشیم و کد بهینه‌تری برای میکروکنترلر AVR بنویسیم.


حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 2:
#malloc & #free
در هنگام برنامه نویسی میکروکنترلر ها یکی از نکاتی که باید بسیار به آن توجه کرد مدیریت حافظه میباشد زیرا حافظه ی بسیاری از میکروکنترلر ها به شدت محدود بوده و در هنگام کدنویسی اگر از روش های بهینه استفاده نکنیم ، ممکن است که حافظه ی میکروکنترلر پاسخگوی نیاز ما برای کامپایل تمام پروژه نباشد و خیلی از افراد در این مواقع تصمیم میگیرند که پردازنده ی خود را عوض کرده و یک پردازنده ی گران تر را جایگزین کنند و حتی سخت افزاری که برای پروزه خود طراحی کرده اند را کنار گذاشته و یک سخت افزار جدید برای پروژه خود و متناسب با پردازنده جدید طراحی کنند. این در صورتی است که با رعایت برخی نکات ممکن است که نیازی به انجام دادن چنین کاری نباشد و محصول خود را با هزینه کمتر تولید کرد
یکی از نکات مهم در مدیریت حافظه استفاده از توابع malloc , free میباشد :
تابع malloc :
تابع malloc برای تخصیص حافظه به اندازه‌ی خاصی به کار می‌رود. برای استفاده از تابع malloc، باید از کتابخانه‌ی stdlib.h استفاده شود. پارامتر ورودی این تابع، اندازه‌ی حافظه درخواستی است که قصد تخصیص آن را داریم. تابع malloc یک اشاره‌گر به حافظه‌ی تخصیص داده شده را برمی‌گرداند. در صورتی که حافظه‌ی درخواستی تخصیص داده نشود، تابع malloc مقدار NULL را برمی‌گرداند.

در زیر مثالی برای استفاده از تابع malloc آورده شده است:
#include <stdio.h>
#include <stdlib.h>

int main() {
int size = 10;
int* ptr = (int*) malloc(size * sizeof(int));
if (ptr == NULL) {
printf("Failed to allocate memory!");
return 1;
}
for (int i = 0; i < size; i++) {
ptr[i] = i * 2;
}
for (int i = 0; i < size; i++) {
printf("%d ", ptr[i]);
}
free(ptr);
return 0;
}
در این مثال، یک اشاره‌گر به یک بلاک حافظه به اندازه ۱۰ عدد از نوع int تخصیص داده شده است. در ادامه، این بلاک حافظه با استفاده از حلقه تکمیل شده و سپس با استفاده از تابع free، آزاد شده است.

تابع free:
تابع free برای آزادسازی حافظه‌ی اختصاص یافته به یک اشاره‌گر استفاده می‌شود. تابع free به تنهایی می‌تواند به یک بلاک حافظه دسترسی داشته باشد که با استفاده از تابع malloc یا realloc تخصیص داده شده است. برای استفاده از تابع free، باید از کتابخانه‌ی stdlib.h استفاده شود.

در مثالی که بالا بیان شد ، پس از استفاده از بلاک حافظه‌ی تخصیص داده شده، با استفاده از تابع free، حافظه‌ی مربوط به آن بلاک آزاد شده است.

حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#C
نکات برنامه نویسی در C برای میکرو کنترلر ها :
نکته ی شماره 1 :
#strcpy
کد زیر اشتباه است :
char WriteData[1024];
WriteData = "Hello world";
در زبان C شما مستقیم نمیتوانید یک رشته را وارد یک Byte Array کنید و برای این کار باید از دستور زیر کمک بگیرید :
#include <string.h>

char WriteData[1024];
strcpy(WriteData, "Hello world");

این کد، کاراکترهای "Hello world" را در آرایهٔ WrtieData کپی خواهد کرد. لطفاً توجه داشته باشید که باید اطمینان حاصل کنید که آرایهٔ شما دارای فضای کافی برای نگهداری رشتهٔ مدنظر داراست در غیر این صورت ممکن است با خطاهای buffer overflow مواجه شوید.

حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥
#مهندس_الکترونیک
#الکترونیک

🆔 @elec_source
#clip
#opencv
#c++

🌹آموزش پروژه محور پردازش تصویر با کتابخانه opencv در نرم افزار visual studio 2017
زبان cpp
نام پروژه : تشخیص چهره
مدرس :میلاد شیخلر
🌹این آموزش رو مدت ها پیش من تو سایت فریادرس منتشر کرده بودم  و لینک دانلودشم براتون میذارم امیدوارم براتون مفید باشه 
🌹 شما در این آموزش از ابتدای نصب کتاب خانه تا مرحله آخر کدنویسی و اجرای یک پروژه رو  مشاهده خواهید کرد
لینک دسترسی به آموزش




حمایت از کانال : 🔥🔥🔥🔥🔥🔥حامی باش🔥🔥🔥🔥🔥🔥

#مهندس_الکترونیک    
#الکترونیک

🆔 @elec_source
Ещё