Làm thế nào chức năng shiftOut hoạt động nội bộ? (giải thích về mã nguồn)


7

Tôi đã kiểm tra shiftOut()mã chức năng wiring_shift.cvà tôi hoàn toàn không hiểu những gì đang diễn ra trong chức năng digitalWrite. Tôi thấy !!(val & (1 << i))là lấy giá trị bit từ valnhưng chính xác thì nó hoạt động như thế nào?

Toàn bộ chức năng dưới đây.

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
    uint8_t i;

    for (i = 0; i < 8; i++)  {
        if (bitOrder == LSBFIRST)
            digitalWrite(dataPin, !!(val & (1 << i)));
        else    
            digitalWrite(dataPin, !!(val & (1 << (7 - i))));

        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);        
    }
}

!!(val & (1 << i))là phần phức tạp nhất của mã này. Nếu bạn làm hiểu được điều này, thì phần bạn là những gì không hiểu?
Edgar Bonet

@ edgar-bonet Thật ra đây là câu hỏi. Tôi có thể thấy nó bằng cách nào đó tính toán giá trị bit, nhưng tôi không hiểu làm thế nào nó làm điều này.
wizofwor

Bạn có hiểu hành vi của hàm shiftOut không? Ý tôi là, bạn hiểu rằng đó sẽ shift outlà một giá trị (ở dạng nhị phân). Và sẽ cho một xung đồng hồ cùng với nó.
Paul

Câu trả lời:


9

Tôi sẽ giả sử bitOrder == LSBFIRST.

  • i là số bit, tức là chỉ số của người hướng dẫn của bit tiếp theo để viết
  • 100000001trong nhị phân
  • <<là sự thay đổi toán tử trái. Nó trả về đối số đầu tiên của nó được dịch chuyển sang trái bởi nhiều vị trí như được chỉ ra bởi đối số thứ hai
  • 1<<ilà nhị phân 00000001dịch chuyển sang trái bởi icác vị trí, nghĩa là một cái gì đó giống như 0...010...0, trong đó số 1 ở vị trí thứ i tính từ bên phải (vị trí ngoài cùng bên phải là 0)
  • &là bit bit bitcoin và toán tử, có giá any_bit & 0trị 0 và any_bit & 1any_bit
  • val & (1 << i)0...0(i-th bit of val)0...0ở dạng nhị phân, trong đó bit thứ i của val ở vị trí thứ i của kết quả
  • !! là một phủ định kép: nó chuyển đổi 0 thành 0 và bất kỳ giá trị khác không thành một
  • !!(val & (1 << i)) là 0 hoặc 1 và chính xác là bit thứ i của val

hãy để tôi tóm tắt những gì tôi hiểu. Hãy giả sử val = '10010111'; for i=2 !!(val & (1 << i))= !!('10010111' & '00000100')= !!('00000100')= 1 Nếu tôi là = 3 !!(val & (1 << i))= !!('10010111' & '00001000')= !!('00000000')=0
wizofwor

Chính xác!
Edgar Bonet

Và điều này có nghĩa là nếu tôi cung cấp dữ liệu 16 bit hoặc dài hơn cho shiftOut, nó sẽ gửi 8 bit đáng kể nhất và bỏ qua phần còn lại.
wizofwor

1
shiftOut()lấy uint8_tdữ liệu. Nếu bạn gọi nó bằng đối số 16 bit, trình biên dịch sẽ ngầm loại bỏ 8 bit quan trọng nhất trước khi gọi thực tế đến shiftOut().
Edgar Bonet

1
@SteveMcDonald: Có, đầu ra sẽ giống nhau mà không có phủ định kép, bởi vì digitalWrite() diễn giải bất kỳ giá trị khác không (không chỉ 1) là có nghĩa HIGH. Rõ ràng, tác giả của shiftOut()không muốn dựa vào hành vi này, và thay vào đó muốn luôn luôn gọi digitalWrite()bằng 0 (tức là LOW) hoặc 1 ( HIGH).
Edgar Bonet
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.