Thông tin từ Duck Duck là chính xác nhưng không đầy đủ.
Tôi cần một lượng lớn đầu ra PWM kỹ thuật số để điều khiển tàu sở thích.
Vì vậy, tôi đã kết nối 4 x 74HC595 với At Mega của mình, nó phải được cung cấp với mẫu bit 2 kHz thông qua 0,5 ms. gián đoạn.
Hàm dịch chuyển nối tiếp của tôi chuyển 32 bit vào các thanh ghi mất 562 chúng tôi mỗi chu kỳ. Không thể nào.
Tôi đã tạo một phiên bản tối ưu hóa của DigitalWrite và Read, trong đó có 328 chúng tôi. Bây giờ có thể để PWM với 2 kHz. Thủ thuật là chức năng tối ưu hóa của tôi ghi nhớ 2 Ghim cuối cùng bao gồm bitmasks và outports của nó; và tôi bỏ qua kiểm tra Timer. Đây là chủ đề an toàn. Đối với một kỹ thuật số duy nhất, việc này sẽ mất thêm một chút thời gian. Với việc lặp lại ghi vào datapin và đồng hồ, nó cải thiện Arduino kỹ thuật số tiêu chuẩn với khoảng 42%.
Nhân tiện: Với thư viện digitalWriteFast, kết quả là 45,8, một sự cải tiến thực sự to lớn. Nhưng thư viện này xử lý chỉ ghi, nếu số pin được biết (và do đó cố định!) Tại thời gian biên dịch. Đó không phải là trường hợp với thư viện LiquidCrystal của tôi, trong đó 4 hoặc 8 bit song song được ghi vào tấm chắn thông qua 4 chân nối tiếp.
Tôi đã nhận được kỹ thuật số tối ưu hóa của mình. Chỉ hoạt động cho ứng dụng của tôi, bao gồm cả LiquidDisplay khi tôi sao chép thư viện C: \ Users \ Dell \ Tải xuống \ arduino-1.8.5 \ phần cứng ứng dụng, được gọi là
C: \ Users \ Dell \ Google Drive \ '\' .. .. AppFolder \ library .
Khi tôi thay thế trong cả hai thư mục, hệ thống dây điện tử với phiên bản tối ưu hóa của tôi, nó đã hoạt động.
Tôi không thể có được nó tại nơi làm việc, khi tôi chỉ thay thế hệ thống dây điện tử trong thư viện Arduino (LiquidCrystal đã thực hiện chức năng tiêu chuẩn ở một nơi khác).
Chỉ thêm Wired_digital.c trong thư mục con của ứng dụng của tôi đã tạo ra hàng loạt lỗi liên kết.
Do đó, tôi đã sao chép toàn bộ thư mục Arduino (không lớn) vào thư mục con của tôi trong ứng dụng và nó biên dịch mà không gặp vấn đề gì. Không phải là một giải pháp rất thanh lịch, bởi vì có một bản sao của toàn bộ thư viện; nhưng nó đã có tác dụng.
Kết luận để ghi đè chức năng Arduino lõi:
• Đặt (các) chức năng đã thay đổi của bạn (.c và / hoặc .h) trong thư viện Arduino và sao chép hoàn toàn thư viện này vào "thư viện" thư mục con trong thư mục ứng dụng của bạn. Sau đó, tất cả các thư viện khác cũng sẽ sử dụng chức năng thay đổi của riêng bạn.
Kết luận hiệu suất digitalWrite trong dịch chuyển nối tiếp 32 bit thực:
• Một DigitalWrite và Read được tối ưu hóa dễ dàng vượt trội so với tiêu chuẩn với 42% nếu 2 chân được sử dụng lặp lại. • digitalWriteFast (với các chân xác định tại thời gian biên dịch) vượt trội so với DigitalWrite tiêu chuẩn trong ứng dụng dịch chuyển 32 bit thực với 92% (nhanh hơn 12,2 lần).
Hy vọng điều này sẽ giúp những người dùng Arduino khác.
//**********************
void digitalWrite(uint8_t pin, uint8_t val)
//**********************
{
uint8_t
timer,
bit,
port;
volatile uint8_t *out; // volatile because bitmask may be changed by (higher) interrupt
uint8_t oldSREG;
static uint8_t pin1 = 0,
pin2 = 0;
static bool p1 = true; // boolean toggle memory
static uint8_t // Store 2 sets of port/out adresses static
// timer1, //now exclued. Safety threat?
bit1,
*out1,
// timer2,
bit2,
*out2;
oldSREG = SREG; // CLI for thread proof function
cli();
if ( (pin == pin1) || (pin == pin2) )
{
if (pin == pin1) //Compiler optimizes this excellent (see ASM listing)
{
if (val == LOW)
{
*out1 &= ~bit1;
} else
{
*out1 |= bit1;
}
}
else
if (pin == pin2)
{
if (val == LOW)
{
*out2 &= ~bit2;
} else
{
*out2 |= bit2;
}
}
SREG = oldSREG;
}
else //normal clumsy digitalWrite operation
{
SREG = oldSREG; //Enable interrupts again
timer = digitalPinToTimer(pin);
bit = digitalPinToBitMask(pin);
port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
// if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
if (p1) // Save this port, bit and out, also atomic
{
pin1 = pin;
bit1 = bit;
out1 = out; // save the pointer, not the value
}
else
{
pin2 = pin;
bit2 = bit;
out2 = out; // save the pointer, not the value
}
p1 = !p1;
SREG = oldSREG; //enable interrupts
}
}
//**********************
int digitalRead(uint8_t pin)
//**********************
{
uint8_t
oldSREG,
timer,
bit,
port;
static uint8_t pin1 = 0;
bool readBit;
static uint8_t // Store 2 sets of port/out adresses static
// timer1, //now exclued. Safety threat?
port1,
bit1;
oldSREG = SREG;
cli();
if (pin == pin1)
{
readBit = (*portInputRegister(port1) & bit1);
SREG = oldSREG;
return readBit;
}
else
{
SREG = oldSREG;
timer = digitalPinToTimer(pin);
bit = digitalPinToBitMask(pin);
port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return LOW;
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
// if (timer != NOT_ON_TIMER) turnOffPWM(timer);
oldSREG = SREG;
cli();
pin1 = pin; //Atomic operation pin - bit combi must be correct
bit1 = bit;
port1 = port;
SREG = oldSREG;
if (*portInputRegister(port) & bit) return HIGH;
return LOW;
}
}