Được rồi, tôi đã tìm ra cách để làm chính xác những gì tôi đã hỏi trong câu hỏi mà không liên quan đến WDT.
Đó là một chút hack, để nói rằng ít nhất, và hy sinh hai chân (EDIT: chỉ có một pin được hy sinh) (nhưng không yêu cầu các thành phần bên ngoài, vì vậy nếu bạn có hai chân không sử dụng, nó sẽ là "miễn phí").
Ý tưởng là sử dụng PSMC (Điều khiển chế độ chuyển đổi chế độ) của PIC16F1783.
Điều này có thể được xung nhịp từ INTOSC, bằng cách kết nối HFINTOSC với PLL 4x, mang lại tần số 64 MHz để theo dõi đầu ra của PWM.
Đầu ra PWM sau đó có thể được định tuyến đến một chân khác trên PCB.
Bây giờ, bằng cách sử dụng tinh thể bên ngoài để xung nhịp CPU, tín hiệu PWM có thể được đọc trong một vòng lặp chặt chẽ. Vì hai đồng hồ không được đồng bộ hóa, nên có jitter giữa hai đồng hồ và đầu vào PWM sẽ chứa một số jitter không thể đoán trước.
Trên đường sử dụng jitter này để xây dựng các giá trị ngẫu nhiên có thể có một mảng tổng kiểm tra 16 byte. TMR1 sau đó có thể được cấu hình để chạy nhanh nhất có thể và mỗi khi tín hiệu PWM thay đổi, giá trị TMR1 có thể được ghi vào đầu mảng. Sau đó, tổng MD5 của mảng có thể được lấy và ghi lại vào cùng một mảng.
Bằng cách lặp lại quy trình này vài nghìn lần, hàm băm MD5 16 byte có thể được xây dựng, điều này hoàn toàn ngẫu nhiên.
Tuy nhiên, thuật toán kiểm tra MD5 hầu như không phù hợp với PIC16F1783, do đó, thuật toán này được sử dụng nhiều hơn trên các chip mạnh hơn một chút. Mặc dù vậy, ý tưởng tương tự có thể được sử dụng, chỉ bằng cách tăng một byte theo giá trị TMR1 và để nó bao quanh vài nghìn lần trước khi xem xét nó "đủ ngẫu nhiên".
Cách duy nhất điều này có thể thất bại là nếu nguồn 500kHz bên trong bằng cách nào đó sẽ đồng bộ hóa với bộ dao động tinh thể. Tôi không biết nếu điều đó là có thể.
Cập nhật:
Các mã sau đây dường như hoạt động trong thực tế trong phòng thí nghiệm của tôi:
#define RAND_SIZE 255
unsigned char random_data[RAND_SIZE];
void make_random_data()
{
//Used output pin: RC3. Make sure it is unconnected!
PSMC1PRH=0x0; //choose a very short period period
PSMC1PRL=0x3;
PSMC1DCH=0x00; //set 50% duty
PSMC1DCL=0x2;
PSMC1PHH=0;
PSMC1PHL=0;
PSMC1CONbits.PSMC1EN=1;
PSMC1CLK=1; //64mhz
PSMC1STR0bits.P1STRD=1;
PSMC1OENbits.P1OED=1;
PSMC1PRSbits.P1PRST=1;
PSMC1PHSbits.P1PHST=1;
PSMC1DCSbits.P1DCST=1;
// Zero the id, to make sure any previous value does not influence result.
for(int i=0;i<RAND_SIZE;++i)
random_data[i]=0;
// Generate the new random id:
for(int pass=0;pass<1000;++pass)
{
for(int j=0;j<RAND_SIZE;++j)
{
unsigned char bitmask=1;
for(signed char bitnum=7;bitnum>=0;--bitnum)
{
if (PORTCbits.RC3)
random_data[j] ^= bitmask;
bitmask<<=1;
}
}
}
}
Cập nhật 2:
Chỉ có một chân được hy sinh, vì có thể đọc chân PWM đầu ra, bạn không cần định tuyến nó đến đầu vào và đọc nó.