Tranh luận là một câu hỏi thường gặp. Bạn sẽ có thể tìm thấy ... số lượng trang web gần như không giới hạn về chủ đề này. Smith cũng nhận xét về bản PDF được đọc rộng rãi của Jack Ganssle về chủ đề này. Và với tất cả những câu trả lời này, bạn đã có cả phương pháp phần cứng và phần mềm.
Tôi sẽ thêm vào "tài liệu" này một chút bằng cách chủ yếu nói về những ý tưởng chưa được đề cập tốt. Nhưng trước khi tôi làm, một hoặc hai điểm:
- Việc gỡ lỗi trong phần cứng tương tự có thể đạt được kết quả mà bạn không thể đạt được bằng cách chuyển đổi "quan sát" chỉ bằng kỹ thuật số trên cơ sở định kỳ bằng cách bỏ phiếu hoặc thậm chí bằng các sự kiện thay đổi pin phần cứng. Nhưng bạn có thể làm "đủ tốt" cho tất cả ý định và mục đích, bằng kỹ thuật số. Hầu như không ai ngày nay sử dụng các giải pháp gỡ lỗi tương tự bên ngoài. Nhưng tôi đã sử dụng tất cả mọi thứ, từ kéo dài xung bằng cách sử dụng một lần chụp (74121) đến các kỹ thuật được đề cập bởi Jack Ganssle ở đây .
- Đối với những người chỉ lập trình nhúng và hoàn toàn không thích tìm hiểu về điện tử, công tắc gỡ lỗi có lẽ là một trong hai bộ kỹ năng cơ bản cần thiết. Đèn LED hoạt động có lẽ là một trong những khác. Và bằng cách này, tôi không có nghĩa là chỉ có một kỹ năng này. Tôi có nghĩa là có thể làm điều đó theo một số cách. Vì vậy, bạn thực sự làm cần thiết phải hoàn toàn thấu hiểu những gì Jack Ganssle viết về, và vẫn còn nhiều, liên quan đến công tắc.
Vì tôi đã đề cập đến việc kéo dài xung bằng cách sử dụng 74121 và vì Jack Ganssle không đề cập đến nó và cũng không có ai ở đây cả, nên tôi cũng có thể cung cấp liên kết bổ sung này dưới dạng đọc thêm đề nghị sử dụng 74121 hoặc 555 dưới dạng một lần hẹn giờ cho công tắc gỡ lỗi.
Bây giờ, để làm điều này thông qua quan sát với một vi điều khiển.
Tôi thường sử dụng một máy trạng thái để xử lý tranh luận. Điều này hầu như luôn được điều khiển bởi một bộ đếm thời gian "nhịp tim" thông thường mà tôi đặt thành khoảng , nếu có thể. (Tôi thường KHÔNG sử dụng các sự kiện ngắt kích hoạt cạnh vì một số lý do.)số 8bệnh đa xơ cứng
Máy trạng thái trông như thế này:
mô phỏng mạch này - Sơ đồ được tạo bằng CircuitLab
Giá trị DEBOUNCED cho công tắc có thể mang các giá trị "không hoạt động", "hoạt động" và "không xác định". Bằng cách này, bạn có thể đảm bảo rằng phần mềm của bạn sẽ đợi cho đến khi giá trị chuyển đổi lắng xuống sau khi khởi tạo. Nhưng thông thường, tôi không bận tâm với điều đó. Tôi thay thế giá trị "không xác định" bằng một số giá trị mặc định và thay vào đó chỉ sử dụng hệ thống giá trị nhị phân.
Máy trạng thái được nhập bằng cách trước tiên đặt giá trị được gỡ lỗi về mặc định và sau đó nhập trạng thái "THAY ĐỔI" của máy trạng thái. Ở mỗi khoảng thời gian (thường là nếu tôi có thể thoát khỏi nó), tôi sẽ đọc giá trị chuyển đổi hiện tại và thực hiện cập nhật trạng thái hiện tại và có thể, giá trị được gỡ lỗi. Sau đó tôi mới thoát ra. Mã mức cao sau đó chỉ truy cập vào trạng thái được công bố.số 8bệnh đa xơ cứng
Nếu nó quan trọng với tôi, tôi cũng có thể giữ trạng thái được công bố trước đó. Trong những trường hợp này, khi tự cập nhật trạng thái đã phát hành, trước tiên tôi sẽ sao chép trạng thái đó sang 'trạng thái đã được công bố trước'. Sau đó tôi có thể sử dụng cặp giá trị để xác định xem đã có chuyển đổi được công bố chưa. Đôi khi, tôi không quan tâm đến việc chuyển đổi. Đôi khi, tôi làm. Vì vậy, nó phụ thuộc. Nhưng trong mọi trường hợp, tôi chỉ muốn biết về những chuyển đổi đã được công bố. Tôi không bao giờ quan tâm đến việc chuyển đổi runt . Vì vậy, mã mức cao không bao giờ sử dụng bất kỳ trạng thái nội bộ nào mà máy trạng thái sử dụng cho công việc riêng của mình.
Một trong những điều tốt đẹp về phương pháp này là tôi có thể gỡ bỏ toàn bộ cổng chuyển đổi cùng một lúc. Và tôi cũng có thể làm điều đó mà không cần một nhánh trong mã ngắt. Điều này có nghĩa là mã gỡ lỗi rất nhanh và ngắn cho chiều rộng cổng của vi điều khiển (thường rộng 8 bit.) Một ví dụ từ Atmel AT90 cho thấy cách đạt được điều này bằng cách sử dụng sự kiện ngắt Timer0:
.equ SWPORTPINS = PINB
.def SwRawCurr = r4
.def SwRawPrev = r5
.def SwState = r6
.def SwDebCurr = r7
.def SwDebPrev = r8
; Debounce the input switches.
mov SwRawPrev, SwRawCurr
in SwRawCurr, SWPORTPINS
mov Timer0Tmp1, SwRawCurr
eor Timer0Tmp1, SwRawPrev
mov Timer0Tmp0, Timer0Tmp1
or Timer0Tmp1, SwState
mov SwState, Timer0Tmp0
mov Timer0Tmp0, Timer0Tmp1
com Timer0Tmp0
and Timer0Tmp1, SwDebCurr
and Timer0Tmp0, SwRawCurr
or Timer0Tmp1, Timer0Tmp0
mov SwDebPrev, SwDebCurr
mov SwDebCurr, Timer0Tmp1
Bây giờ, ví dụ này hiển thị toàn bộ thỏa thuận, bao gồm các giá trị chuyển đổi được công bố trước đó và hiện tại. Và nó cũng thực hiện tất cả các chuyển đổi trạng thái cần thiết. Tôi không hiển thị việc khởi tạo mã này. Nhưng những điều trên có ý nghĩa về việc máy trạng thái hoạt động dễ dàng như thế nào và cần ít mã để làm như vậy. Nó khá nhanh và đơn giản và không yêu cầu phân nhánh (đôi khi liên quan đến các chu kỳ bổ sung cũng như không gian mã bổ sung.)
Tôi thích sử dụng thời gian vì việc thử nghiệm lâu dài với nhiều người khác nhau sử dụng thiết bị mà tôi đã làm việc trong quá khứ đã đưa tôi đến đó. Tôi đã thử thời gian dài hơn và khi tôi làm như vậy, tôi bắt đầu thấy mọi người nói với tôi rằng "khả năng đáp ứng" không đủ "nhanh". (Ngày nay, với những đứa trẻ lớn lên làm việc chơi game "bắn chúng" theo thời gian thực, tôi thậm chí có thể rút ngắn nó hơn nữa. Chúng sẽ phàn nàn cay đắng về sự chậm trễ thậm chí do TV kỹ thuật số hiện đại gây ra trong việc thiết lập và hiển thị khung hình.)số 8bệnh đa xơ cứng
Một số người sẽ có cảm giác rất rõ ràng về mức độ rõ ràng và phản ứng của một hệ thống. Sắc nét và đáp ứng có nghĩa là mẫu thường xuyên hơn, không ít hơn. Nhưng cá nhân, tôi thấy thời gian quan sát chấp nhận được. (Tuy nhiên, tôi không tìm thấy thời gian đủ tốt ngay cả đối với tôi.)20bệnh đa xơ cứng
Xin lưu ý rằng máy trạng thái mà tôi đã đề cập trước tiên phải nhập trạng thái CÀI ĐẶT và sau đó ở đó thêm một lần nữa trước khi giá trị cho DEBOUNCED được cập nhật. Vì vậy, nhấn một nút và giữ nó, ngay cả trong trường hợp tốt nhất, sẽ yêu cầu các bóng bán dẫn này:
- thay đổi từ THIẾT LẬP sang THAY ĐỔI
- thay đổi từ THAY ĐỔI sang THIẾT LẬP
- ở lại CÀI ĐẶT, cập nhật DEBOUNCED
Vì vậy, một trạng thái mới được công bố đòi hỏi tối thiểu 3 khoảng thời gian mẫu để đạt được.
Một nút ấn sẽ cần ít nhất 6 lần mẫu để chuyển từ không hoạt động, sang hoạt động và sau đó trở lại không hoạt động.
Tôi đã đề cập đến các chi tiết ở trên để hoàn toàn rõ ràng rằng thời gian mẫu là có nghĩa là nó nằm ở đâu đó trong khoảng để đi từ không hoạt động đến một kết quả được công bố hoạt động được công nhận. Và sẽ mất thêm trước khi trạng thái có thể trở lại không hoạt động. Đó là tối thiểu để trải qua toàn bộ chu kỳ nút ấn. 16số 8bệnh đa xơ cứng 2416ms < t ≤ 24bệnh đa xơ cứng 4024bệnh đa xơ cứng40ms <t≤48bệnh đa xơ cứng
Sử dụng thời gian mẫu dài hơn sẽ có thời gian dài hơn tương ứng. Sử dụng Tôi đã đề cập là "chấp nhận được" đối với tôi khi đó có nghĩa là khoảng cho toàn bộ chu kỳ nút ấn . Và đó là nhận thẳng lên vào khu vực nơi người ta có xu hướng thông báo. Tôi chắc chắn không thích "cảm giác" nếu nó dài hơn thế. 10020bệnh đa xơ cứng100ms<t≤120ms
Nếu bạn đi theo con đường này, đừng nên ung dung về việc sử dụng thời gian mẫu dài hơn. Nếu bạn phải, thì tôi nghĩ bạn cũng phải thực hiện nhiều thử nghiệm với người dùng / người tiêu dùng.
Và nếu bạn đang phát triển mã cho bàn phím gõ, thì hãy sử dụng thời gian ngắn hơn. Kỷ lục cho một người đánh máy đã được thiết lập cách đây hàng thập kỷ ở mức 217 wpm. Điều này dẫn đến khoảng một khóa cứ sau . Những người đánh máy như thế đang nhấn nhiều phím theo thứ tự được kiểm soát. Để có được hiệu suất tốt cho những người đánh máy rất nhanh bằng cách sử dụng hệ thống chuyển tiếp rơle sậy ướt thủy ngân, tôi thấy rằng hoạt động tốt. 245ms2ms