Câu hỏi ban đầu
Tôi có một câu hỏi chung về việc xử lý các ngắt trong vi điều khiển. Tôi đang sử dụng MSP430, nhưng tôi nghĩ câu hỏi có thể được mở rộng cho các uC khác. Tôi muốn biết có hay không thực hành tốt để bật / tắt các ngắt thường xuyên dọc theo mã. Ý tôi là, nếu tôi có một phần mã sẽ không nhạy cảm với các ngắt (hoặc thậm chí tệ hơn, không được nghe các ngắt, vì bất kỳ lý do nào), tốt hơn là:
- Vô hiệu hóa các ngắt trước và sau đó kích hoạt lại chúng sau phần quan trọng.
- Đặt cờ bên trong ISR tương ứng và (thay vì vô hiệu hóa ngắt), đặt cờ thành sai trước phần quan trọng và đặt lại thành đúng, ngay sau đó. Để ngăn chặn mã của ISR được thực thi.
- Cả hai, vì vậy đề nghị được chào đón!
Cập nhật: ngắt và biểu đồ trạng thái
Tôi sẽ cung cấp một tình huống cụ thể. Giả sử chúng ta muốn thực hiện một biểu đồ trạng thái, bao gồm 4 khối:
- Chuyển đổi / Hiệu ứng.
- Điều kiện thoát hiểm.
- Hoạt động nhập cảnh.
- Làm hoạt động.
Đây là những gì một giáo sư đã dạy chúng tôi tại trường đại học. Có lẽ, không phải cách tốt nhất để làm điều đó là bằng cách làm theo sơ đồ này:
while(true) {
/* Transitions/Effects */
//----------------------------------------------------------------------
next_state = current_state;
switch (current_state)
{
case STATE_A:
if(EVENT1) {next_state = STATE_C}
if(d == THRESHOLD) {next_state = STATE_D; a++}
break;
case STATE_B:
// transitions and effects
break;
(...)
}
/* Exit activity -> only performed if I leave the state for a new one */
//----------------------------------------------------------------------
if (next_state != current_state)
{
switch(current_state)
{
case STATE_A:
// Exit activity of STATE_A
break;
case STATE_B:
// Exit activity of STATE_B
break;
(...)
}
}
/* Entry activity -> only performed the 1st time I enter a state */
//----------------------------------------------------------------------
if (next_state != current_state)
{
switch(next_state)
{
case STATE_A:
// Entry activity of STATE_A
break;
case STATE_B:
// Entry activity of STATE_B
break;
(...)
}
}
current_state = next_state;
/* Do activity */
//----------------------------------------------------------------------
switch (current_state)
{
case STATE_A:
// Do activity of STATE_A
break;
case STATE_B:
// Do activity of STATE_B
break;
(...)
}
}
Chúng ta cũng giả sử rằng, từ, STATE_A
tôi muốn nhạy cảm với một ngắt đến từ một tập hợp các nút (với hệ thống gỡ lỗi, v.v.). Khi ai đó nhấn một trong các nút này, một ngắt được tạo và cờ liên quan đến cổng đầu vào được sao chép vào một biến buttonPressed
. Nếu phần gỡ lỗi được đặt thành 200 ms theo một cách nào đó (bộ đếm thời gian theo dõi, bộ đếm thời gian, bộ đếm, ...) chúng tôi chắc chắn rằng buttonPressed
không thể cập nhật với giá trị mới trước 200 ms. Đây là những gì tôi đang hỏi bạn (và bản thân tôi :) tất nhiên)
Tôi có cần kích hoạt ngắt trong hoạt động DO STATE_A
và vô hiệu hóa trước khi rời đi không?
/* Do activity */
//-------------------------------------
switch (current_state)
{
case STATE_A:
// Do activity of STATE_A
Enable_ButtonsInterrupt(); // and clear flags before it
// Do fancy stuff and ...
// ... wait until a button is pressed (e.g. LPM3 of the MSP430)
// Here I have my buttonPressed flag ready!
Disable_ButtonsInterrupt();
break;
case STATE_B:
// Do activity of STATE_B
break;
(...)
}
Theo cách mà tôi chắc chắn rằng lần sau khi tôi thực hiện khối 1 (chuyển tiếp / hiệu ứng) ở lần lặp tiếp theo, tôi chắc chắn rằng các điều kiện được kiểm tra dọc theo các chuyển đổi không đến từ một ngắt tiếp theo đã ghi đè lên giá trị trước đó của buttonPressed
tôi cần (mặc dù điều này không thể xảy ra vì 250 ms phải trôi qua).