arduino - millis ()


8

Sao chép từ tài liệu tham khảo Arduino - millis ()

Mẹo : Lưu ý rằng tham số cho millis là một dấu dài không dấu, có thể được tạo ra nếu lập trình viên cố gắng làm toán với các kiểu dữ liệu khác như ints.

Loại toán nào? Những loại xử lý khác được loại trừ trong khi làm việc với millis?

Ai đó có thể làm rõ tuyên bố này và / hoặc đưa ra một số ví dụ?

Câu trả lời:


8

Bất cứ khi nào bạn viết một phương trình trong C / C ++, các kiểu dữ liệu được vận hành trên có ảnh hưởng rất thực đến đầu ra của phương trình.

Mỗi loại thích int, floatunsigned longcó các hành vi khác nhau và dành một khoảng trống nhất định trong bộ nhớ để lưu trữ.

int . đến + 2 ^ 15-1 (32.767).

unsigned long(trên arduino) là 32 bit, nhưng không có bit nào được chỉ định là âm. phạm vi của nó là 0 đến 2 ^ 32-1 (4294967295).

Loại toán nào? Những loại xử lý khác được loại trừ trong khi làm việc với millis?

Mấu chốt của vấn đề là thời gian quay trở lại đã qua 32767 và bạn đã cố lưu nó trong một int, arduino không thể làm điều đó, bởi vì intkhông thể giữ được con số lớn như vậy. Loại toán học vượt quá giới hạn là toán học xảy ra với các loại dữ liệu nhỏ hơn, không phải bất kỳ hoạt động cụ thể nào. Có thể những ví dụ này sẽ giúp:

  int i = 32767;
  Serial.println(i);
  //No problems here; it fits just fine

32767

  i = 32767 + 1;
  Serial.println(i);
  //Oh no, the value didn't fit

-32768

  unsigned long fake_millis = 42000;
  i = fake_millis;
  Serial.println(i);
  //This is an example of millis going past an int

-23536

  i = -10;
  unsigned int j = i;
  Serial.println(j);
  //no way to put a negative number in an unsigned value

65526

  uint32_t k = fake_millis;
  Serial.println(k);
  //unsigned long is a uint32_t on arduino; this works great!

42000

Cách thức thực hiện này thực sự khá thiên tài; Nếu bạn quan tâm đến việc những con số này đến từ đâu và tại sao chúng lại tràn ra theo cách chúng làm, bạn nên xem xét các giải thích tương tự về biểu diễn số bổ sung của hai.


Chỉ cần một câu hỏi đơn giản: Khai báo "unsained long fake_millis;" bằng với "uint_32 fake_millis;" ?
dùng3060854

Vâng, đó là bằng nhau trên arduino. Sự khác biệt là unsigned longcó thể thay đổi với các nền tảng khác nhau (ví dụ x86), uint32_tsẽ luôn là 32 bit không dấu ở mọi nơi.
BrettAM

1
Cần lưu ý rằng ví dụ thứ hai của bạn ( 32767 + 1) mang lại hành vi không xác định, gần như luôn luôn là một điều xấu . Các ví dụ khác của bạn là hành vi được ghi lại mà bạn có thể dựa vào.
Edgar Bonet

6

millis()trả về a unsigned long, là số nguyên không dấu 32 bit trên Arduino. Sau đó, khi bạn cố gắng làm một cái gì đó như thế unsigned int time = millis() - 1000, bạn cố gắng lưu trữ số đó trong một số nguyên không dấu 16 bit unsigned int. Số nguyên 16 bit không bao giờ có thể giữ giá trị 32 bit.

Theo đặc tả C , đoạn 6.3.1.3, 16 bit trên bị loại bỏ.

Nếu có thể, hãy giữ millis()đầu ra ở dạng a unsigned longvà chỉ sử dụng các loại dữ liệu có ít bit hơn khi bạn chắc chắn rằng mình sẽ không bị mất bit.

Có thêm thông tin về các diễn viên rõ ràng trong C tại đây: https://stackoverflow.com/a/13652624/1544337


Cảm ơn đã chỉnh sửa. Tôi đã xóa tham chiếu đến uint32_t vì nó có gì đó khác biệt. uint32_t đảm bảo rằng bạn có số nguyên không dấu 32 bit, dài không dấu (mặc dù trên Arduino là vậy). Tôi cũng đã đề cập rằng đó là loại 32 bit.

Sau đó, bạn sẽ không nói đúng hơn khi nói nó trả về một uint32_tthứ xảy ra unsigned longtrên arduino chứ?
BrettAM

@BrettAM theo các tài liệu mà hàm này trả về unsigned long.

Loại bỏ các bình luận cũ, vì toàn bộ cuộc thảo luận không có ý nghĩa gì với phiên bản hiện tại của câu trả lời. Chỉ giữ điều này cho bản ghi: nếu chuyển đổi thành số nguyên đã ký ( int time = millis() - 1000), kết quả tương tự: 16 bit trên bị loại bỏ. Lần này, tiêu chuẩn C cho biết kết quả được xác định theo triển khai và hành vi được chỉ định trong tài liệu gcc về hành vi được xác định theo triển khai của số nguyên (điểm đầu dòng thứ tư).
Edgar Bonet

2

Khi bạn muốn làm công cụ với millis (), chỉ cần nhớ khởi tạo biến của bạn với loại "uint32_t"

Vì vậy, hãy làm một cái gì đó như "uint32_t last_millis" nơi bạn sẽ lưu trữ đầu ra của hàm "millis ()".

Nếu không như những người khác nói, nó sẽ tràn ra khi vượt qua 31.000, điều này sẽ xảy ra khá nhanh.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.