Câu trả lời được chấp nhận của jfpoilpret được viết rất tốt, hoàn toàn hợp lệ và trong 99% trường hợp tôi sẽ làm chính xác những gì anh ấy giải thích. Các giải pháp của anh ấy nằm trong các tham số đã xác định của bạn, vì vậy chúng sẽ hoạt động rất tốt. Nhưng cái gì tốt hơn " rất tốt "? Sự hoàn hảo! Rốt cuộc, câu hỏi là về việc tạo ra một giá trị chính xác. Như đã nói đủ gần là tốt trong hầu hết các trường hợp (có thể nói là tất cả), và ngay cả khi xử lý một cái gì đó như đồng hồ khi 1 giây cần 1 giây, bạn vẫn phải chịu những khiếm khuyết bộ phận được thừa hưởng.
Những gì tôi sẽ đề nghị không phải lúc nào cũng có thể. Trong một số trường hợp, điều đó là có thể, nhưng với nhiều rắc rối và nỗ lực hơn trường hợp này. Là nó xứng đáng phụ thuộc vào từng trường hợp. Mục tiêu của tôi chủ yếu là hiển thị một sự thay thế cho các tài liệu tham khảo trong tương lai tốt hơn trong các trường hợp hơi khác. Điều này được viết với người dùng Arduino mới làm quen với việc không có nhiều kinh nghiệm về điện tử.
Đối với những người cao cấp hơn, điều này có lẽ sẽ trông quá dài dòng và chết lặng. Nhưng tôi tin rằng, những người đó có lẽ đã biết và không cần câu trả lời này. Điều này cũng có thể áp dụng cho mọi vi điều khiển và mọi nhà sản xuất và kiến trúc. Nhưng đối với các bộ vi điều khiển khác, bạn sẽ cần tham khảo bảng dữ liệu chính xác để tìm ra các thanh ghi thích hợp và tên và giá trị đặt trước.
Trong trường hợp của bạn, bạn cần một tần số cụ thể và điều tuyệt vời về nó, đó là chính xác 56 kHz thực sự có thể đạt được rất dễ dàng (không tính các khiếm khuyết thực tế của các bộ phận). Vì vậy, đây cũng là một ví dụ hoàn hảo.
Việc tạo tín hiệu phụ thuộc vào bộ định thời và nguồn xung nhịp của vi điều khiển, như được giải thích tốt bởi jfpoilpret. Câu trả lời của anh ấy liên quan đến vấn đề chỉ có một quan điểm và đó là vấn đề với bộ tính giờ. Nhưng bạn cũng có thể sử dụng nguồn đồng hồ, hoặc thậm chí tốt hơn với cả hai cho kết quả tuyệt vời và tuyệt vời. Bằng cách thay đổi các tham số của môi trường, trong trường hợp này là hack hệ thống và thay thế nguồn đồng hồ, chúng ta có thể xử lý một vấn đề cụ thể với nhiều, đơn giản và dễ dàng hơn nhiều.
Trước tiên, để nhắc nhở, vì chuyển đổi trạng thái pin, bạn cần thực thi ISR nhiều hơn hai lần so với tần số tín hiệu. Đây là 112.000 lần mỗi giây. 56.000 và 16.000.000 không cộng dồn rất độc đáo như đã chỉ ra. Chúng ta cần thay đổi tần số tín hiệu hoặc tần số xúc giác. Bây giờ chúng ta hãy giải quyết với tần số tín hiệu bất biến và tìm tốc độ xung nhịp tốt hơn.
Sẽ đơn giản nhất khi chọn một chiếc đồng hồ có độ lớn lớn hơn 56 kHz (hoặc 112 kHz, nhưng thực tế là như vậy), vì bạn chỉ thêm số không và loại toán này là đơn giản nhất đối với hầu hết mọi người. Thật không may, tất cả mọi thứ trên thế giới này là một loại thỏa hiệp với một cái gì đó. Không phải mọi giá trị sẽ làm việc.
Ví dụ đầu tiên là với tốc độ máy phát chiến thuật quá thấp.
Nếu bạn chọn đồng hồ 56.000 Hz, bạn sẽ không thể làm bất cứ điều gì vì bạn sẽ cần gọi ISR mỗi chu kỳ và không thể làm gì khác. Nó hoàn toàn vô dụng. Nếu bạn chọn tốc độ nhanh hơn 10 lần (560 kHz), bạn sẽ có 9 (10 chu kỳ để bộ định thời đạt giá trị tối đa - một chu kỳ để gọi hàm ISR) chu trình vi điều khiển để thực hiện công việc của bạn và điều này hoàn toàn có thể là không đủ. Bạn chỉ đơn giản là thường cần sức mạnh tính toán nhiều hơn.
Nếu bạn chọn một giá trị quá lớn, mặt khác, vì 56 MHz, vi điều khiển đơn giản là không thể làm việc với nó. Đó là cách quá nhanh. Vì vậy, chỉ cần chọn giá trị lớn nhất trong cửa hàng cũng sẽ không cắt giảm.
Arduino Uno R3 nguyên bản có xung nhịp chứng khoán ở mức 16 MHz, do đó, mọi thứ chậm hơn được đảm bảo để hoạt động. Giá trị tiếp theo là một thứ tự cường độ lớn hơn 56 và thấp hơn 16 MHz là 5,6 MHz. Điều này sẽ dẫn đến việc có thể gọi ISR sau mỗi 50 chu kỳ và sẽ tạo ra tần số hẹn giờ 112.000 Hz hoàn hảo. Và tín hiệu của bạn sẽ chính xác là 56 kHz. Bạn sẽ có 49 chu kỳ MCU để thực hiện chương trình của mình giữa các cuộc gọi ISR, nhưng nó vẫn chỉ bằng khoảng 1/3 tốc độ của đồng hồ gốc. Người ta có thể sử dụng 112 làm cơ sở và sử dụng đồng hồ 11,2 MHz và điều này sẽ cung cấp khoảng 2/3 bộ cộng hưởng 16 MHz. Hàm ISR sẽ được gọi sau mỗi 100 chu kỳ và vẫn tạo ra tín hiệu 56 kHz hoàn hảo.
Tuy nhiên, hai vấn đề chính tồn tại với các giá trị này.
Vấn đề đầu tiên phụ thuộc rất nhiều vào nhu cầu của bạn: Bạn hy sinh khoảng 1/3 (với 11,2 MHz) công suất tính toán tối đa của bạn để có được tần số tín hiệu chính xác sử dụng giá trị thanh ghi dễ tìm (OCR iirc ). Bạn có thể ổn với nó hoặc bạn có thể không.
Vấn đề thứ hai là một showstopper khó : Rất dễ tìm thấy các giá trị, nhưng rất thường chúng không tồn tại như một nguồn đồng hồ được sản xuất. Đây là trang web cộng hưởng của Farnell chỉ đơn giản là thiếu cả 5,6 MHz và 11,2 MHz.
Để phá vỡ điều này, chúng ta có thể xem xét các giá trị cộng hưởng có sẵn và tìm ra thứ khác có thể được sử dụng để tạo ra các giá trị mong muốn chính xác. Nếu chúng ta chia 56 cho 4, chúng ta sẽ có 14 và may mắn là có bộ cộng hưởng 14 MHz. Điều này cung cấp cho chúng tôi tốc độ cao hơn và nhiều sức mạnh hơn và với giá trị đăng ký dễ dàng như nhau. Để gọi ISR 112.000 lần mỗi giây, chúng ta cần đặt giá trị thập phân 124 hoặc thập lục phân 0x7C vào thanh ghi OCR, do đó, với việc đếm 124 chu kỳ + 1 để gọi ISR, chúng ta có được giá trị hoàn hảo mong muốn.
Lưu ý
- ISR - thói quen dịch vụ ngắt (đây là mã chỉ được thực thi trên các ngắt được tạo)
- Chương trình của bạn có thể lớn đến mức nào tùy thuộc vào kích thước bộ nhớ! Nó không liên quan gì đến tốc độ đồng hồ và không liên quan gì đến tần suất bạn gọi ISR.
Khi vi điều khiển bắt đầu với lệnh chương trình, bộ đếm được tăng lên. Nếu một ngắt được tạo, ISR được gọi và giá trị này được lưu trữ trong một thanh ghi đặc biệt. Khi mã ISR hoàn thành, giá trị của bộ đếm chương trình được khôi phục từ thanh ghi đặc biệt này và chương trình tiếp tục từ nơi bị gián đoạn như thể nó chưa từng xảy ra.
Tôi sẽ đưa ra một ví dụ cực kỳ ngu ngốc. Nếu bạn là người theo chủ nghĩa thuần túy, tôi cảnh báo bạn: chảy máu mũi và mắt có thể xảy ra.
Hãy tưởng tượng bạn phải đi bộ từ nơi nào đó đến nơi nào đó. Các hướng dẫn lộ trình từng bước là chương trình chính của bạn và các lệnh của nó. Bạn đi bộ hay chạy nhanh như thế nào, tùy thuộc vào "tốc độ đồng hồ" của bạn, nhưng không phụ thuộc vào hướng dẫn lộ trình (30 bước tiến, 1 rẽ 90 độ trái, 10 bước tiến, 45 độ, phải, v.v.) Chúng luôn giống nhau . Bây giờ hãy tưởng tượng một đứa trẻ hoặc một chính trị gia tham nhũng địa phương tham lam cởi giày của bạn bây giờ và sau đó. Đây là sự kiện tạo ra một ngắt. Sau đó, bạn dừng lại sau bước cuối cùng của bạn, quỳ xuống và buộc giày của bạn một lần nữa. Đây là chương trình ISR của bạn.
Sau đó, bạn tiếp tục từ nơi bạn đã dừng lại; bạn không bắt đầu lại từ đầu Khi bạn đi bộ mà không có sự quan tâm trên thế giới và với tất cả thời gian, bạn không quan tâm ngay cả khi bạn phải buộc giày của mình mỗi bước khác. Tuy nhiên, nếu bạn làm điều đó với thời gian hạn chế, như chạy trong 100 mét trên Thế vận hội (hoặc chạy từ một kẻ săn mồi ăn thịt đói), dừng và buộc giày của bạn có thể gây ra hậu quả nghiêm trọng. Điều tương tự là với vi điều khiển. Ngay cả khi bạn chỉ thực thi một dòng mã, chương trình của bạn sẽ tiếp tục, mặc dù chậm. Nếu bạn không quan tâm đến tốc độ, nó sẽ không thành vấn đề. Nếu bạn phải thực hiện một số thời gian liên quan, như sử dụng các hành động phụ thuộc thời gian khác, nhiễu có thể rất không mong muốn và có vấn đề.
Càng đơn giản càng đẹp! Đồng hồ nhanh hơn không phải lúc nào cũng tốt hơn. Các thiết bị có đồng hồ chậm hơn sử dụng ít năng lượng hơn đáng kể. Đây có thể là một điểm quan trọng trong một thiết bị hoạt động bằng pin.
Các chu trình cần thiết được lấy từ công thức này:
(tốc độ xung nhịp / (giá trị bộ đếm trước * tần số gọi ISR cần thiết)) - 1