با درود و احترام خدمت همه دوستان و همکاران عزیز. میخام با استفاده از ارتباط سریال یه رشته 10 کارکتری رو دریافت کنم. در حالت عادی و بدون استفاده از وقفه دریافت ارتباط سریال، با دستور gets برنامه به خوبی کار میکنه و هر 10 بایت دیتای ارسالی بدون نقص در گیرنده دریافت میشه ولی چون وقتی میکرو به این دستور میرسه تا زمان دریافت دیتا روی این خط از برنامه متوقف میشه، نمیتونم همزمان سون سگمنتهایی که به میکرو وصل هستن رو رفرش کنم. بنابراین از وقفه دریافت استفاده کردم که متاسفانه این وقفه که با شماره وکتور 12 قابل دسترسی هستش، هر دفعه فقط یک بایت از رشته ارسالی رو دریافت میکنه. لطفا اگر راهکاری به نظرتون میرسه برای دریافت کامل 10 بایت ارائه بفرمایید. از دستورات حلقه و ... استفاده کردم ولی جواب نداد.
اطلاعیه
Collapse
No announcement yet.
درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt
Collapse
X
-
پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt
نوشته اصلی توسط soleimani_m نمایش پست هابا درود و احترام خدمت همه دوستان و همکاران عزیز. میخام با استفاده از ارتباط سریال یه رشته 10 کارکتری رو دریافت کنم. در حالت عادی و بدون استفاده از وقفه دریافت ارتباط سریال، با دستور gets برنامه به خوبی کار میکنه و هر 10 بایت دیتای ارسالی بدون نقص در گیرنده دریافت میشه ولی چون وقتی میکرو به این دستور میرسه تا زمان دریافت دیتا روی این خط از برنامه متوقف میشه، نمیتونم همزمان سون سگمنتهایی که به میکرو وصل هستن رو رفرش کنم. بنابراین از وقفه دریافت استفاده کردم که متاسفانه این وقفه که با شماره وکتور 12 قابل دسترسی هستش، هر دفعه فقط یک بایت از رشته ارسالی رو دریافت میکنه. لطفا اگر راهکاری به نظرتون میرسه برای دریافت کامل 10 بایت ارائه بفرمایید. از دستورات حلقه و ... استفاده کردم ولی جواب نداد.
استفاده از حلقه و معطل کردن برنامه در سرویس وقفه کار درستی نیست! سرویس وقفه باید تا حد ممکن کوتاه باشه.
شما کافیه یک بافر و یک متغیر گلوبال تعریف کنید که این متغیر وظیفه شمارش روی بافر رو انجام بده. به این شکل که با هر بار وارد شدن به سرویس وقفه، داده پورت سریال رو داخل بافر و توی خونه ای که اون شمارنده مشخص میکنه کپی کنید و یک واحد شمارنده رو افزایش بدید. به محض این که شمارنده به عدد ۱۰ رسید دوباره صفرش میکنید. فقط باید به وسیله پرچمی به برنامه اصلی اطلاع بدید بافر پر شده.
برای عملکرد بهتر میتونید از ۲ بافر استفاده کنید. زمانی که برنامه در حال پردازش روی بافر اول هستش سرویس وقفه بافر دوم رو پر کنه و برعکس. مدیریت این عملکرد هم کار زیاد سختی نیست و کمی فکر کنید روش مناسبی براش پیدا میکنید.
- تشکرها 1
-
پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt
نوشته اصلی توسط hossein.m98 نمایش پست هاسلام
استفاده از حلقه و معطل کردن برنامه در سرویس وقفه کار درستی نیست! سرویس وقفه باید تا حد ممکن کوتاه باشه.
شما کافیه یک بافر و یک متغیر گلوبال تعریف کنید که این متغیر وظیفه شمارش روی بافر رو انجام بده. به این شکل که با هر بار وارد شدن به سرویس وقفه، داده پورت سریال رو داخل بافر و توی خونه ای که اون شمارنده مشخص میکنه کپی کنید و یک واحد شمارنده رو افزایش بدید. به محض این که شمارنده به عدد ۱۰ رسید دوباره صفرش میکنید. فقط باید به وسیله پرچمی به برنامه اصلی اطلاع بدید بافر پر شده.
برای عملکرد بهتر میتونید از ۲ بافر استفاده کنید. زمانی که برنامه در حال پردازش روی بافر اول هستش سرویس وقفه بافر دوم رو پر کنه و برعکس. مدیریت این عملکرد هم کار زیاد سختی نیست و کمی فکر کنید روش مناسبی براش پیدا میکنید.
مشکل اینجاست در حالت بدون وقفه، همه 10 بایت روی یک رشته با دستور gets قرار میگیره اما در حالت وقفه باید 10 بار دیتا رو پشت سر هم ارسال کنم چون هر بار هم فقط یه بایت دربافت میشه. ولی خوب بعد از 10 بار ارسال، رشته مزبور بطور کامل دریافت میشه.جدیدترین ویرایش توسط soleimani_m; ۰۰:۲۰ ۱۴۰۰/۰۳/۱۹.
دیدگاه
-
پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt
نوشته اصلی توسط soleimani_m نمایش پست هاممنونم از پاسختون مهندس. با قسمت آخر جوابتون خیلی مشکلی ندارم ولی قسمت اول رو درست متوجه نشدم. اگه نمونه برنامه ای دارید ممنون میشم بذارید.
مشکل اینجاست در حالت بدون وقفه، همه 10 بایت روی یک رشته با دستور gets قرار میگیره اما در حالت وقفه باید 10 بار دیتا رو پشت سر هم ارسال کنم چون هر بار هم فقط یه بایت دربافت میشه. ولی خوب بعد از 10 بار ارسال، رشته مزبور بطور کامل دریافت میشه.
unsigned char Counter = 0;
volatile unsigned char BufferFullFlag = 0;
unsigned char Buffer[10];
void ISR_UART(void)
{
Buffer[Counter] = UDR;
Counter++;
if (Counter == 10)
{
Counter = 0;
BufferFullFlag = 1;
}
}
void main(void)
{
// Some code
while (1)
{
if (BufferFullFlag != 0)
{
BufferFullFlag = 0;
// Some code
}
}
}
اینم یه نمونه کد ساده که متونید ازش الگو بگیرید. فقط حواستون باشه این برنامه در مقابل از دست رفتن داده ها ایمن نیست و قبل از رسیدن بایت 0 ام باید توی برنامه اصلی بافر خالی بشه وگرنه داده ها از بین میرن.
- تشکرها 1
دیدگاه
-
پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt
نوشته اصلی توسط hossein.m98 نمایش پست هاشما اگر 10 بایت ارسال کنید 10 بار هم وقفه دریافت میکنید.
unsigned char Counter = 0;
volatile unsigned char BufferFullFlag = 0;
unsigned char Buffer[10];
void ISR_UART(void)
{
Buffer[Counter] = UDR;
Counter++;
if (Counter == 10)
{
Counter = 0;
BufferFullFlag = 1;
}
}
void main(void)
{
// Some code
while (1)
{
if (BufferFullFlag != 0)
{
BufferFullFlag = 0;
// Some code
}
}
}
اینم یه نمونه کد ساده که متونید ازش الگو بگیرید. فقط حواستون باشه این برنامه در مقابل از دست رفتن داده ها ایمن نیست و قبل از رسیدن بایت 0 ام باید توی برنامه اصلی بافر خالی بشه وگرنه داده ها از بین میرن.
کد:[FONT=Yekan]/*******************************************************[/FONT]Date : 6/8/2021 Chip type : ATmega32A AVR Core Clock frequency: 11.059200 MHz *******************************************************/ #include <mega32a.h> #include <alcd.h> #include <stdio.h> #include <delay.h> #ifndef RXB8 #define RXB8 1 #define TXB8 0 #define UPE 2 #define DOR 3 #define FE 4 #define UDRE 5 #define RXC 7 #endif #define DATA_REGISTER_EMPTY (1<<UDRE) #define RX_COMPLETE (1<<RXC) #define FRAMING_ERROR (1<<FE) #define PARITY_ERROR (1<<UPE) #define DATA_OVERRUN (1<<DOR) // USART Receiver buffer #define RX_BUFFER_SIZE 11 char rx_buffer[RX_BUFFER_SIZE]; bit rx_buffer_overflow; unsigned char rx_wr_index =0; // USART Receiver interrupt service routine interrupt [USART_RXC] void usart_rx_isr(void) { char status,data; status=UCSRA; data=UDR; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) { rx_buffer[rx_wr_index++]=data; if(rx_wr_index == RX_BUFFER_SIZE)rx_buffer_overflow=1; } } void main(void) { DDRB.0=1; // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: Off // USART Mode: Asynchronous // USART Baud Rate: 9600 UCSRA=0; UCSRB=0x90; UCSRC=0x86; UBRRH=0x00; UBRRL=0x47; // Global enable interrupts #asm("sei") lcd_init(16); lcd_puts("USART Interrupt"); delay_ms(2000); lcd_clear(); lcd_puts("Receive:"); while (1) { if(rx_buffer_overflow) { rx_buffer_overflow =0; rx_wr_index=0; lcd_gotoxy(2,1); lcd_puts(rx_buffer); } PORTB.0 =~PORTB.0; delay_ms(400); } [FONT=Yekan]}[/FONT]
دیدگاه
-
پاسخ : درخواست راهنمایی برای کار با وقفه ارتباط سریال USART Receiver Interrupt
برادر عزیز هیچ وقت سون سگمت را در داخل main رفرش نکنید.یعنی تابع نمایش سگمنت هارا در وقفه تایمر صفر یا یک قراربدید.هر وقت تایمر سرریز کرد، در روتین وقفه تایمر صفر پایه هارا رفرش کنید.اینجوری هیچ وقت به مشکل نخواهید خورد.از انجایی که کلاک تایمر مستقیم از واحدمقسم فرکانس تامین میشه همیشه ثابته و همین قابت بودن باعث میشه که شما یک سرعت بسیار خوبی برای رفرش سگمنت ا داشته باشید.جدیدترین ویرایش توسط Namvar14; ۰۲:۰۳ ۱۴۰۰/۰۳/۲۰.eshop-hodhod.ir
دیدگاه
دیدگاه