View Full Version : Các bác cho em hỏi về ADC và LCD
pk178
11-11-2009, 10:43 AM
Chào các bác !!!
Vấn đề của em là như thế này, em thấy trong PIC (16f877A), bộ ADC max là 10 bit, tuy nhiên lại có rất nhiều đầu vào analog, các bác thử tư vấn cho em xem có cách nào nâng độ phân giải của ADC lên ko ? Chứ nếu sử dụng bộ ADC ở ngoài thì tốn kém quá, lại lãng phí tài nguyên sẵn có trong PIC.
Em nghĩ nếu mình chia điện áp ở đầu vào analog thành 2, rồi đưa và 2 chân analog, như vậy liệu có nâng được độ phân giải của ADC lên thành 11 bit ko nhỉ ?
Các bác cho em hỏi 1 câu nữa về LCD, em muốn lập trình cho con LCD 20x4, trong CCS có sẵn driver, nhưng nó lại cố định các chân điều khiển LCD rồi, mình ko tác động được, em có down driver từ trên mạng, nhưng khi mô phỏng, thấy chỉ dùng được cho con 16f877, còn với con 16f877A thì chịu, ko bit đây có phải là lỗi của proteus hay ko, vì em chưa thử mạch thực tế nên chưa biết nó có chạy được ko !!!
Nếu bác nào có driver cho lcd 20x4 thì share cho em với nhé. Em xin cảm ơn rất nhiều ạ !
namqn
11-11-2009, 10:47 AM
Chào các bác !!!
Vấn đề của em là như thế này, em thấy trong PIC (16f877A), bộ ADC max là 10 bit, tuy nhiên lại có rất nhiều đầu vào analog, các bác thử tư vấn cho em xem có cách nào nâng độ phân giải của ADC lên ko ? Chứ nếu sử dụng bộ ADC ở ngoài thì tốn kém quá, lại lãng phí tài nguyên sẵn có trong PIC.
Em nghĩ nếu mình chia điện áp ở đầu vào analog thành 2, rồi đưa và 2 chân analog, như vậy liệu có nâng được độ phân giải của ADC lên thành 11 bit ko nhỉ ?
...
Bạn dùng cho mục đích gì mà cần độ phân giải cao hơn 10-bit? Bạn có biết một số PIC18 có bộ ADC 12-bit không?
Thân,
pk178
11-11-2009, 11:29 AM
Em định dùng cho bộ cân điện tử bác ạ !
PIC18 em chưa tìm hiểu , nhưng chắc giá cả đắt hơn con PIC16 nhiều đúng ko ạ ? Em chỉ nghĩ với phần cứng như vậy (con PIC16 ấy), mình làm thế nào để tận dụng hết khả năng của nó, chứ nếu dùng con khác, thì có nhiều cách lắm.
À, bác có driver cho lcd 20x4 ko ạ, bác send cho em với nhé ! Em xin cảm ơn bác rất nhiều ạ !!!
nhanh0112
11-11-2009, 05:38 PM
Driver cho LCD CCS có sẵn thư viện mà bạn. chỉ cần khai báo
#include <lcd.c>//đường dẫn đến driver của thư viện
hoặc
#include "lcd.c" // đường dẫn đến driver nằm cùng thư mục project
sau #use delay là đc
còn định nghĩa cho các chân thì bạn thêm đoạn này vào đoạn đầu của driver lcd.c
#define LCD_ENABLE_ PIN PIN_B3 ////
#define LCD_RS_PIN PIN_B1 ////
#define LCD_RW_PIN PIN_B2 ////
#define LCD_DATA0 PIN_B4 ////
#define LCD_DATA1 PIN_B5 ////
#define LCD_DATA2 PIN_B6 ////
#define LCD_DATA3 PIN_B7 ////
(đã test trên cả proteus và mạch thật với 16F877A)
Nếu bạn nào chưa có (hoặc có nhưng phiên bản khác thì có thể tham khảo) file đính kèm http://www.mediafire.com/?iqzzwmiurtm
(sao diễn đàn ko up đc file nhỉ?!)
Ý tưởng ADC của bạn khá hay nhưng phải làm mạch ngoài và vref khá chính xác
Tui có thể nói lại ý tưởng của bạn như sau:
Chia đôi mức điện áp với Vref bằng mức điện áp chia đôi này giả sử Vref=2.5V
Vậy từ 0-2.5V bạn đưa vào AN0. Từ 2.5 đến 5V bạn đưa vào AN1 (có thể dùng điôt ổn áp hoặc mạch giới hạn để mức điện áp vào từ 2.5-5V đưa vào AN1 cũng là 0 -2.5v)
trong phần mềm... bạn đọc giá trị của AN0 và AN1 rồi cộng dồn... sẽ đc 11bit ngay.
Mạch ngoài cũng khá phức tạp đây :(
pk178
11-11-2009, 06:37 PM
Cám ơn bạn đã cho ý kiến !
Việc chỉnh Vref mình nghĩ có thể dùng 1 con DAC, như vậy chắc điện áp ra chính xác (đây mới chỉ là ý tưởng thôi chứ mình cũng chưa test thử).
Cái file lcd.c của bạn hình như chỉ dùng được cho lcd 2 dòng thôi thì phải, mình đã thử add vào chương trình, nhưng ko hiểu sao nó lại báo lỗi 133 : "Interrupt handler uses too much stack".
Bạn nào biết lỗi này xử lí thế nào ko ? Mình dùng thư viện chuẩn trong ccs thì ok, nhưng cứ dùng thư viện down trên mạng là bị báo lỗi.
Xin cám ơn các bạn rất nhiều !!!
nhanh0112
11-11-2009, 09:21 PM
Xin lỗi vì ko đọc kỹ đầu bài, đó đúng là cho LCD20x2 nhưng nó chạy tốt với 2 dòng mà.
Tui vừa sửa sang lại chút xíu driver LCD gốc để hoạt động cho 4 line (và mới test bằng proteus, chưa làm thử thực tế)
http://www.mediafire.com/?tvjmzfchrxm
#include <16F877A.h>
#fuses XT, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use delay(clock=4000000)
#include "lcd.c"
void main()
{
lcd_init();
lcd_gotoxy(1,1);
lcd_putc("Test LCD");
lcd_gotoxy(1,2);
lcd_putc("nhanh0112");
//lcd_putc("\f");
lcd_gotoxy(1,3);
lcd_putc("pk178");
lcd_gotoxy(1,4);
lcd_putc("picvietnam");
while(TRUE)
{
}
}
và kết quả
http://farm3.static.flickr.com/2681/4095568226_b6f948c205.jpg
pk178
11-11-2009, 09:52 PM
Cám ơn bạn nhé, để mình test xem thế nào đã, thực tế mình cũng hơi lười :D, ngại ko đọc code LCD, nên chỉ lên mạng tìm có code sẵn nào rồi down về thôi :D
pk178
11-11-2009, 10:15 PM
Bạn ạ, cái thư viện đó của bạn chạy tốt khi mình test, nhưng ko hiểu sao cứ add vào cái đoạn code mà mình đang viết là nó lại báo cái lỗi trên :lỗi 133 : "Interrupt handler uses too much stack".
Mình thử bỏ ngắt ngoài (tại chân B0) đi thì ok. Ko hiểu sao có ngắt nó lại ko chạy được.
Bạn biết vì sao ko ? giúp mình với, cảm ơn bạn nhiều nhé !!!
Delfy_Coltech
11-11-2009, 10:41 PM
Bạn ạ, cái thư viện đó của bạn chạy tốt khi mình test, nhưng ko hiểu sao cứ add vào cái đoạn code mà mình đang viết là nó lại báo cái lỗi trên :lỗi 133 : "Interrupt handler uses too much stack".
Mình thử bỏ ngắt ngoài (tại chân B0) đi thì ok. Ko hiểu sao có ngắt nó lại ko chạy được.
Bạn biết vì sao ko ? giúp mình với, cảm ơn bạn nhiều nhé !!!
Cái thông báo lỗi 133 như sau: " Bộ quản lý ngắt sử dụng quá nhiều ngăn xếp"
--> Mình nghĩ nguyên nhân là do chân PB0 đã được định nghĩa dùng cho LCD.
#define LCD_ENABLE_PIN PIN_B2 ////
#define LCD_RS_PIN PIN_B0 ////
#define LCD_RW_PIN PIN_B1 ////
#define LCD_DATA0 PIN_B4 ////
#define LCD_DATA1 PIN_B5 ////
#define LCD_DATA2 PIN_B6 ////
#define LCD_DATA3 PIN_B7
Bạn thử sửa lại cái thư viện LCD xem nhé.
nhanh0112
11-11-2009, 11:03 PM
Bạn ạ, cái thư viện đó của bạn chạy tốt khi mình test, nhưng ko hiểu sao cứ add vào cái đoạn code mà mình đang viết là nó lại báo cái lỗi trên :lỗi 133 : "Interrupt handler uses too much stack".
Mình thử bỏ ngắt ngoài (tại chân B0) đi thì ok. Ko hiểu sao có ngắt nó lại ko chạy được.
Bạn biết vì sao ko ? giúp mình với, cảm ơn bạn nhiều nhé !!!
Nếu bạn sử dụng chân B0 làm ngắt ngoài rồi thì bạn chuyển LCD sang portC hoặc portD đi. Bạn vào trong lcd.c và sửa lại phần định nghĩa chân (PIN_Bx thành PIN_Dx chẳng hạn)
pk178
11-11-2009, 11:20 PM
Cám ơn các bạn đã giúp đỡ !
Mình vừa sửa lại rồi, đổi hết các chân nối với LCD vào cổng D, nhưng nó vẫn báo lỗi như vậy bạn ạ !!!
Đúng là trong ngắt mình có sử dụng hàm của LCD, nhưng mình nghĩ chắc ko ảnh hưởng gì cả, mình dùng thư viện of CCS thì vẫn dùng bình thường mà.
Trong thiết kế of mình, bắt buộc phải sử dụng ngắt, mình ko hiểu lỗi trên là do đâu nữa !!!
Rất mong các bạn giúp đỡ !!!
Delfy_Coltech
11-11-2009, 11:34 PM
Bạn post cái Project lên đây cho mọi người cùng kiểm tra nào!
Thực mục sở thị sẽ dễ bắt lỗi hơn đó. :')
rikimaru87
11-11-2009, 11:42 PM
cho em hỏi tí mọi người .
em dùng 6 kenh ADC trong pic 16f877a.
khi setup_adc_ports(AN0);
.....để đọc gia trị thì ok .
setup_adc_ports(AN1);
CCS báo lỗi không AN1 không dc định nghĩa.
nhưng khi tạo ccs em đã chọn là dùng 6 bộ ADC rùi mà ?
mọi người giúp em với
pk178
11-11-2009, 11:55 PM
Đây là code của mình :
//================================================== ============================
// Project 3
// Author : pk
// Date 26/10/2009
// Description : ...........
/* Function :
- Su dung ngat ngoai RB0 de cho phep viec nhap du lieu
*/
//================================================== ============================
#include <16f877A.h>
#device *=16, ADC = 10
#use delay(clock = 4000000)
//#include <LCD420.c>
//#include <lcd4x20.c>
#include <lcd.h>
#include <keypad_input.c>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use fast_io(d)
#use fast_io(b)
#use fast_io(c)
int32 so_bao; // So bao dat
int khoi_luong; // Khoi luong moi bao
int32 so_bao_ok; // So bao da can xong
//================================================== ============================
void hien_thi_thong_so(){ // Hien thi cac thong so tren LCD
lcd_putc("\f");
lcd_putc("SO LUONG : ");
//lcd_putc("\n");
lcd_put_int(so_bao);
lcd_putc("\n");
lcd_putC("KHOI LUONG : ");
lcd_put_int(khoi_luong);
/* lcd_putc("SO BAO DA XUAT : ");
lcd_put_int(so_bao_ok);
lcd_putc("\n");
//lcd_putc("KHOI LUONG LIEU TRONG THUNG : ");
*/
}
//================================================== ============================
#int_ext
void interrupt_rb0(){
lcd_putc("\f");
//Nhap so bao yeu cau
lcd_putc("SO LUONG : ");
so_bao = input_key();
while(!so_bao){ // Neu khong nhap phim nao => nhap lai
lcd_putc("\f");
lcd_putc("SO LUONG : ");
so_bao = input_key();
}
lcd_putc("\f");
// Nhap khoi luong moi bao
lcd_putc("KHOI LUONG : ");
khoi_luong = input_key();
while(!khoi_luong){ // Neu khong nhap phim nao => nhap lai
lcd_putc("\f");
lcd_putc("KHOI LUONG : ");
khoi_luong = input_key();
}
lcd_putc("\f");
hien_thi_thong_so();
}
//================================================== ============================
void khoi_dong(){
int i;
lcd_init();
lcd_putc("STARTING");
for(i = 1; i < 9; i++){
lcd_putc(".");
delay_ms(100);
}
lcd_putc("\f");
// Nhap gia tri lan dau
lcd_putc("\f");
//Nhap so bao yeu cau
lcd_putc("SO LUONG : ");
// lcd_putc("\n");
so_bao = input_key();
while(!so_bao){ // Neu khong nhan phim nao => nhap lai
lcd_putc("\f");
lcd_putc("SO LUONG : ");
so_bao = input_key();
}
lcd_putc("\f");
lcd_putc("KHOI LUONG :");
// lcd_putc("\n");
khoi_luong = input_key();
while(!khoi_luong){ // Neu khong nhan phim nao => nhap lai
lcd_putc("\f");
lcd_putc("KHOI LUONG :");
//lcd_putc("\n");
khoi_luong = input_key();
}
lcd_putc("\f");
hien_thi_thong_so();
}
//================================================== ============================
void main(){
set_tris_C(0x07);
set_tris_D(0x00);
set_tris_B(0x01);
output_b(0x00);
setup_adc(ADC_CLOCK_DIV_32); // sample time = IC clock
setup_adc_ports(AN0_AN1_AN3); // Set PIN_A0 as analog input 1
enable_interrupts ( int_ext ) ;
enable_interrupts ( global ) ;
khoi_dong();
lcd_putc("\n");
}
//================================================== ============================
Hàm keypad_input là để quyét phím, nó sẽ trả về giá trị sau khi nhập xong !!!
Rất mong được các bạn giúp đỡ. Xin cảm ơn rất nhiều !!!
pk178
12-11-2009, 12:06 AM
cho em hỏi tí mọi người .
em dùng 6 kenh ADC trong pic 16f877a.
khi setup_adc_ports(AN0);
.....để đọc gia trị thì ok .
setup_adc_ports(AN1);
CCS báo lỗi không AN1 không dc định nghĩa.
nhưng khi tạo ccs em đã chọn là dùng 6 bộ ADC rùi mà ?
mọi người giúp em với
Không có định nghĩa setport cho AN1, nếu bạn muốn sử dụng cổng AN1 là cổng vào analog, phải dùng lệnh set_adc_channel(1)
Delfy_Coltech
12-11-2009, 12:10 AM
Nếu bạn gửi kèm cả file mạch mô phỏng để check thì tốt!
Bạn thử chuyển hàm khoidong() lên trước ngat #int_ext xem sao!
(Để hàm ngắt ngay trên hàm main()).
pk178
12-11-2009, 12:20 AM
Đây là mạch mô phỏng của mình :
http://www.mediafire.com/?fkm22z3anye
Cám ơn các bạn đã giúp đỡ !!!
Delfy_Coltech
12-11-2009, 10:32 AM
Rất tiếc! Tớ dùng bản 7.4
Không mở được file của bác. :')
Bác đã tìm ra lỗi chưa zay?
nhanh0112
12-11-2009, 04:30 PM
Đây là mạch mô phỏng của mình :
http://www.mediafire.com/?fkm22z3anye
Cám ơn các bạn đã giúp đỡ !!!
Ko hiểu sao tui thử cái code của bạn với đoạn chương trình con giả lập bù vào phần thư viện còn thiếu của bạn... thì dịch ra chỉ thấy mấy warning thôi, chứ ko thấy error (cảnh báo là do các ngắt chồng chéo thôi!)
char ascii[10]={'0','1','2','3','4','5','6','7','8','9'};
void lcd_put_int(int dulieu)
{
lcd_putc(ascii[dulieu]);
}
int32 input_key()
{
return 1;
}
với cảnh báo sau
>>> Warning 216 "test1.c" Line 157(0,1): Interrupts disabled during call to prevent re-entrancy: (@delay_ms1)
>>> Warning 216 "test1.c" Line 157(0,1): Interrupts disabled during call to prevent re-entrancy: (lcd_send_nibble)
>>> Warning 216 "test1.c" Line 157(0,1): Interrupts disabled during call to prevent re-entrancy: (lcd_send_byte)
>>> Warning 216 "test1.c" Line 157(0,1): Interrupts disabled during call to prevent re-entrancy: (lcd_putc)
>>> Warning 216 "test1.c" Line 157(0,1): Interrupts disabled during call to prevent re-entrancy: (hien_thi_thong_so)
Memory usage: ROM=13% RAM=8% - 15%
0 Errors, 5 Warnings.
có lẽ, bạn thử xem lại phần <keypad_input.c> thử xem
pk178
12-11-2009, 08:56 PM
Cám ơn các bạn rất nhiều !!!
Mình đã thử bỏ thư viện keypad_input.c, đúng là nó chạy được thật, để mình xem lại xem cái thư viện đó sai chỗ nào, nhưng ko hiểu sao mình dùng cái thư viện chuẩn của ccs lại được nhỉ !!!
nhanh0112
13-11-2009, 12:41 AM
cho em hỏi tí mọi người .
em dùng 6 kenh ADC trong pic 16f877a.
khi setup_adc_ports(AN0);
.....để đọc gia trị thì ok .
setup_adc_ports(AN1);
CCS báo lỗi không AN1 không dc định nghĩa.
nhưng khi tạo ccs em đã chọn là dùng 6 bộ ADC rùi mà ?
mọi người giúp em với
Bạn phải viết là:
setup_adc_ports(AN0_ANALOG);
setup_adc_ports(AN1_ANALOG);
.........
hoặc như bạn pk178 đã nói.
@pk178:Chắc do hàm Keypad của bạn có dụng chạm gì đó đến ngắt chính. Bạn có thể viết riêng hoặc tìm trên net về keypad 4x4 mà ko cần dùng ngắt, code cũng khá đơn giản mà. Ko nhất thiết phải dùng đúng thư viện của PIC
pk178
23-11-2009, 11:30 PM
Cám ơn các bạn đã giúp đỡ, vấn đề trên mình đã giải quyết được rồi, tuy ko được như ý muốn, nhưng cũng thực hiện được vấn đề.
Nguyên nhân CCS báo lỗi như vậy là do tràn stack, trong trình phục vụ ngắt dài quá, làm tràn stack, mình đã bỏ hết các hàm con gọi trong ngắt đi, thế là nó chạy ok.
Bây giờ mình lại gặp phải vấn đề này, dịch thì ok rồi, nhưng khi cho vào proteus mô phỏng thì nó cho cảnh báo sau :
"ADC conversion started before 'wait' time has expired following previous conversion or channel change"
Mình thử debug thì thấy nó cảnh báo ở dòng sau :
...
while(a > b){
a= read_adc(); // nó báo ở dòng này
while(!adc_done());
}
.....
Mình nghĩ mãi rồi, ko biết sai chỗ nào nữa, bạn nào biết thì giúp mình với, mình ko biết đưa ra mạch thật thì thế nào, nhưng mô phỏng nó báo vậy, chắc là cũng có vấn đề !
Cám ơn các bạn !
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.