آموزش راه اندازی پورت سریال نرم افزاری در AVR (توسط کامپایلر اتمل استادیو):
در این مقاله راه اندازی پورت سریال نرم افزاری در میکروکنترلر AVR توسط کامپایلر اتمل استادیو (ATMEL Studio) را آموزش می دهیم. راه اندازی پورت سریال نرم افزاری در آردیونو بشدت ساده و آماده می باشد. در این مقاله ما یک درایور کامل با زبان سی را آموزش می دهیم. در دنیای طراحی سیستمهای امبدد، میکروکنترلرهای AVR به دلیل کارایی و قابلیتهای متنوع، محبوبیت زیادی پیدا کردهاند.
این میکروکنترلرها با پشتیبانی از امکاناتی چون تایمرها، پورتهای ورودی و خروجی دیجیتال، و واحدهای ارتباط سریال سختافزاری، ابزار قدرتمندی برای طراحان مدارهای الکترونیکی فراهم میکنند. یکی از مهمترین نیازها در سیستمهای امبدد، قابلیت ارتباط سریال است که به میکروکنترلرها اجازه میدهد با دستگاههای دیگر مانند سنسورها، ماژولهای ارتباطی و سایر میکروکنترلرها تبادل داده داشته باشند.
این ارتباط بهویژه در پروژههای صنعتی و تجاری که نیاز به انتقال دقیق و پایدار دادهها دارند، اهمیت زیادی دارد.
یکی از راههای پیادهسازی ارتباط سریال در میکروکنترلرها، استفاده از پورتهای سریال سختافزاری است که در بیشتر سریهای AVR تعبیه شدهاند.
با این حال، در پروژههایی که تعداد پورتهای سریال سختافزاری محدود است یا نیاز به پورتهای بیشتری داریم، میتوان از پورت سریال نرمافزاری (Software UART) استفاده کرد.
این روش بهکمک تایمرهای میکروکنترلر و با استفاده از برنامهنویسی، قابلیت ارتباط سریال را فراهم میآورد و امکان ایجاد پورت سریال مجازی را بدون نیاز به سختافزار اضافی مهیا میکند.
Software UART بهویژه زمانی که به چند پورت سریال در یک میکروکنترلر با پورتهای سختافزاری محدود نیاز داریم، یک راهکار انعطافپذیر و مؤثر است.
در این آموزش، به پیادهسازی یک پورت سریال نرمافزاری با استفاده از تایمر 16 بیتی ATmega16 خواهیم پرداخت و با معرفی کتابخانهای که برای این کار طراحی شده است و به زبان C نوشته شده، مراحل راهاندازی و استفاده از این روش را به شما آموزش میدهیم.
مفاهیم پایه:
پروتکلهای ارتباط سریال UART:
ارتباط سریال (Serial Communication) یکی از رایجترین روشها برای تبادل دادهها بین دستگاههای الکترونیکی است. در این روش، دادهها به صورت رشتهای از بیتها از فرستنده به گیرنده منتقل میشوند.
یکی از پروتکلهای ارتباط سریال متداول، UART (Universal Asynchronous Receiver/Transmitter) است که امکان ارسال و دریافت دادهها را بدون نیاز به هماهنگی زمانی خاص (کلاک مشترک) فراهم میکند. در UART، هر دستگاه فرستنده و گیرنده به صورت جداگانه فرکانس خود را تنظیم میکنند و با استفاده از بیتریت یکسان میتوانند دادهها را همگامسازی کنند.
بیتریت (Baud Rate):
بیتریت، یا نرخ انتقال دادهها، تعداد بیتهایی را نشان میدهد که در یک ثانیه از طریق کانال ارتباطی منتقل میشود. این مقدار برحسب بیت در ثانیه (bps) اندازهگیری میشود. بیتریت برای ارتباطات سریال پارامتری حیاتی است، زیرا باید بین فرستنده و گیرنده یکسان باشد تا دادهها به درستی تفسیر شوند.
برای مثال، اگر بیتریت 9600 bps تنظیم شود، فرستنده در هر ثانیه 9600 بیت را ارسال میکند و گیرنده باید با همین نرخ دادهها را دریافت کند. هرگونه تفاوت در بیتریت میتواند منجر به ایجاد اختلال و اشتباه در تفسیر دادهها شود.
تفاوت بین UART سختافزاری و نرمافزاری:
در میکروکنترلرهایی که دارای UART سختافزاری هستند، این ارتباط به کمک مدارهای داخلی میکروکنترلر و بدون نیاز به بارگذاری محاسباتی بر روی CPU انجام میشود. این روش معمولاً دقیقتر و پایدارتر است و به دلیل استفاده از سختافزار خاص، فرایند ارتباط سریال با سرعت بیشتری انجام میشود.
اما در پروژههایی که به چند پورت سریال نیاز داریم و میکروکنترلر تنها دارای یک یا چند واحد UART سختافزاری است، میتوان از UART نرمافزاری یا Software UART استفاده کرد.
در Software UART، پورت سریال به کمک برنامهنویسی و استفاده از تایمرها شبیهسازی میشود.
اگرچه این روش ممکن است از لحاظ دقت و سرعت محدودیتهایی داشته باشد، اما امکان انعطافپذیری بیشتری در تعداد پورتهای سریال فراهم میآورد و به همین دلیل در کاربردهایی که نیاز به چندین پورت ارتباط سریال وجود دارد، بسیار مفید است.
آموزش راه اندازی پورت سریال نرم افزاری در AVR با تایمر 16 بیتی:
در این آموزش با استفاده از یک تایمر شانزده بیتی (که در میکروکنترلر ATmega16 تایمر یک می باشد)، یک پورت سریال مجازی یا پورت سریال نرم افزاری (Software UART) راه اندازی نمائیم.
این تایمر به ما امکان تولید زمانبندیهای دقیقی را میدهد که برای ارسال و دریافت بیتهای سریال ضروری است. این کتابخانه با بهرهگیری از تایمر1 و وقفههای مرتبط با آن، امکان شبیهسازی یک پورت سریال را بدون نیاز به سختافزار اضافی فراهم میآورد.
ویژگیهای تایمر 16 بیتی:
تایمر1 در میکروکنترلر ATmega16 به عنوان یک تایمر 16 بیتی، میتواند تا مقدار 65535 را شمارش کند که برای ایجاد زمانبندی دقیق در ارتباطات سریال ایدهآل است.
این تایمر قابلیت تنظیم در مدهای کاری مختلف (مانند CTC و PWM)، مقسم فرکانس (Prescaler) و پشتیبانی از ورودیهای خارجی را دارد که این ویژگیها، آن را برای پیادهسازی نرمافزار UART مناسب میسازد.
استفاده از سه وقفه برای راهاندازی Software UART:
این کتابخانه از سه وقفه مختلف تایمر1 برای پیادهسازی Software UART بهره میبرد:
-
وقفه Capture: این وقفه برای شناسایی لحظهای به کار میرود که یک سیگنال ورودی (پالس) به پایه ICP (Input Capture Pin) میرسد. با استفاده از این وقفه، میکروکنترلر میتواند زمان دقیق شروع هر بیت ورودی را شناسایی کرده و دریافت داده را همگامسازی کند.
- وقفه CompareA و CompareB: این دو وقفه برای کنترل زمانبندی دریافت و ارسال بیتها استفاده میشوند. با تنظیم مقادیر مناسب در رجیسترهای OCR1A و OCR1B، تایمر1 بهصورت دقیق در بازههای زمانی از پیش تعیینشده عمل میکند. وقفه CompareA به عنوان سیگنال تایمینگ اصلی برای ارسال بیتها به کار میرود، و وقفه CompareB زمانبندی دریافت داده را تنظیم میکند.
پیکربندی رجیسترهای تایمر1 برای Software UART:
برای پیکربندی تایمر1 جهت استفاده در Software UART، از چندین رجیستر کلیدی استفاده میکنیم:
-
TCCR1A و TCCR1B: این دو رجیستر برای تنظیم مد کاری تایمر، منبع کلاک و مقسم فرکانس به کار میروند. برای استفاده از مد CTC و تعیین فرکانس خروجی، از بیتهای WGM12 و CS10، CS12 در TCCR1B استفاده میشود.
-
OCR1A و OCR1B: این دو رجیستر مقادیر مقایسهای تایمر را ذخیره میکنند. با تنظیم مقادیر مناسب در این رجیسترها، میتوان تایمینگ دقیق برای ارسال و دریافت بیتهای سریال نرمافزاری را بهدست آورد.
-
TIMSK: این رجیستر وقفههای تایمر1 را فعال میکند. با فعالسازی وقفه Capture برای شناسایی لحظهای شروع بیتها و وقفههای CompareA و CompareB برای کنترل زمانبندی، میتوان عملیات ارسال و دریافت سریال را بهطور همزمان و دقیق اجرا کرد.
این پیکربندی در تابع softUart_Init() در فایل softUart.c انجام شده است که در ادامه توضیح داده خواهد شد.
شرح کتابخانه Software UART:
کتابخانه Software UART که در فایل softUart.h تعریف شده است، شامل توابع و تنظیمات لازم برای پیادهسازی یک پورت سریال مجازی (نرمافزاری) در میکروکنترلرهای AVR است. در ادامه، ساختار و توابع کلیدی تعریفشده در این فایل بهطور مفصل توضیح داده میشود.
1. تنظیمات ورودی/خروجی برای ارتباط سریال نرمافزاری:
در کتابخانه، تعریف پورتهای ورودی/خروجی برای استفاده در Software UART به صورت زیر آمده است:
1 2 3 4 5 6 7 8 9 |
#define SWU_DDR DDRD // تعریف رجیستر جهتدهی داده برای UART نرمافزاری #define SWU_PORT PORTD // تعریف رجیستر پورت خروجی برای UART نرمافزاری #define SWU_PIN PIND // تعریف رجیستر پورت ورودی برای UART نرمافزاری #define SWU_RX PD6 // تعریف پین RX برای دریافت دادهها #define SWU_TX PD5 // تعریف پین TX برای ارسال دادهها |
-
SWU_DDR، SWU_PORT و SWU_PIN به ترتیب جهت تنظیم رجیسترهای جهتدهی داده، پورت و خواندن وضعیت پورت استفاده میشوند.
-
SWU_RX و SWU_TX به ترتیب پینهای مورد استفاده برای دریافت و ارسال داده را مشخص میکنند. در اینجا، پین PD6 یا همان ICP1 به عنوان دریافتکننده (RX) و PD5 یا OC1A به عنوان فرستنده (TX) استفاده میشود. همانطور که از نام این پین ها مشخص است، از تایمر یک میکروکنترلر استفاده شده است.در صورتی که بخواهیم از تایمر شانزده بیتی شماره سه در یک میکروکنترلر ATmega64 برای ساخت پورت سریال نرم افزاری استفاده نمائیم، باید از پین های ICP3 و OC3A برای پین های دریافت و ارسال دیتای سریال استفاده نمائیم.
این تنظیمات به ما اجازه میدهد که ارتباط سریال را با استفاده از این پینها شبیهسازی کنیم و دادهها را بین میکروکنترلر و دستگاههای خارجی منتقل کنیم.
2. تعریف بیتریت و زمان هر بیت (BAUDRATE و BIT_TIME):
یکی از بخشهای مهم در ارتباط سریال، تنظیم بیتریت (Baud Rate) است. در این کتابخانه، بیتریت با مقدار 19200 تعریف شده است:
1 2 3 |
#define BAUDRATE 19200 // تعریف بیتریت (سرعت انتقال داده) برای ارتباط سریال نرمافزاری #define BIT_TIME (uint16_t)(F_CPU / BAUDRATE + 0.5) /* تعداد کلاکها برای انتقال هر بیت (به صورت گرد شده) */ |
-
BAUDRATE: این مقدار مشخص میکند که چه تعداد بیت در ثانیه ارسال یا دریافت میشود. بیتریت 19200 به این معنی است که 19200 بیت در هر ثانیه منتقل میشود.
-
BIT_TIME: این مقدار تعداد کلاکهای لازم برای انتقال یک بیت را نشان میدهد و با استفاده از فرکانس کاری میکروکنترلر (F_CPU) محاسبه میشود. این مقدار به صورت گرد شده محاسبه میشود تا دقت لازم برای تنظیم زمان هر بیت فراهم شود.
3. توابع کلیدی کتابخانه:
در فایل softUart.h، تعدادی تابع برای راهاندازی و استفاده از ارتباط سریال نرمافزاری تعریف شدهاند:
-
void softUart_Init(void): این تابع برای مقداردهی اولیه Software UART و تنظیم پورتهای ورودی/خروجی استفاده میشود.
-
void softUart_RxByte(uint8_t *data): این تابع یک بایت داده را از پورت سریال دریافت کرده و در متغیر اشارهگر داده ذخیره میکند.
-
void softUart_TxByte(uint8_t data): این تابع یک بایت داده را از طریق پورت سریال ارسال میکند.
-
void softUart_RxBuffer(uint8_t *buffer, uint8_t length): این تابع چندین بایت داده را به صورت پشتسرهم از پورت سریال دریافت کرده و در آرایه buffer ذخیره میکند.
-
void softUart_TxBuffer(uint8_t *buffer, uint8_t length): این تابع چندین بایت داده را از طریق پورت سریال ارسال میکند.
در ادامه، با بررسی فایل softUart.c به توضیح پیادهسازی این توابع میپردازیم و نحوه عملکرد آنها را به تفصیل بررسی خواهیم کرد.
پیادهسازی توابع راه اندازی پورت سریال نرم افزاری:
فایل softUart.c شامل پیادهسازی کامل کتابخانه Software UART است که با استفاده از تایمر1 و وقفهها، قابلیت ارتباط سریال نرمافزاری را در میکروکنترلرهای AVR فراهم میکند. در ادامه، بخشهای مهم کد و توابع آن به تفصیل توضیح داده میشود.
1. تعریف متغیرها:
در ابتدای فایل softUart.c، متغیرهایی برای کنترل عملیات ارسال و دریافت سریال تعریف شدهاند:
1 2 3 4 5 6 7 8 9 10 11 |
volatile uint8_t sRxDone; /* نشاندهنده آماده بودن داده دریافتی برای خواندن */ static volatile uint8_t sTxCount; /* شمارشگر تعداد بیتهایی که باید ارسال شوند */ static volatile uint8_t sTxData; /* دادهای که باید از طریق پورت سریال ارسال شود */ static volatile uint8_t sRxData; /* دادهای که از طریق پورت سریال دریافت شده است */ static volatile uint8_t sRxMask; /* ماسک بیت برای خواندن بیتهای دریافتی به صورت گام به گام */ static volatile uint8_t sRxTemp; /* متغیر موقت برای ذخیره دادههای دریافتی */ |
-
sRxDone: این متغیر volatile نشان میدهد که بایت دریافتی آمادهی خواندن است.
-
sTxCount: تعداد بیتهایی که باید ارسال شوند را کنترل میکند.
-
sTxData و sRxData: این متغیرها برای ذخیره دادههای در حال ارسال و دریافت استفاده میشوند.
-
sRxMask و sRxTemp: برای خواندن بیتهای دریافتی به صورت گام به گام و ذخیره موقتی دادهها استفاده میشوند.
2. مدیریت وقفهها:
کتابخانه از وقفههای تایمر1 برای شبیهسازی عملیات ارسال و دریافت سریال استفاده میکند. این وقفهها به شرح زیر هستند:
وقفه ورودی Capture (TIMER1 Input Capture Interrupt):
این وقفه زمانی فعال میشود که پایه RX یک بیت شروع (Start Bit) را تشخیص میدهد. در این حالت، رجیستر OCR1B برای خواندن بیتها پس از زمان مشخصی تنظیم میشود:
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 |
ISR(TIMER1_CAPT_vect) { /* تنظیم OCR1B برای خواندن دادههای دریافتی (Rx) */ OCR1B = ICR1 + (uint16_t)(BIT_TIME * 1.5); /* وقفه مقایسه B (Output Compare B) پس از 1.5 BIT_TIME رخ خواهد داد */ sRxTemp = 0; /* پاکسازی متغیر موقت */ sRxMask = 1; /* تنظیم ماسک بیت برای خواندن اولین بیت داده */ TIFR = BV(OCF1B); /* پاکسازی فلگ وقفه مقایسه B (Output Compare B) */ if(!(SWU_PIN & BV(SWU_RX))) /* اگر پایه RX پایین باشد، به این معناست که بیت شروع (Start Bit) دریافت شده است */ { TIMSK = BV(OCIE1A) | BV(OCIE1B); /* غیرفعال کردن وقفه ورودی (تشخیص بیت شروع)، فعال کردن وقفه مقایسه A (برای ارسال Tx) و B (برای دریافت Rx) */ } } |
این وقفه مقدار OCR1B را بهگونهای تنظیم میکند که پس از مدت زمان 1.5 BIT_TIME از شروع بیت، بیتهای بعدی خوانده شوند.
وقفه مقایسه B یا (TIMER1 Output Compare B Interrupt):
این وقفه برای خواندن بیتهای داده از پورت RX استفاده میشود. هر بار که وقفه فعال میشود، یک بیت از پورت RX خوانده شده و در sRxTemp ذخیره میشود:
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 |
ISR(TIMER1_CAPT_vect) { /* تنظیم OCR1B برای خواندن دادههای دریافتی (Rx) */ OCR1B = ICR1 + (uint16_t)(BIT_TIME * 1.5); /* وقفه مقایسه B (Output Compare B) پس از 1.5 BIT_TIME رخ خواهد داد */ sRxTemp = 0; /* پاکسازی متغیر موقت */ sRxMask = 1; /* تنظیم ماسک بیت برای خواندن اولین بیت داده */ TIFR = BV(OCF1B); /* پاکسازی فلگ وقفه مقایسه B (Output Compare B) */ if(!(SWU_PIN & BV(SWU_RX))) /* اگر پایه RX پایین باشد، به این معناست که بیت شروع (Start Bit) دریافت شده است */ { TIMSK = BV(OCIE1A) | BV(OCIE1B); /* غیرفعال کردن وقفه ورودی (تشخیص بیت شروع)، فعال کردن وقفه مقایسه A (برای ارسال Tx) و B (برای دریافت Rx) */ } } |
این وقفه به صورت گام به گام بیتهای دریافتی را میخواند و در نهایت مقدار دریافتی را در sRxData ذخیره میکند.
وقفه مقایسه A یا (TIMER1 Output Compare A Interrupt):
این وقفه برای ارسال بیتهای داده از پورت TX استفاده میشود. بیتها یکی یکی از sTxData خوانده شده و در پورت TX قرار میگیرند:
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 |
ISR(TIMER1_COMPA_vect) { uint8_t OutputMode; OCR1A += BIT_TIME; /* تنظیم OCR1A برای ارسال بیت بعدی */ if(sTxCount) /* اگر بیتهایی برای ارسال وجود دارد */ { sTxCount--; /* کاهش شمارشگر بیتها */ OutputMode = BV(COM1A1); /* تنظیم خروجی به حالت پایین (low) */ if(sTxCount != 9) /* اگر بیت جاری یک بیت داده است (نه بیت شروع یا توقف) */ { /* اگر بیت جاری صفر باشد، خروجی را به حالت بالا (high) تنظیم کن (چون sTxData معکوس شده است) */ if(!(sTxData & 0x01)) OutputMode = BV(COM1A1) | BV(COM1A0); sTxData >>= 1; /* شیفت به سمت راست برای آماده کردن بیت بعدی */ } TCCR1A = OutputMode; /* تنظیم حالت خروجی تایمر برای بیت جاری */ } } |
این وقفه مسئول ارسال بیتها به صورت معکوس (برای ایجاد بیت توقف صحیح) میباشد.
3. توابع کلیدی
مقداردهی اولیه (softUart_Init):
این تابع برای مقداردهی اولیه Software UART استفاده میشود:
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 |
void softUart_Init() { OCR1A = TCNT1 + 1; /* وقفه مقایسه A بلافاصله پس از مقداردهی اولیه فراخوانی میشود */ TCCR1A = BV(COM1A1) | BV(COM1A0); /* تنظیم حالت خروجی: OC1A در وضعیت بالا (Idle)، تایمر1 در حالت 0 */ TCCR1B = BV(ICNC1) | BV(CS10); /* فعالسازی حذف نویز برای ورودی Capture، تشخیص لبه نزولی، بدون تقسیم فرکانس */ TIFR = BV(ICF1); /* پاکسازی فلگ Capture */ TIMSK = BV(TICIE1) | BV(OCIE1A); /* فعالسازی وقفه ورودی Capture (تشخیص بیت شروع) و وقفه مقایسه A (برای ارسال Tx) */ sTxCount = 0; /* بدون داده برای ارسال (Tx) */ sRxDone = 0; /* بدون داده برای دریافت (Rx) */ SWU_DDR |= BV(SWU_TX); /* تنظیم پین TX بهعنوان خروجی */ sei(); /* فعالسازی وقفههای عمومی */ } |
این تابع پایه TX را به عنوان خروجی تنظیم کرده و وقفههای لازم برای ارسال و دریافت داده را فعال میکند.
دریافت یک بایت (softUart_RxByte):
این تابع یک بایت داده را از پورت سریال دریافت میکند:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void softUart_RxByte(uint8_t * data) { while( !sRxDone ); /* منتظر بمانید تا داده دریافتی آماده شود */ sRxDone = 0; /* علامت آماده بودن داده را پاک کنید */ *data = sRxData; /* ذخیره داده دریافتی */ } |
این تابع تا زمانی که داده آماده نشده باشد، منتظر میماند و سپس داده دریافتی را بازمیگرداند.
ارسال یک بایت (softUart_TxByte)
این تابع یک بایت داده را ارسال میکند:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void softUart_TxByte(uint8_t data) { while(sTxCount); /* منتظر بمانید تا ارسال دادههای قبلی به پایان برسد */ sTxData = ~data; /* نوشتن داده به صورت معکوس برای تولید بیت توقف */ sTxCount = 10; /* تعداد بیتها: بیت شروع (1) + داده (8) + بیت توقف (1) */ } |
در این تابع، دادهها معکوس میشوند تا بیت توقف به درستی تولید شود.
ارسال و دریافت چند بایت (softUart_RxBuffer و softUart_TxBuffer):
این توابع برای دریافت یا ارسال چندین بایت داده به صورت پشتسرهم استفاده میشوند:
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 |
void softUart_RxBuffer(uint8_t *buffer, uint8_t length) { for(uint8_t i = 0; i < length; i++) /* حلقه برای دریافت تعداد مشخصی از بایتها */ { softUart_RxByte(buffer); /* دریافت یک بایت و ذخیره آن در آرایه buffer */ buffer++; /* اشارهگر buffer را به بایت بعدی منتقل کن */ } } void softUart_TxBuffer(uint8_t *buffer, uint8_t length) { for(uint8_t i = 0; i < length; i++) /* حلقه برای ارسال تعداد مشخصی از بایتها */ { softUart_TxByte(*buffer); /* ارسال یک بایت از آرایه buffer */ buffer++; /* اشارهگر buffer را به بایت بعدی منتقل کن */ } } |
این توابع از توابع softUart_RxByte و softUart_TxByte برای پردازش هر بایت به صورت جداگانه استفاده میکنند.
استفاده از کتابخانه در فایل main.c:
فایل main.c شامل کد اصلی پروژه است که از توابع کتابخانه Software UART برای ارسال و دریافت دادهها استفاده میکند. این فایل به عنوان نمونهای از نحوه استفاده از کتابخانه در پروژههای واقعی عمل میکند. در ادامه به توضیح بخشهای مهم این فایل میپردازیم.
1. تعریف متغیرها و تنظیمات اولیه:
در ابتدای فایل، متغیری برای ذخیره دادههای دریافتی تعریف شده است و توابع و سختافزارهای مورد نیاز مقداردهی اولیه میشوند:
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 |
uint8_t receivedByte = 0; /* متغیر برای ذخیره بایت دریافتی از ارتباط سریال */ int main(void) { //---------------------------------------- // مقداردهی اولیه سیستم //---------------------------------------- // مقداردهی اولیه سختافزارها hardwares_Init(); // مقداردهی اولیه ورودی/خروجیها io_Init(); // مقداردهی اولیه UART نرمافزاری softUart_Init(); // روشن کردن LED برای نشان دادن وضعیت فعال بودن سیستم HB_LED_On(); _delay_ms(50); HB_LED_Off(); _delay_ms(50); //---------------------------------------- |
-
receivedByte: متغیری برای ذخیره داده دریافتی از پورت سریال نرمافزاری.
-
hardwares_Init()، io_Init()، و softUart_Init(): توابع مقداردهی اولیه سختافزارها، ورودی/خروجیها، و Software UART.
-
HB_LED_On() و HB_LED_Off(): این توابع برای نمایش وضعیت کارکرد سیستم (مثلاً روشن یا خاموش بودن LED) استفاده میشوند.
2. حلقه اصلی برنامه:
در حلقه اصلی، دادههای دریافتی از پورت سریال خوانده شده و سپس همان داده دوباره ارسال میشود. این عملیات با نام “Echo” شناخته میشود که به معنای ارسال دوباره دادههای دریافتی است:
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 |
//---------------------------------------- // حلقه بینهایت برای اجرای مداوم //---------------------------------------- while(1) { //------------------------------------------------ // اکو کردن هر بایت دریافتی از UART نرمافزاری if(sRxDone) /* اگر بایت دریافتی آماده است */ { softUart_RxByte(&receivedByte); /* دریافت بایت و ذخیره در متغیر receivedByte */ softUart_TxByte(receivedByte); /* ارسال بایت دریافتی از طریق پورت سریال */ } //------------------------------------------ //------------------------------------------ // چشمک زدن LED برای نشان دادن وضعیت فعال بودن سیستم HB_LED_Tgl(); _delay_ms(50); //------------------------------------------ } return 0; } |
-
while(1): حلقه بینهایت برای اجرای مداوم کد.
-
if(sRxDone): بررسی میکند که آیا دادهای از پورت سریال دریافت شده است یا خیر. اگر sRxDone برابر با 1 باشد، به این معنی است که داده آماده خواندن است.
-
softUart_RxByte(&receivedByte): این تابع یک بایت داده را از پورت سریال دریافت کرده و در receivedByte ذخیره میکند.
-
softUart_TxByte(receivedByte): این تابع بایت دریافتشده را دوباره از طریق پورت سریال ارسال میکند.
- HB_LED_Tgl(): تغییر وضعیت LED برای نمایش زنده بودن سیستم.
برای دانلود فایل سورس کد و کتابخانه و فایل شبیه سازی آموزش راه اندازی پورت سریال نرم افزاری در AVR و اتمل استودیو روی لینک زیر کلیک کنید. پسورد فایل www.mehradkit.ir می باشد.
شبیه سازی انجام شده و کارکتر های اکو شده در پورت سریال مجازی توسط شبیه سازی با نرم افزار پروتئوس در زیر نشان داده شده.
نتیجهگیری:
در این مقاله، با نحوه پیادهسازی و استفاده از یک پورت سریال نرمافزاری (Software UART) در میکروکنترلرهای AVR آشنا شدیم. ابتدا به معرفی مفهوم Software UART و دلیل استفاده از آن پرداختیم. سپس به بررسی اصول پایه ارتباط سریال، پیکربندی تایمر1، و نحوه مقداردهی اولیه و تنظیم رجیسترها برای راهاندازی ارتباط سریال نرمافزاری پرداختیم.
این کتابخانه یک راهحل ساده و کاربردی برای راهاندازی ارتباط سریال در میکروکنترلرهایی است که پورت سریال سختافزاری کافی ندارند. با پیکربندی مناسب تایمرها و استفاده از وقفهها، میتوان ارتباط سریال قابل اعتمادی را بهصورت نرمافزاری پیادهسازی کرد. این روش بهخصوص در پروژههایی که نیاز به گسترش تعداد پورتهای سریال دارند یا به دلیل محدودیتهای سختافزاری امکان استفاده از چندین پورت UART سختافزاری نیست، بسیار مفید است.
بسیار بسیار ممنون از اینکه رایگان این اطلاعات را در اختیار همه قرار میدید.
با سلام. ممنون از انرژی مثبت شما