I.Sơ đồ khối ADC
Bộ chuyển đổi tương tự sang số – ADC (Analog to Digital Converter) lấy mức điện thế vào tương tự sau đó một thời gian sẽ sinh ra mã đầu ra dạng số biểu diễn đầu vào tương tự. Tiến trình biến đổi A/D thường phức tạp và mất nhiều thời gian hơn tiến trình chuyển đổi D/A. Do đó có nhiều phương pháp khác nhau để chuyển đổi từ tương tự sang số. Hình vẽ 5.16 là sơ đồ khối của một lớp ADC đơn giản.
Hoạt động cơ bản của lớp ADC thuộc loại này như sau:
- Xung lệnh START khởi đôïng sự hoạt động của hêï thống.
- Xung Clock quyết định bộ điều khiển liên tục chỉnh sửa số nhị phân lưu trong thanh ghi.
- Số nhị phân trong thanh ghi được DAC chuyển đổi thành mức điện thế tương tự VAX.
- Bộ so sánh so sánh VAX với đầu vào trương tự VA. Nếu VAX < VA đầu ra của bộ so sánh lên mức cao. Nếu VAX > VA ít nhất bằng một khoảng VT (điện thế ngưỡng), đầu dra của bộ so sánh sẽ xuống mức thấp và ngừng tiến trình biến đổi số nhị phân ở thanh ghi. Tại thời điểm này VAX xấp xỉ VA. giá dtrị nhị phân ở thanh ghi là đại lượng số tương đương VAX và cũng là đại lượng số tương đương VA, trong giới hạn độ phân giải và độ chính xác của hệ thống.
- Logic điều khiển kích hoạt tín hiệu ECO khi chu kỳ chuyển đổi kết thúc.
- Tiến trình này có thể có nhiều thay dổi đối với một số loại ADC khác, chủ yếu là sự khác nhau ở cách thức bộ điều khiển sửa đổi số nhị phân trong thanh ghi.
- IC ADC0808 là một vi mạch tích hợp có chức năng chuyển đổi tín hiệu tương tự sang kỹ thuật số (Analog to Digital Converters), độ phân giải của bộ ADC là 8bit tức nó sẽ chuyển đổi tín hiệu điện tương tự sang 256 mức điện áp so với Vref cấp vào bộ chuyển đổi. Các bạn có thể xem datasheet của nó trong tệp đính kèm.
1.Sơ đồ chân
Sau đây chúng ta xem chức năng của từng chân ADC0808:
- IN0-7 – ngõ vào tín hiệu Analog Input
- START – chân điều khiển tín hiệu bắt đầu quá trình biến đổi ADC.
- EOC – Chân phát tín hiệu báo kết thúc quá trình chuyển đổi ADC.
- 2-1 – 2-8 – Ngõ ra Tín hiệu số- Data 8 bit
- OUT EN – Chân cho phép xuất.
- CLK – chân nhận nguồn xung Clock
- Vcc/ GND – Chân nhận điện nguồn dương
- Vref+/ Vref- – Chân nhận(input) điện áp tham chiếu.
- ALE – Address Latch Enable
- ADD A, B, C – Address Input A, B, C (xác định ngõ vào)
Như vậy ADC0808 có tất cả 8 đầu vào Analog, được xác định bởi A, B, C (từ 000 đến 111)! Và chúng ta lưu ý tầm điện áp đầu vào analog là: 0 đến 5v, tương ứng với mức 0 và mức 255 ở đầu ra. Tuy nhiên chúng ta cũng có thể chọn giá trị đầu vào nhỏ hơn mà vẫn có thể chia với độ 255 thông qua việc điều chỉnh điện áp trên chân điện áp tham chiếu Vref, ví dụ 2,55 V.
II.Cảm biến nhiệt độ LM35
LM35 là cảm biến nhiệt độ, đầu ra là tín hiệu điện áp biến đổi theo nhiệt độ, cứ 10mV tương ứng với 1 độ C và giải đo của IC này là -55 độ đến 150 độ C, điện áp cung cấp từ 4-20VDC. Để đo được nhiệt độ âm tức nhỏ hơn 0 ta phải cấp thêm nguồn âm -Vs cho IC:
III.Lập trình giao tiếp ADC0808
Tự động cập nhật giá trị nhiệt độ của LM35 từ ADC0808 rồi hiển thị lên LCD 16×2, tạo xung đồng hồ cho IC ADC0808 sử dụng ngắt timer.
Xây dựng: Xây dựng các hàm giao tiếp LCD và giao tiếp ADC0808:
- LCD16x2:
- LCD_Init() Hàm khởi tạo LCD
- LCD_Clear() Hàm xóa màn hình
- LCD_Gotoxy(X,Y) Hàm trỏ tới vị trí trên màn hình.
- LCD_PutChar(c) Hàm gửi một ký tự ASCII lên LCD.
- LCD_Puts(“String”) Hàm gửi một chuỗi ký tự lên LCD
- ADC0808:
-
- ADC0808_Read(channel) Hàm đọc ADC theo kênh từ 0-7
Và một số hàm khác như delay, tính nhiệt độ, chuyển đổi hiển thị các em xem thêm trong đoạn code phía dưới! Tiếp theo chúng ta sẽ thiết kế mạch kết nối giữa vi điều khiển 8051 và ADC0808.
Với 8051 chúng ta sẽ dùng PORT2 làm port nhập data của ADC808. Chúng ta cần có 3 chân dùng để điều khiển chân đầu vào của tín hiệu vào ADC là P3.2, P3.3, P3.4.
Ngoài ra để có thể điều khiển được quá trình truy xuất/giao tiếp ADC thì chúng ta cũng cần thêm một số chân để kết nối với ADC0808 nữa, cụ thể là:
- Chân EOC của ADC0808 sẽ kết nối với chân P1.4 của 8051
- Chân OE của ADC0808 sẽ kết nối với chân P1.5 của 8051
- Chân LE của ADC0808 sẽ kết nối với chân P1.7 của 8051
- Chân START của ADC0808 sẽ kết nối chung với chân LE
- Nguồn xung clock cấp cho ADC0808 sẽ được tạo ra bởi chính chân P1.6
Một số chân của vi điều khiển lại được cần đến để có thể điều khiển LCD
- Chân E của LCD sẽ được điều khiển bởi chân P3.5 của 8051
- Chân RS của LCD sẽ được điều khiển bởi chân P3.6 của 8051
- Chân RW của LCD sẽ được điều khiển bởi chân P3.7 của 8051
1.Code
/*Do nhiet do dung LM35 va ADC0808 hoac ADC0809*/ #include <REGX52.H> #define VREF 5 //Khai bao chan giao tiep ADC0808 #define ADC0808_DATA P3 #define ADC0808_A P2_0 #define ADC0808_B P2_1 #define ADC0808_C P2_2 #define ADC0808_ALE P2_3 #define ADC0808_START P2_4 #define ADC0808_EOC P2_5 #define ADC0808_OE P2_6 #define ADC0808_CLK P2_7 //Khai bao chan giao tiep LCD16x2 4bit #define LCD_RS P0_0 #define LCD_RW P0_1 #define LCD_EN P0_2 #define LCD_D4 P0_4 //Truyền dữ liệu qua 4 chân #define LCD_D5 P0_5 #define LCD_D6 P0_6 #define LCD_D7 P0_7 /*Hàm đọc và điều khiển ADC0808*/ unsigned char ADC0808_Read(unsigned char channel) { unsigned char kq; ADC0808_A = channel & 0x01; ADC0808_B = channel & 0x02; ADC0808_C = channel & 0x04; ADC0808_ALE = 1; ADC0808_START = 1; ADC0808_ALE = 0; ADC0808_START = 0; while (ADC0808_EOC); while (!ADC0808_EOC); ADC0808_OE = 1; kq = ADC0808_DATA; ADC0808_OE = 0; return kq; } /*Ham delay*/ void delay_us(unsigned int t) { unsigned int i; for (i = 0; i < t; i++); } void delay_ms(unsigned int t) { unsigned int i, j; for (i = 0; i < t; i++) for (j = 0; j < 123; j++); } /*Chương trình giao tiep LCD 16×2 4bit*/ void LCD_Enable(void) { LCD_EN = 1; delay_us(3); LCD_EN = 0; delay_us(50); } void LCD_Send4Bit(unsigned char Data) { LCD_D4 = Data & 0x01; LCD_D5 = (Data >> 1) & 1; LCD_D6 = (Data >> 2) & 1; LCD_D7 = (Data >> 3) & 1; } void LCD_SendCommand(unsigned char command) { LCD_Send4Bit(command >> 4); LCD_Enable(); LCD_Send4Bit(command); LCD_Enable(); } void LCD_Clear() { LCD_SendCommand(0x01); delay_us(10); } void LCD_Init() { LCD_Send4Bit(0x00); delay_ms(20); LCD_RS = 0; LCD_RW = 0; LCD_Send4Bit(0x03); LCD_Enable(); delay_ms(5); LCD_Enable(); delay_us(100); LCD_Enable(); LCD_Send4Bit(0x02); LCD_Enable(); LCD_SendCommand(0x28); LCD_SendCommand(0x0c); LCD_SendCommand(0x06); LCD_SendCommand(0x01); } void LCD_Gotoxy(unsigned char x, unsigned char y) { unsigned char address; if (!y) address = (0x80 + x); else address = (0xc0 + x); delay_us(1000); LCD_SendCommand(address); delay_us(50); } void LCD_PutChar(unsigned char Data) { LCD_RS = 1; LCD_SendCommand(Data); LCD_RS = 0; } void LCD_Puts(char * s) { while ( * s) { LCD_PutChar( * s); s++; } } /*Hiển thị nhiệt độ trên LCD*/ void TempShow(unsigned char z) { LCD_Puts(“Nhiet do :“); LCD_PutChar((z / 100) + 48); // LCD_PutChar((z % 100 / 10) + 48); LCD_PutChar((z % 10) + 48); LCD_Puts(“ * C”); } /*Chương trình ngắt timer 0*/ void INT_Timer0() interrupt 1 { //ctr phuc vu ngat tao xung clock cho ADC0808 ADC0808_CLK = ~ADC0808_CLK; //Dao bit } /*Main Program*/ unsigned char temp; void main() { //Tao xung clock cho ADC0808 – sẽ học sau TMOD = 0x02; TH0 = TL0 = 236; TR0 = 1; ET0 = 1; //Ngat timer0 EA = 1; //Cho phep ngat cuc bo LCD_Init(); //Khoi tao LCD delay_ms(200); LCD_Puts(“Dang do nhiet do…”); delay_ms(1000); LCD_Clear(); LCD_Gotoxy(0, 1); LCD_Puts(“KT.VIXULY– PTIT”); while (1) { LCD_Gotoxy(0, 0); temp = ADC0808_Read(0); TempShow(temp); delay_ms(500); } }
2. Mô phỏng trên Proteus
Danh sách một số thiết bị như sau:
Tại sao ?? temp=ADC0808_Read(0) = ADC0808_DATA.
Giải thích như sau:
Với LM35, nhiệt độ tăng 1 thì điện thế đầu ra tăng 0.01 V. Trong bài này chúng ta không đo được nhiệt độ âm. Chúng ta chỉ đo nhiệt độ từ 0-150, thay vì -55 đến 150 độ C, tức là điện thế đầu ra của LM35 từ 0-1,5 V, cũng chính là Vin của ADC.
Công thức tính điện áp chuyển đổi sang dạng số của ADC:
- ADC0808_DATA = (Vin⁄Vref)*255
- Từ đó tính ra Vin = (ADC0808_DATA * Vref)/255
- Từ đó tính ra nhiệt độ temp = Vin/100
- Khi chúng ta cho Vref = 2,55 V thì kết quả temp = ADC0808_DATA.