[Help] Lập trình nhiều nhiệm vụ cùng một lúc

lee_trieu

Gà con
Chào anh chị và các bạn !!
Em có một vấn đề này mong mọi người giúp đỡ !:-(
Em thường hay gặp phải vướn mắc ở chỗ lập trình sao cho các công việc khác nhau thực hiện song song cùng một lúc ạ???:5cool_sweat:
Ví dụ : Em thiết kế một mạch đèn cảnh sát như sau:

Chân P1.0 em xuất xung để tạo tiếng còi hú, còn 5 LED thì em lập trình theo hiệu ứng của đèn cảnh sát. vấn đề em gặp phải là khi còi hú thì đèn đứng yên:-scòn khi đèn nháy thì còi lại không hú đúng ..:5cool_sweat:Mong anh chị và các bạn giúp đỡ em ạ !! Em xin cảm ơn !!:)
 

electric_man

Thành Viên PIF
có 3 cách e có thể dùng
1. dùng interrupt (strong recommend)
2. e dùng vòng lặp vô tận để thực hiện các task, kiểu như thế này
while(1)
{
task1();
delay();
task2();
delay();
}
tất nhiên là cách này thời gian phải đủ nhỏ để tránh k nhận biết được
3. nếu MCU em đủ lớn thì dùng RTOS để quản lý!!!
 

lee_trieu

Gà con
có 3 cách e có thể dùng
1. dùng interrupt (strong recommend)
2. e dùng vòng lặp vô tận để thực hiện các task, kiểu như thế này
while(1)
{
task1();
delay();
task2();
delay();
}
tất nhiên là cách này thời gian phải đủ nhỏ để tránh k nhận biết được
3. nếu MCU em đủ lớn thì dùng RTOS để quản lý!!!
Anh có thể nói rõ hơn giúp em chỗ dùng ngắt và RTOS không ạ?? Vì cách 2 em thấy hơi khó với ứng dụng của em, vì phải tạo tín hiệu ra loa với tần số cao nên việc delay không khả thi ạ:-s
 

chung

Trứng gà
chương trình chính tạo âm thanh còn ngắt timer cho hiển thị led
 

lee_trieu

Gà con
chương trình chính tạo âm thanh còn ngắt timer cho hiển thị led
Em viết Timer theo kiểu này, nhưng hình như nó bị xung đột hay sao ah, mấy anh xem giúp em thử lỗi là do đâu ạ??:-(
PHP:
#define T_out1Hz     100
#define T_nhayled1s  100
#define T_nhayled5s  500
 
unsigned char Enable_out1Hz=0;
unsigned char Enable_nhayled1s=0;
unsigned char Enable_nhayled5s=0;
 
void out1Hz(void)
{
Enable_out1Hz=0;
P1OUT ^= BIT0;
}
void nhay5s(void)
{
Enable_nhayled1s=0;
P1OUT ^= BIT1;
}
void nhay1s(void)
{
Enable_nhayled5s=0;
P1OUT ^= BIT2;
}
 
void main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  P1DIR |= 0xff;
  while(1)
  {
   if(Enable_out1Hz==1) out1Hz();
   if(Enable_out1Hz==1) nhay5s();
   if(Enable_out1Hz==1) nhay1s();
  }
}
 
Ngat_Timer_1(void)//Gia su sau 10ms vào ngat nay 1 lan
{
 static unsigned int count_out1Hz=0;
 static unsigned int count_nhayled1s=0;
 static unsigned int count_nhayled5s=0;
 
 count_out1Hz++;
 count_nhayled1s++;
 count_nhayled5s++;
 
 if(count_out1Hz >> T_out1Hz)
   {
    count_out1Hz=0;    
    Enable_out1Hz=1;
   }
 if(count_nhayled1s >> T_nhayled1s)
   {
    count_nhayled1s=0;
    Enable_nhayled1s=1;
   }
 if(count_nhayled5s >> T_nhayled5s)
   {
    count_nhayled5s=0;
    Enable_nhayled5s=1;
   }
}
Chương trình trên :
-chân P1.0 xuất xung 1Hz.
-chân P1.1 nháy LED mỗi 1s
-Chân P1.2 nháy LED mỗi 5s
nhưng kết quả lại bị sai, chỉ LED ở chân P1.1 là nháy đúng 1s, còn LED chân P1.2 không phải 5s đổi trạng thái 1 lần mà nó nhấp nháy 2 lần (2s) sau đó tắt, rồi lại như thế, hình như nó bị xung đột ngắt hay sao ah, ai xem giúp em với ạ :((:5cool_sweat:
 

electric_man

Thành Viên PIF
Haizza!!! có chút nhận xét như sau
1. đánh giá tốt ý tưởng viết: sử dụng các cờ (flag) sẽ được set trong ngắt và cờ đó được dùng để thực thi task nào được thực hiện
2. bạn nên xem lại chương trình mình viết xíu đi, bạn sẽ phát hiện ra những lỗi khá là ngớ ngẩn đó (do copy --> paste mà k sữa hết nội dung, cái dấu " >>" dùng để dịch phải bit chứ k dùng để so sánh lớn hơn...ect)!!!
 

lee_trieu

Gà con
Haizza!!! có chút nhận xét như sau
1. đánh giá tốt ý tưởng viết: sử dụng các cờ (flag) sẽ được set trong ngắt và cờ đó được dùng để thực thi task nào được thực hiện
2. bạn nên xem lại chương trình mình viết xíu đi, bạn sẽ phát hiện ra những lỗi khá là ngớ ngẩn đó (do copy --> paste mà k sữa hết nội dung, cái dấu " >>" dùng để dịch phải bit chứ k dùng để so sánh lớn hơn...ect)!!!
ah cái dấu >> là >= đó anh. :-(
(cái Project em viết đúng lúc Ctr+H để replace nó lỗi không hay)
mà em viết như thế, nhwg khi đổ code xuống thì LED nó nháy không đúng như ý muốn, chỉ có cái LED nháy 1s là đúng, còn 5s lại sai, cứ như nó bị ưu tiên ngắt cho 1s hay sao ấy??:5cool_sweat::-(
 

messier

Ban Chủ Nhiệm
Đang suy nghĩ tại sao bạn lại không dùng chức năng PWM của timer ?? :5cool_sweat:
 

electric_man

Thành Viên PIF
chương trình chính tạo âm thanh còn ngắt timer cho hiển thị led
Em viết Timer theo kiểu này, nhưng hình như nó bị xung đột hay sao ah, mấy anh xem giúp em thử lỗi là do đâu ạ??:-(
PHP:
#define T_out1Hz    100
#define T_nhayled1s  100
#define T_nhayled5s  500
 
unsigned char Enable_out1Hz=0;
unsigned char Enable_nhayled1s=0;
unsigned char Enable_nhayled5s=0;
 
void out1Hz(void)
{
Enable_out1Hz=0;
P1OUT ^= BIT0;
}
[COLOR=#ff0000]void nhay5s(void)[/COLOR]
[COLOR=#ff0000]{[/COLOR]
[COLOR=#ff0000]Enable_nhayled1s=0;[/COLOR]
P1OUT ^= BIT1;
}
[COLOR=#ff0000]void nhay1s(void)[/COLOR]
[COLOR=#ff0000]{[/COLOR]
[COLOR=#ff0000]Enable_nhayled5s=0;[/COLOR]
P1OUT ^= BIT2;
}
 
void main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  P1DIR |= 0xff;
  while(1)
  {
[COLOR=#ff0000] if(Enable_out1Hz==1) out1Hz();[/COLOR]
[COLOR=#ff0000]  if(Enable_out1Hz==1) nhay5s();[/COLOR]
[COLOR=#ff0000]  if(Enable_out1Hz==1) nhay1s();[/COLOR]
  }
}
 
Ngat_Timer_1(void)//Gia su sau 10ms vào ngat nay 1 lan
{
static unsigned int count_out1Hz=0;
static unsigned int count_nhayled1s=0;
static unsigned int count_nhayled5s=0;
 
count_out1Hz++;
count_nhayled1s++;
count_nhayled5s++;
 
if(count_out1Hz >> T_out1Hz)
  {
    count_out1Hz=0;
    Enable_out1Hz=1;
  }
if(count_nhayled1s >> T_nhayled1s)
  {
    count_nhayled1s=0;
    Enable_nhayled1s=1;
  }
if(count_nhayled5s >> T_nhayled5s)
  {
    count_nhayled5s=0;
    Enable_nhayled5s=1;
  }
}
Chương trình trên :
-chân P1.0 xuất xung 1Hz.
-chân P1.1 nháy LED mỗi 1s
-Chân P1.2 nháy LED mỗi 5s
nhưng kết quả lại bị sai, chỉ LED ở chân P1.1 là nháy đúng 1s, còn LED chân P1.2 không phải 5s đổi trạng thái 1 lần mà nó nhấp nháy 2 lần (2s) sau đó tắt, rồi lại như thế, hình như nó bị xung đột ngắt hay sao ah, ai xem giúp em với ạ :((:5cool_sweat:
bạn kiểm tra lại mấy lỗi màu đỏ mình quote trên. rồi tính tiếp!!!!
 

lee_trieu

Gà con
bạn kiểm tra lại mấy lỗi màu đỏ mình quote trên. rồi tính tiếp!!!!
đây là code hoàn chỉnh của em, anh xegiups em nó bị lỗi chỗ nào không anh>?? em đổ code xuống thì kết quả cũng giống như mô phỏng, như hình bên dưới:-(

PHP:
#include "msp430g2553.h"
 
#define T_out1Hz     20  //nhay 1s
#define T_nhayled1s  60 //nhay 3s
#define T_nhayled5s  100  //nhay 5s
 
unsigned char Enable_out1Hz=0;
unsigned char Enable_nhayled1s=0;
unsigned char Enable_nhayled5s=0;
 
void out1Hz(void)
{
Enable_out1Hz=0;
P1OUT ^= BIT0;
}
void nhay5s(void)
{
Enable_nhayled5s=0;
P1OUT ^= BIT1;
}
void nhay1s(void)
{
Enable_nhayled1s=0;
P1OUT ^= BIT2;
}
void conf_clock(void)
{
   if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
  {  
    while(1);                               // If calibration constants erased
                                            // do not load, trap CPU!!
  }
  BCSCTL1 = CALBC1_1MHZ; //calibration clock - 1MHz
  DCOCTL = CALDCO_1MHZ;   
  
}
void conf_timer(void)
{
  CCTL0 = CCIE;                             // CCR0 interrupt enabled
  CCR0 = 50000;
  TACTL = TASSEL_2 + MC_1;                  // SMCLK, upmode
  __bis_SR_register(GIE);
}
void main( void )
{
  conf_timer();
  conf_clock();
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  P1DIR |= 0xff;
  while(1)
  {
   if(Enable_out1Hz==1) out1Hz();
   if(Enable_nhayled5s==1) nhay5s();
   if(Enable_nhayled1s==1) nhay1s();
  }
}
 
 
 
 
//Trih phuc vu ngat
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
 static unsigned int count_out1Hz=0;
 static unsigned int count_nhayled1s=0;
 static unsigned int count_nhayled5s=0;
 
 count_out1Hz++;
 count_nhayled1s++;
 count_nhayled5s++;
  CCR0 += 50000;  
 if(count_out1Hz >= T_out1Hz)
   {
    count_out1Hz=0;    
    Enable_out1Hz=1;
   }
 if(count_nhayled1s >= T_nhayled1s)
   {
    count_nhayled1s=0;
    Enable_nhayled1s=1;
   }
 if(count_nhayled5s >= T_nhayled5s)
   {
    count_nhayled5s=0;
    Enable_nhayled5s=1;
   }
}
 

electric_man

Thành Viên PIF
ủa. a thấy nó chạy đúng mà em. nếu như mình lấy thèn P1.0 làm chuẩn là 1s. còn việc nó bị trễ lúc bắt đầu thì chuyện này cũng bt vì nó mất chút time để khởi tạo chương trình chứ.!!!
 

lee_trieu

Gà con
ủa. a thấy nó chạy đúng mà em. nếu như mình lấy thèn P1.0 làm chuẩn là 1s. còn việc nó bị trễ lúc bắt đầu thì chuyện này cũng bt vì nó mất chút time để khởi tạo chương trình chứ.!!!
Em thấy Chỉ LED 1s là chạy đúng mà anh:-(LED 5s với LED 3s thì hình như nó chạy nó phân nữa thời gian hay gì à????:5cool_sweat:(2,5s cho 5s và 1,5s cho 3s) mặc dù em đã tính cho nó sáng 5s và tắt 5s trong code mà anh???:-(
Em tính như thế này nè:
xung 1Mhz(1 000 000)
cho Timer đếm lên từ 0 đến 50 000
vậy suy ra cứ sau 20 lần đếm là 1s.
em define tương ứng là:
#define T_out1Hz 20 //nhay 1s : đổi trạng thái sau 1s
#define T_nhayled1s 60 //nhay 3s: đổi trạng thái sau 3s
#define T_nhayled5s 100 //nhay 5s: đổi trạng thái sau 5s

:-s
 
Top