Giáo trình Mô đun Lập trình vi điều khiển - Điện công nghiệp
* Port 0
Port 0 là port có 2 chức năng ở các chân 23 – 39 của 8051. Trong các thiết kế cỡ
nhỏ không dùng bộ nhớ mở rộng nó có chức năng như các đường IO. Đối với
các thiết kế cỡ lớn có bộ nhớ mở rộng, P0 là port đa hợp địa chỉ và dữ liệu.
* Port 1
Port 1 là port IO trên các chân 1-8. Các chân được ký hiệu P1.0, P1.1, , .P1.7.
Port 1 được dùng cho giao tiếp và điều khiển với các thiết bị bên ngoài.
* Port 2
Port 2 là port có tác dụng kép trên các chân 21 - 28 được dùng như các đường
xuất nhập hoặc là byte cao của bus địa chỉ đối với thiết kế lớn có mở rộng port
và bộ nhơ mở rộng.
* Port 3
Port 3 là port có tác dụng kép trên các chân 10 - 17. Các chân của port này có
nhiều chức năng, các công dụng chuyển đổi có liên hệ với các đặc tính đặc biệt
của 8051 như ở bảng sau:18
Bit Tên Chức năng chuyển đổi
P3.0 RXT Ngõ vào dữ liệu nối tiếp.
P3.1 TXD Ngõ xuất dữ liệu nối tiếp.
P3.2 INT0\ Ngõ vào ngắt cứng thứ 0.
P3.3 INT1\ Ngõ vào ngắt cứng thứ 1.
P3.4 T0 Ngõ vào của timer/counter thứ 0.
P3.5 T1 Ngõ vào của timer/counter thứ 1.
P3.6 WR\ Tín hiệu ghi dữ liệu lên bộ nhớ ngoài.
P3.7 RD\ Tín hiệu đọc bộ nhớ dữ liệu ngoài.
* Ngõ tín hiệu PSEN (Program store enable)
PSEN là tín hiệu ngõ ra ở chân 29 có tác dụng cho phép đọc bộ nhớ chương
trình mở rộng thường được nói đến chân 0E\ (output enable) của Eprom cho
phép đọc các byte mã lệnh. PSEN ở mức thấp trong thời gian Microcontroller
8051 lấy lệnh. Các mã lệnh của chương trình được đọc từ Eprom qua bus dữ liệu
và được chốt vào thanh ghi lệnh bên trong 8051 để giải mã lệnh. Khi 8951 thi
hành chương trình trong ROM nội PSEN sẽ ở mức logic 1.
* Ngõ tín hiệu điều khiển ALE (Address Latch Enable )
Khi 8051 truy xuất bộ nhớ bên ngoài, port 0 có chức năng là bus địa chỉ và bus
dữ liệu do đó phải tách các đường dữ liệu và địa chỉ. Tín hiệu ra ALE ở chân thứ
30 dùng làm tín hiệu điều khiển để giải đa hợp các đường địa chỉ và dữ liệu khi
kết nối chúng với IC chốt.
Tín hiệu ra ở chân ALE là một xung trong khoảng thời gian port 0 đóng vai trò
là địa chỉ thấp nên chốt địa chỉ hoàn toàn tự động.
Các xung tín hiệu ALE có tốc độ bằng 1/6 lần tần số dao động trên chip và có
thể được dùng làm tín hiệu clock cho các phần khác của hệ thống. Chân ALE
được dùng làm ngõ vào xung lập trình cho Eprom trong 8051.
Trang 1
Trang 2
Trang 3
Trang 4
Trang 5
Trang 6
Trang 7
Trang 8
Trang 9
Trang 10
Tải về để xem bản đầy đủ
Tóm tắt nội dung tài liệu: Giáo trình Mô đun Lập trình vi điều khiển - Điện công nghiệp
y đổi quá trình nấu tương ứng sau đó chấm dứt bằng cách chuyển điều khiển về cho chương trình chính, chương trình chính lại tiếp tục từ nơi bị ngắt. Một điểm quan trọng trong ví dụ này là việc nhập bằng tay xảy ra một cách không đồng bộ có nghĩa là không biết trước hoặc không được điều khiển bằng phần mềm đang chạy trong hệ thống. Đó chính là đặc điễm của ngắt. Hình 23-06-1 Thực hiện chương trình Cờ ngắt xảy ra Trình phục vụ ngắt vectơ ngắt Chương trình hiện hành Cách nhìn ngắn gọn của một chương trình thực thi không có ngắt Cách nhìn ngắn gọn của một chương trình thực thi có ngắt Bắt đầu trình phục vụ ngắt Kết thúc trình phục vụ ngắt 112 2. Tổ chức ngắt Mục tiêu: - Hiểu được cấu tạo các thanh ghi của ngắt - Biết được chuỗi vòng hoạt động của các ngắt - Biết được địa chỉ các thanh ghi ngắt - Ứng dụng các thanh ghi để viết chương trình điều khiển 2.1. Thanh ghi cho phép và không cho phép ngắt Mỗi nguồn ngắt được cho phép hoặc không cho phép thông qua thanh ghi chức năng đặc biệt có các bit được địa chỉ hóa IE (Interrupt Enable) tại địa chỉ 0A8H. Bit Symbol Address Mô tả (1: cho phép, 0: không cho phép) IE.7 EA AFH Cho phép, không cho phép toàn cục IE.6 - AEH Không xác định IE.5 ET2 ADH Cho phép ngắt do timer 2(có ở 8952) IE.4 ES ACH Cho phép ngắt nối tiếp IE.3 ET1 ABH Cho phép ngắt do timer1 IE.2 EX1 AAH Cho phép ngắt do bên ngoài (INT 1) IE.1 ET0 A9H Cho phép ngắt do timer0 IE.0 EX0 A8H Cho phép ngắt do bên ngoài (INT 0) 2.2. Thanh ghi ưu tiên ngắt Khi có nhiều ngắt được cho phép, một trong số các ngắt được chọn ưu tiên cao hơn. Nếu một ngắt được chọn ưu tiên nó sẽ làm cho ngắt khác đang thực thi sẽ tạm dừng cho đến khi trình phục vụ ngắt ưu tiên kết thúc . Trong một tình huống khác, khi hai ngắt xảy ra cùng lúc, ngắt nào có mức ưu tiên cao hơn sẽ làm trước. Ở vi điều khiển 89xxx, một chương trình có sử dụng ngắt được chia làm 3 mức: mức nền (thường cho chương trình chính), mức ngắt và ưu tiên ngắt và chỉ có một ngắt được ưu tiên cao nhất nếu có nhiều ngắt được cho phép. 113 Mỗi một nguyên nhân ngắt riêng rẽ được lập trình để có một trong hai mức ưu tiên thông qua thanh ghi chức năng đặt biệt IP (interrupt priority). Bit Symbo l Bit Address Description (1: ưu tiên, 0: không ưu tiên) IP.7 - - Không sử dụng IP.6 - - Không sử dụng IP.5 ET2 ADH Ưu tiên do ngắt do bộ định thời 2 IP.4 ES ACH Ưu tiên do ngắt do port nối tiếp IP.3 ET1 ABH Ưu tiên do ngắt do bộ định thời 1 IP.2 EX1 AAH Ưu tiên do ngắt do bên ngoài (INT 1) IP.1 ET0 A9H Ưu tiên do ngắt do bộ định thời 0 IP.0 EX0 A8H Ưu tiên do ngắt do bên ngoài (INT 0) 2.3. Chuỗi Pooling Nếu như có nhiều ngắt cùng xuất hiện đồng thời, chuỗi vòng sẽ xác định ngắt nào thực hiện trước. Chuỗi vòng này là: Ngắt ngoài 0, ngắt do bộ định thời 0, ngắt ngoài 1, ngắt do bộ định thời 1, ngắt do port nối tiếp, ngắt do bộ định thời 2. 114 Hình 23-06-2 Cấu trúc ngắt 8051 2.4. Vector ngắt Khi có sự kiện ngắt (Cờ ngắt) xuất hiện, chương trình ngắt bắt đầu một địa chỉ cố định – gọi là vectơ ngắt. Interrupt Flag Interrupt Vector System Reset RST 0000h External 0 IE0 0003H Timer 0 TF0 000BH External 1 IE1 0013H Timer 1 TF1 001BH Serial Port RI, TI 0023H Timer2 TF2 & EXF2 (vđk 8952) 002BH 3. Thiết kế ngắt Mục tiêu:Viết chương trình sử dụng ngắt Dựa vào kích thước của chương trình, ta có 2 mẫu thiết kế như sau: 115 Mẫu thiết kế trình phục vụ ngắt có kích thước nhỏ Org 0000h Ljmp main ; Nhảy qua khỏi đoạn các vectơ ngắt Org 00xxh ISR_xx: ;Trình phục vụ ngắt Reti Org 0030h Main: End Mẫu thiết kế trình phục vụ ngắt có kích thước lớn Org 0000h Ljmp main ; Nhảy qua khỏi đoạn các vectơ ngắt Org 00xxh Ljmp ISR_xx ;vùng khai báo các vecto ngắt và ;dùng l ệnh nhảy đến trình phục vụ ngắt Org 0030h Main: ISR_xx: ; Các trình phục vụ ngắt Reti End 116 4. Ngắt Timer Mục tiêu: - Hiểu được hoạt động của ngắt Timer - Viết chương trình điều khiển sử dụng các ngắt Timer Các ngắt do các bộ Timer xảy ra do sự kiện tràn ở các Timer, khi đó các cờ tràn TF0 hoăc TF1 sẽ được đặt bằng 1. Khi ISR được đáp ứng, các cờ TF0 hoăc TF1 sẽ tự động được xóa bởi phần mềm. 5. Ngắt ngoài Mục tiêu: - Hiểu được hoạt động của ngắt ngoài - Viết chương trình điều khiển sử dụng các ngắt ngoài Các ngắt ngoài xảy ra khi có một mức thấp hoặc cạnh xuống trên chân /INT0 hoặc /INT1 của bộ vi điều khiển. Các cờ tạo ra các ngắt này là bít IE.0 và IE.1 trong thanh ghi TCON, cờ tạo ra ngắt bị xóa bởi phần cứng khi CPU trỏ đến ISR nếu ngắt là loại tác động cạnh, còn đối với ngắt tác động bằng mức thì nguồn tạo ngắt bên ngoài sẻ điều khiển mức của cờ ngắt. Việc chọn lựa ngắt tác động mức thấp hoặc tác động cạnh âm được được lập trình thông qua bít IT0 và IT1 trong thanh ghi TCON. VD: Nếu IT1 = 0 thì ngắt 1 ngoài được kích bởi mức thấp tại chân INT1 và nếu IT1 = 1 thì ngắt này được kích bằng cậnh âm. Trong chế độ này nếu các mẫu tại chân INT1 ở mức cao trong một chu kỳ và ở mức thấp trong các chu kỳ kế tiếp thì cờ IE1 trong TCON được set và sau đó cờ này sẻ yêu cầu một ngắt. Vì các chân ngắt ngoài được lấy mẫu mỗi chu kỳ máy một lần nên ngỏ vào này phải được duy trì ít nhất trong 12 chu kỳ dao động để bảo đãm việc lấy mẫu là thích hợp. Nếu là loại tác động cạnh thì nguồn ngoài phải giữ ở mức cao ít nhất một chu kỳ và ở mức thấp ít nhất một chu kỳ hoặc hơn để bảo đảm nhận ra được sự chuyển mức. IE0 và IE1 được xóa tự động khi CPU trỏ đến ngắt. Nếu ngắt ngoài là loại tác động mức thì nguồn ngoài phải duy trì mức tác động cho đến khi ngắt yêu cầu thực sự được tạo ra. Sau đó phải trở về mức không tác động trước khi ISR hoàn tất hoặc 117 trước khi một ngắt khác được tạo ra. Thông thường một thao tác trong ISR làm cho nguồn tạo ngắt trả tín hiệu ngắt trở về trạng thái không tác động. 6. Ngắt cổng nối tiếp Mục tiêu: - Hiểu được hoạt động của ngắt do cổng nối tiếp - Viết chương trình điều khiển sử dụng ngắt do cổng nối tiếp Các ngắt của cổng nối tiếp xảy ra khi một trong hai cờ ngắt phát TI hoặc cờ ngắt thu RI được set. Ngắt phát xuất hiện khi quá trình phát của ký tự trước đó được viết vào SBUF hoàn tất, một ngắt thu xuất hiện khi một ký tự đã được nhận đầy đủ và đang chờ đọc trong SBUF. Các ngắt cổng nối tiếp khác với các ngắt của timer, cờ tạo ra ngắt cổng nối tiếp không được xóa bằng phần cứng khi CPU trỏ đến véc tơ ngắt lý do là có hai nguồn tạo ra một ngắt cổng nối tiếp đó là TI hoặc RI. Nguồn tạo ra ngắt phải được xác định trong ISR và cờ ngắt được xóa bằng phần mềm. Trở lại với các ngắt timer, cờ ngắt được xóa bằng phần cứng khi CPU trỏ đến ISR THỰC HÀNH VỚI NGẮT I. MỤC TIÊU - Hiểu rõ hơn về tập lệnh của vi điều khiển MCS-51. - Hiểu được hoạt động của ngắt (Interrupt) ở các chế độ khác nhau. - Hiểu được phương pháp lập trình và điều khiển có sử dụng các ngắt. II. NỘI DUNG THÍ NGHIỆM 1. Nối mạch thí nghiệm Ngắt do Timer Chương trình 1 : Viết chương trình tạo sóng vuông tần số f = 5 KHz tại P1.0 dùng ngắt timer 1 (giả sử tần số thạch anh là 12 MHz). 118 2. Viết chương trình điều khiển ORG 0000h LJMP main ORG 001Bh CPL P1.0 ; đảo bit RETI ; trở về chương trình chính từ ISR Main: MOV TMOD,#20h MOV IE,#88h ; Có thể thay thế bằng 2 lệnh sau: ; SETB EA ; SETB ET1 MOV TH1,#(-100) MOV TL1,#(-100) SETB TR1 SJMP $ END 119 Chương trình 2 : Viết chương trình tạo xung vuông tần số f =10KHz tại P1.0 dùng ngắt timer 0 và xung vuông tần số f = 1 KHz tại P1.1 dùng ngắt timer 1. ORG 0000h LJMP main ORG 000Bh CPL P1.0 RETI ORG 001Bh MOV TH1,#HIGH(-500) ; 2 byte MOV TL1,#LOW(-500) ; 2 byte CPL P1.1 ; 2 byte RETI ; 1 byte Main: MOV TMOD,#12h MOV IE,#8Ah SETB TR0 SETB TR1 MOV TH1,#HIGH(-500) 120 MOV TL1,#LOW(-500) MOV TH0,#(-50) MOV TL0,#(-50) SJMP $ END Ngắt ngoài Chương trình 3: Giả sử chân INT1 được nối đến công tắc bình thường ở mức cao. Mỗi khi nó xuống thấp phải bật một đèn LED. Đèn LED được nối đến chân P1.3 và bình thường ở chế độ tắt. Khi nó được bật lên nó phải sáng vài phần trăm giây. Chừng nào công tắc được ấn xuống thấp đèn LED phải sáng liên tục. ORG 0000H LJMP MAIN ; Nhảy đến bảng véc tơ ngắt ; - - Chương trình con ISR cho ngắt cứng INT1 để bật đèn LED. ORG 0013H ; Trình phục vụ ngắt ISR cho INT1 SETB P1.3 ; Bật đèn LED MOV R3, # 235 ; BACK: DJNZ R3, BACK ; Giữ đèn LED sáng một lúc 121 CLR P1.3 ; Tắt đèn LED RETI ; Trở về từ ISR ; - - Bắt đầu chương trình chính Main. ORG 30H MAIN: MOV IE, #10000100B ; Cho phép ngắt dài SJMP HERE ; Chờ ở đây cho đến khi được ngắt END Chương trình 4 Viết chương trình sao cho mỗi khi có mức logic 0 xuất hiện tại P3.2 (ngắt ngoài 0) thì tạo xung 1 KHz tại P1.0. Quá trình tạo xung chỉ dừng khi có mức logic 0 xuất hiện tại P3.3 (ngắt ngoài 1). ORG 0000h LJMP main ORG 0003h ; Địa chỉ ISR ngắt ngoài 0 SETB TR1 ; Timer 1 chạy RETI 122 ORG 0013h ; Địa chỉ ISR của ngắt ngoài 1 CLR TR1 ; Cấm timer 1 RETI ORG 001Bh ; Địa chỉ ISR timer 1 MOV TH1,#HIGH(-500); Chế độ 16 bit nên mỗi lần tràn MOV TL1,#LOW(-500); phải nạp lại giá trị CPL P1.0 ; Đảo bit P1.0 để tạo xung RETI Main: MOV TMOD,#10h MOV TH1,#HIGH(-500) MOV TL1,#LOW(-500) MOV IE,#8Dh ; Cho phép ngắt tại ngắt ngoài 0, 1 và SJMP $ ; timer 1 END Ngắt cổng nối tiếp Chương trình 6 Viết chương trình đếm sản phẩm bằng vi điều khiển 8051 và truyền dữ liệu qua cổng nối tiếp. 123 Chương trình: org 0000h mov tmod,#20h mov scon,#50h mov th1,#0fdh setb tr1 clr tf1 clr ti clr ri mov r7,#0 lap: call delay cpl p1.0 jb p3.7,lap jnb p3.7,$ inc r7 call truyensanpham sjmp lap truyensanpham: mov a,r7 mov b,#10 div ab mov 30h,b mov b,#10 div ab mov 31h,b mov 23h,a mov dptr,#ma movc a,@a+dptr clr ti 124 mov sbuf,a jnb ti,$ mov a,31h movc a,@a+dptr clr ti mov sbuf,a jnb ti,$ mov a,30h movc a,@a+dptr clr ti mov sbuf,a jnb ti,$ clr ti mov sbuf,#0dh jnb ti,$ ret delay: mov 70h,#2 dl1: mov 71h,#235 dl2: mov 72h,#235 djnz 72h,$ djnz 71h,dl2 djnz 70h,dl1 ret ma: db '0123456789',00h end ĐIỀU KHIỂN LCD I. MỤC TIÊU - Hiểu hơn về tập lệnh của vi điều khiển MCS-51. 125 - Biết cách viết các chương trình điều khiển LCD. - Hiểu được sơ đồ và nguyên lý hoạt động của khối LCD trên mô hình thí nghiệm. - Hiểu được nguyên lý và kỹ thuật điều khiển để hiển thị các thông tin trên LCD. - Biết cách viết các chương trình ứng dụng để hiển thị các dạng thông tin khác nhau trên LCD tùy theo nhu cầu sử dụng. II. NỘI DUNG THÍ NGHIỆM 1. Nối mạch thí nghiệm Sơ đồ của LCD1602A: CONST (contrast): chỉnh độ tương phản (độ sáng của hình ảnh trên LCD). - EN (Enable): cho phép đọc/ghi dữ liệu. Trong chế độ đọc, EN tác động bằng xung dương (cạnh lên) và trong chế độ ghi, EN tác động bằng xung âm (cạnh xuống). - RS (register selection): chọn thanh ghi lệnh (RS = 0) hoặc thanh ghi dữ liệu (RS = 1) - R/W: đọc (R/W = 1) hay ghi (R/W = 0) - D7 – D4: bus dữ liệu (chế độ 8 bit: 4 bit cao, chế độ 4 bit: dùng cho truyền 4 bit cao và 4 bit thấp). Ngoài ra, bit D7 còn dùng làm ngõ ra cho cờ Busy. - D3 – D0: 4 bit thấp trong chế độ 8 bit hay bỏ trống trong chế độ 4 bit. - A, K: anode và cathode đèn nền của LCD. Các thành phần chức năng của LCD1602A: - Cờ Busy (BF – Busy flag): Nếu BF = 1, LCD đang trong quá trình thực thi một lệnh. Khi đó, các lệnh gởi tiếp theo sẽ bị bỏ qua. BF được đọc tại chân D7 126 khi RS = 0 và R/W = 1. Do đó, trước khi thực hiện một lệnh, cần kiểm tra BF trước, nếu BF = 0 thì mới gởi lệnh. - DDRAM (Display Data RAM): chứa các ký tự sẽ hiển thị trên LCD, tối đa là 80x8 bit (80 ký tự). Khi hiển thị ở chế độ 1 dòng, địa chỉ của DDRAM có phạm vi từ 00h ÷ 4Fh còn khi ở chế độ 2 dòng, địa chỉ DDRAM từ 00h ÷ 27h cho dòng 1 và 40h ÷ 67h cho dòng 2. - Bộ đếm địa chỉ (AC - Address Counter): dùng để lưu địa chỉ hiện hành của DDRAM và CGRAM, có thể thực hiện đọc AC khi RS = 0 và R/W = 1. - CGROM (Character Genaration ROM): chứa các mô hình ký tự sẽ hiển thị trên LCD, bao gồm 192 ký tự 5x7 theo bảng mã ASCII (nghĩa là khi DDRAM chứa giá trị 41h tương ứng với mã ASCII của ký tự ‘A’ thì trên LCD sẽ hiện ‘A’), trong đó chỉ có các mã từ 00h – 0Fh sẽ không lấy theo mã ASCII mà lấy theo các ký tự đã định nghĩa trong CGRAM. Chương trình 1 Cho sơ đồ kết nối LCD 1602A với AT89C51 như hình vẽ. Viết chương trình hiển thị chuỗi “TRUONG CAO DANG” trên dòng 1 hiển thị chuỗi “NGHE CONG NGHIEP” trên dòng 2. 127 2. Viết chương trình điều khiển DATA_PORT EQU P0 RS BIT P2.0 RW_ BIT P2.1 E BIT P2.2 DB7 BIT P0.7 ORG 00h CALL KHOITAO LOOP: MOV DPTR,#CHUOI1 CALL WRITE_STRING MOV A,#0C0H CALL GHI_LENH MOV DPTR,#CHUOI2 CALL WRITE_STRING JMP $ KHOITAO: MOV A,#038H CALL GHI_LENH MOV A,#0dH CALL GHI_LENH MOV A,#01 CALL GHI_LENH RET WRITE_STRING: MOV R0,#0 WR_LOOP: MOV A,R0 MOVC A,@A+DPTR 128 CJNE A,#00H,NEXT JMP EXIT NEXT: CALL WRITE INC R0 JMP WR_LOOP EXIT: RET WRITE: CALL READY MOV DATA_PORT,A SETB RS CLR RW_ CLR E SETB E RET Ghi_lenh: CALL READY mov DATA_PORT,A clr rw_ clr rs clr e setb e ret READY: MOV DATA_PORT,#0FFH CLR RS SETB RW_ recheck: CLR E 129 SETB E JB DB7,recheck RET CHUOI1: DB 'TRUONG CAO DANG',00H CHUOI2: DB 'NGHE CONG NGHIEP ',00H END Yêu cầu về đánh giá kết quả học tập * Về kiến thức: - Hiểu cấu tạo vi điều khiển 8051. - Ứng dụng bộ định thời để tạo thời gian trễ. - Biết công dụng và cách sử dụng ngắt. - Truyền dữ liệu kiểu nối tiếp. - Giải thích sơ đồ mạch. - Viết chương trình ứng dụng theo yêu cầu. *Về kỹ năng: - Lắp ráp được mạch điều khiển theo sơ đồ có sẵn. - Phân tích được hiện tượng và phán đoán nguyên nhân gây hư hỏng trong mạch điều khiển bằng các thiết bị đo. - Sửa được chương trình điều khiển. * Về thái độ - Nghiêm túc, tích cực, chủ động trong học tập. - Chấp hành nghiêm chỉnh nội quy của xưởng và phòng thực hành vi điều khiển. 130 TÀI LIỆU THAM KHẢO [1]- Tống Văn On, Hoàng Đức Hải, Họ vi điều khiển 8051, NXB Lao đông xã hội, Hà Nội 2005. [2]- Ngô Diên Tập, Lập trình bằng hợp ngữ, NXB Khoa học kỹ thuật, Hà Nội 1998. [3]- Ngô Diên Tập, Vi xử lý trong đo lường và điều khiển, NXB Khoa học kỹ thuật, Hà Nội 1999. [4]- Đỗ Xuân Thụ, Hồ Khánh Lâm, Kỹ thuật vi xử lý và máy tính, NXB Giáo dục, Hà Nội 2000. [5]- Nguyễn Tăng Cường, Phan Quốc Thắng, Cấu trúc và lập trình vi điều khiển, NXB Khoa học kỹ thuật, Hà Nội 2004. [6]- Ngô Diên Tập, Vũ Trung Kiên, Phạm Xuân Khánh, Kiều Xuân Thực, Giáo trình vi xử lý và cấu trúc máy tính, NXB Giáo dục, Hà Nội 2007.
File đính kèm:
- giao_trinh_mo_dun_lap_trinh_vi_dieu_khien_dien_cong_nghiep.pdf